Uwaga ta opisuje jak używać makr do konwersji MBCS/Unicode, które są zdefiniowane w AFXPRIV.H. tych makr są najbardziej przydatne, jeśli dotyczy aplikacji bezpośrednio z OLE API lub z jakiegoś powodu, często potrzebuje do konwersji między Unicode i MBCS.
Przegląd
W MFC 3.x, wykorzystano special DLL (MFCANS32.Biblioteka DLL) automatycznie konwertować między Unicode i MBCS, gdy interfejsów OLE były nazywane. Ta biblioteka DLL była niemal przezroczysta warstwa, która dopuszcza aplikacji OLE mają być zapisane tak, jakby interfejsów API OLE i interfejsy zostały MBCS, nawet jeśli są one zawsze Unicode (z wyjątkiem komputerów Macintosh). Podczas wygodny tę warstwę i dozwolone aplikacje mogą być szybko przenoszone z Win16 do Win32 (MFC, program Microsoft Word, Microsoft Excel i programu VBA, są tylko niektóre aplikacje firmy Microsoft, które używane tej technologii), miał również czasami znacznie zwiększyć wydajność trafień. Z tego powodu MFC 4.x nie korzysta z tej biblioteki DLL i zamiast opowiadać bezpośrednio interfejsy Unicode OLE. Aby to zrobić, MFC musi dokonać konwersji na Unicode do MBCS podczas wykonywania połączenia z interfejsem OLE i często trzeba przekonwertować do MBCS ze standardu Unicode podczas wykonywania interfejsu OLE. W celu obsługi to efektywne i łatwe, liczba makra zostały utworzone do ułatwienia tej konwersji.
Jednym z największych przez płotki tworzenia takiego zestawu makr jest alokacji pamięci. Ponieważ ciągi nie mogą być przekonwertowane na miejscu, muszą być przydzielone nowa pamięć do przechowywania konwertowanych wyników. Ten mógłby zrobić z kodu podobnego do następującego:
/ / chcemy, aby przekonwertować cią&g MBCS w lpszA
int nLen = MultiByteToWideChar (CP_ACP, 0, lpszA, -1, NULL, NULL);
LPWSTR lpszW = nowe WCHAR [nLen];
MultiByteToWideChar (CP_ACP, 0, lpszA, -1, lpszW, nLen);
/ / Umożliwia wywołanie OLE tutaj
pI BT;SomeFunctionThatNeedsUnicode(lpszW);
/ / wolne ciąg
Usuń [] lpszW
To podejście jako szereg problemów. Głównym problemem jest, że wiele kodu do zapisu, testowania i debugowania. Coś, co było wywołanie funkcji prostego, teraz jest znacznie bardziej skomplikowane. Ponadto istnieje znaczący runtime napowietrznej w ten sposób. Pamięci musi zostać przydzielone na stercie i zwolniona każdorazowo, który odbywa się konwersja. Wreszcie, powyższy kod musiałaby mieć odpowiednie #ifdefs dodanych do kompilacji Unicode i Macintosh, (które nie wymagają tej konwersji na miejsce).
Rozwiązanie, które możemy pojawiły się z jest utworzenie pewne makra, które 1) maski różnica między różnymi platformami i 2) stosowanie systemu alokacji pamięci efektywne i 3) są łatwo wstawić istniejący kod źródłowy. Oto przykład jednego z definicji:
# define A2W(lpa) (\
nbsp; ((LPCSTR) lpa == &NULL)? PUSTY: (\
_convert = (strlen (lpa) + 1), \
AfxA2WHelper((LPWSTR) alloca(_convert*2), lpa, _convert) \
)\
)
Za pomocą tego makra zamiast powyższego kodu i rzeczy są o wiele prostsze:
&/ / Umożliwia wywołanie OLE tutaj
USES_CONVERSION;
pI BT;SomeFunctionThatNeedsUnicode(T2OLE(lpszA))
Istnieją dodatkowe wywołania, gdy konwersja jest konieczne, ale przy użyciu makra jest proste i skuteczne.
Wprowadzenia w życie każdego makra użyto funkcji _alloca() przydzielić pamięci ze stosu zamiast stercie. Przydzielenie pamięci ze stosu jest znacznie szybsze niż przydzielanie pamięci sterty, a pamięć jest automatycznie zwalniana, gdy funkcja jest zakończony. Ponadto makra uniknąć, wywołanie MultiByteToWideChar (lub Procedura WideCharToMultiByte) więcej niż jeden raz. Robi się to przez przydzielenie trochę więcej pamięci niż jest to konieczne. Wiemy, że MBC będzie przekonwertować co najwyżej jeden WCHAR i że dla każdego WCHAR musimy maksymalnie dwa bajty MBC. Poprzez przydzielenie nieco więcej niż niezbędne, ale zawsze wystarczająco do obsługi konwersji drugie wywołanie drugi unika się wywołanie funkcji konwersji. Wywołanie funkcji pomocnik AfxA2Whelper zmniejsza ilość suwów argumentu, które należy wykonać w celu wykonania konwersji (powoduje to kod mniejszych, niż Jeżeli MultiByteToWideChar on wywołany bezpośrednio).
W celu makra mają miejsce do przechowywania tymczasowego długości, należy zadeklarować zmiennej lokalnej o nazwie _convert, który robi to w każdej funkcji, używa makra konwersji. Robi się to wywołując makro USES_CONVERSION , jak pokazano powyżej.
Istnieją rodzajowy konwersja makr i OLE określonego makra. Te dwa zestawy innego makra są omówione poniżej. Wszystkie makra znajdują się w AFXPRIV.H.
Rodzajowy konwersja makra
Makra rodzajowy konwersji formularza mechanizmu leżących u podstaw rozliczeń. Przykład makro i wdrożenia w poprzedniej sekcji, A2W, jest jedno takie makra "ogólny". On nie ma związku OLE specjalnie. Zestaw rodzajowy makra jest wymienione poniżej:
A2CW (LPCSTR) - BT; (LPCWSTR)
A2W (LPCSTR) - > (LPWSTR)
W2CA (LPCWSTR) - > (LPCSTR)
W2A (LPCWSTR) - > (LPSTR)
Poza tym konwersji tekstu, są również makra i funkcje pomocnika do konwertowania TEXTMETRIC, DEVMODE, BSTRi OLE przydzielone ciągi. Te makra są poza zakres niniejszej dyskusji – odnoszą się do AFXPRIV.H więcej informacji na temat tych makr.
OLE konwersja makra
Makra konwersji OLE są zaprojektowane specjalnie do obsługi funkcji, które oczekują, że OLESTR znaków. Jeśli możesz zbadać nagłówki OLE pojawi się wiele odniesień do LPCOLESTR i OLECHAR. Te typy są używane do odwoływania się do typu znaków używanych w interfejsów OLE w sposób, który nie jest specyficzne dla platformy. OLECHAR mapy char na platformach Win16 i Macintosh i WCHAR w Win32.
W celu utrzymania liczbę dyrektyw, #ifdef w kodzie MFC do minimum mamy podobne makro dla każdej konwersji, w przypadku gdy zaangażowane są ciągi OLE. Następujące makra są najczęściej używane:
T2COLE (LPCTSTR) - BT; (LPCOLESTR)
T2OLE (LPCTSTR) - > (LPOLESTR)
OLE2CT (LPCOLESTR) - > (LPCTSTR)
OLE2T (LPCOLESTR) - > (LPCSTR)
Ponownie istnieją podobne makr spowoduje TEXTMETRIC, DEVMODE, BSTRi OLE przyznane ciągi. Odnoszą się do AFXPRIV.H więcej informacji.
Inne względy
Nie należy używać makr w szczelne pętli. Na przykład możesz nie chcesz zapisać następujące rodzaje kodu:
void BadIterateCode(LPCTSTR lpsz)
{
USES_CONVERSION;
dla (int ii = 0; ii lt; 10000; ii ++)
pI - > SomeMethod (ii, T2COLE(lpsz));
}
Powyższy kod może spowodować przydziela&nie megabajtów pamięci na stosie w zależności od tego, jakie zawartość ciąg lpsz jest! nbsp; Bierze również czas, aby przekonwertować ciąg na każdej iteracji pętli. Zamiast przenosić takie stałe konwersje z pętli:
void MuchBetterIterateCode(LPCTSTR lpsz)
{
USES_CONVERSION;
LPCOLESTR lpszT = T2COLE(lpsz);
dla (int ii = 0; ii lt; 10000; ii ++)
pI - > SomeMethod (ii, lpszT);
}
Jeśli ciąg nie jest stała, następnie hermetyzacji wywołanie metody do funkcji. Pozwoli to buforu konwersji na zwolnione za każdym razem. Na przykład:
void CallSomeMethod (int ii, LPCTSTR lpsz)
{
USES_CONVERSION;
pI BT;SomeMethod (ii, T2COLE(lpsz));
}
void MuchBetterIterateCode2 (LPCTSTR * lpszArray)
{
dla (int ii = 0; ii < 10000; ii ++)
CallSomeMethod (ii, lpszArray[ii]);
}
Nigdy nie zwraca wynik jedno z makr, chyba że wartość zwracany pociąga za sobą kopii danych przed ich zwrotu. Na przykład kod ten jest zły:
LPTSTR BadConvert(ISomeInterface* pI)
{
USES_CONVERSION;
LPOLESTR lpsz = NULL;
pI BT;GetFileName(&lpsz);
LPTSTR lpszT = OLE2T(lpsz);
CoMemFree(lpsz);
Zwraca lpszT; / / bad! zwracanie pamięci alloca
}
Powyższy kod można by ustalić zmieniając wartość zwracany do czegoś, która kopiuje wartość:
CString BetterConvert(ISomeInterface* pI)
{
USES_CONVERSION;
LPOLESTR lpsz = NULL;
pI BT;GetFileName(&lpsz);
LPTSTR lpszT = OLE2T(lpsz);
CoMemFree(lpsz);
Zwraca lpszT; / / CString tworzy kopię
}
Makra są łatwe w użyciu i łatwo wstawić w kodzie, ale jak widać z powyższego ostrzeżenia, trzeba należy zachować ostrożność przy ich.
Uwagi techniczne przez liczbę |nbsp; Uwagi techniczne według kategorii