Sdílet prostřednictvím


TN059: Převod makra MBCS MFC/Unicode pomocí

[!POZNÁMKA]

Následující technické poznámce nebyly aktualizovány od byla poprvé zahrnuta v dokumentaci online.Proto některé postupy a témata mohou být nesprávné nebo zastaralé.Nejnovější informace je vhodné vyhledat téma zájmu v dokumentaci online index.

Tato poznámka popisuje, jak použít makra pro převod MBCS/Unicode, které jsou definovány v AFXPRIV.H.Tato makra jsou zvláště užitečné, pokud vaše aplikace obchodů přímo s OLE API nebo z nějakého důvodu často potřebuje převést mezi Unicode a MBCS.

Přehled

V MFC 3.x byl použit speciální DLL (MFCANS32.(DLL) při volání rozhraní OLE byly automaticky převést mezi Unicode a MBCS.Tato knihovna DLL byla téměř průhledné vrstvy, která povolené aplikace OLE zapsáno jako kdyby rozhraní API OLE a MBCS, přestože jsou vždy Unicode (s výjimkou v systému Macintosh).Během této vrstvy je pohodlný a povolené aplikace rychle přenést z Win16 a Win32 (MFC, aplikace Microsoft Word, Microsoft Excel a VBA, jsou jen některé aplikace společnosti Microsoft, které používají tuto technologii), měl někdy značného přístupů.Z tohoto důvodu MFC 4.x nepoužívá knihovnu DLL tohoto a místo přímo na rozhraní Unicode OLE kterými uživateli komunikovalo.Chcete-li to provést, MFC potřebuje převést do kódování Unicode do znakové sady MBCS při volání rozhraní OLE a často potřebuje převést do znakové sady MBCS z kódování Unicode při implementaci rozhraní OLE.Chcete zpracovat tento snadno a efektivně, byly vytvořeny počet makra usnadnit tento převod.

Jednou z největších mezní vytváření sady maker je přidělení paměti.Protože řetězce nelze převést na místě, musí držet převedené výsledky nové paměti přidělené.To by byly provedeny s kód podobný následujícímu:

// we want to convert an MBCS string in lpszA
int nLen = MultiByteToWideChar(CP_ACP, 0,lpszA, -1, NULL, NULL);
LPWSTR lpszW = new WCHAR[nLen];
MultiByteToWideChar(CP_ACP, 0, 
   lpszA, -1, lpszW, nLen);
// use it to call OLE here
pI->SomeFunctionThatNeedsUnicode(lpszW);
// free the string
delete[] lpszW;

Tento přístup jako počet problémů.Hlavním problémem je jeho velké zapisovat, testování a ladění kódu.Něco, co bylo volání funkce jednoduché, je mnohem složitější.Režie přitom je navíc významná runtime.Paměť musí být přiděleno haldy a pokaždé, když se provádí převod uvolněno.Nakonec výše uvedený kód by musel mít odpovídající #ifdefs přidané pro Unicode a Macintosh sestavení (vyžadující není tento převod se uskuteční).

Řešení, které jsme obdrželi až s je vytvoření některá makra masky 1) rozdíl mezi různými platformami a 2) použití režimu přidělení paměti pro efektivní a 3) jsou, snadno vložit do existující zdrojový kód.Zde je příklad jedné z definic:

#define A2W(lpa) (\
    ((LPCSTR)lpa == NULL) ? NULL : (\
          _convert = (strnlen(lpa)+1),\
        AfxA2WHelper((LPWSTR) alloca(_convert*2), 
      lpa, _convert)\
    )\
)

Pomocí tohoto makra namísto kódu výše a věci jsou mnohem jednodušší:

// use it to call OLE here
USES_CONVERSION;
pI->SomeFunctionThatNeedsUnicode(T2OLE(lpszA));

Existují další volání, kde přeměny je nezbytné, ale pomocí makra je jednoduchý a účinný.

Provádění každé makro funkce _alloca() přidělení paměti ze zásobníku namísto haldy.Přidělování paměti ze zásobníku je mnohem rychlejší než přidělení haldy v paměti a paměť automaticky uvolněna, jakmile skončí funkce.Kromě toho makra předejít volací MultiByteToWideChar (nebo WideCharToMultiByte) více než jednou.To přidělením mírně více paměti, než je nezbytné.Víme, převede MBC do nejvýše jednu WCHAR a že pro každou WCHAR budeme mít maximálně dva MBC bajtů.Přidělením trochu více než nezbytná, ale vždy dostatečně zpracování převod druhé volání druhé volání funkce převodu se lze vyhnout.Volání funkce Pomocník AfxA2Whelper snižuje počet posune argument, které je třeba provést k provedení převodu (výsledkem kód menší, než-li volán MultiByteToWideChar přímo).

Aby maker místa k uložení dočasné délka je nutné deklarovat používá místní proměnnou s názvem _convert, který toto v každé funkce, Převod makra.Důvodem je vyvolán USES_CONVERSION makro popsané výše v příkladu.

Existují i obecný převod a OLE určitého makra.Tyto dvě sady jiné makro jsou uvedeny níže.Všechna makra jsou umístěny v AFXPRIV.H.

Obecný převod makra

Obecný převod makra formuláře základní mechanismus.Například makro a provádění uvedené v předchozí části A2W, je jedno takové makro "Obecné".Nesouvisí s OLE zvlášť.Sadu maker, obecný, jsou uvedeny níže:

A2CW      (LPCSTR) -> (LPCWSTR)
A2W      (LPCSTR) -> (LPWSTR)
W2CA      (LPCWSTR) -> (LPCSTR)
W2A      (LPCWSTR) -> (LPSTR)

Kromě provedení převodu textu jsou k dispozici také makra a pomocné funkce pro převod TEXTMETRIC, DEVMODE, BSTRa OLE přidělené řetězce.Tato makra jsou nad rámec této diskuse – naleznete na AFXPRIV.H Další informace o těchto maker.

Převod makra OLE

Převod makra OLE určené pro zpracování funkcí, které OLESTR znaků.Pokud přezkoumat OLE záhlaví se zobrazí mnoho odkazů na LPCOLESTR a OLECHAR.Tyto typy se používají k odkazu na typ znaků používaných v rozhraní OLE způsobem, který není specifický pro platformu.OLECHAR mapuje na char v platformy Macintosh, Win16 a WCHAR v systému Win32.

Chcete zachovat počet #ifdef kód směrnic v jednotka MFC minimální máme podobné makro pro každý převod, kde jsou zapojeny OLE řetězce.Nejčastěji se používají následující makra:

T2COLE   (LPCTSTR) -> (LPCOLESTR)
T2OLE   (LPCTSTR) -> (LPOLESTR)
OLE2CT   (LPCOLESTR) -> (LPCTSTR)
OLE2T   (LPCOLESTR) -> (LPCSTR)

Znovu, jsou podobné makra pro tím TEXTMETRIC, DEVMODE, BSTRa OLE přidělené řetězce.Odkazovat na AFXPRIV.H Další informace.

Ostatní úvahy

Makra v těsné smyčky nepoužívejte.Například nechcete zapsat druh následující kód:

void BadIterateCode(LPCTSTR lpsz)
{
   USES_CONVERSION;
   for (int ii = 0; ii < 10000; ii++)
      pI->SomeMethod(ii, T2COLE(lpsz));
}

Výše uvedený kód může vést k přidělení megabajtů paměti na zásobníku v závislosti na tom, jaký obsah řetězce lpsz je!Také dlouho převést řetězec pro každou iteraci smyčky.Místo toho přesunete tyto převody konstantní ze smyčky:

void MuchBetterIterateCode(LPCTSTR lpsz)
{
   USES_CONVERSION;
   LPCOLESTR lpszT = T2COLE(lpsz);
   for (int ii = 0; ii < 10000; ii++)
      pI->SomeMethod(ii, lpszT);
}

Pokud řetězec není konstantní, pak zapouzdřit do funkce volání metody.To umožní vyrovnávací převod na každém uvolnění.Příklad:

void CallSomeMethod(int ii, LPCTSTR lpsz)
{
   USES_CONVERSION;
   pI->SomeMethod(ii, T2COLE(lpsz));
}

void MuchBetterIterateCode2(LPCTSTR* lpszArray)
{
   for (int ii = 0; ii < 10000; ii++)
      CallSomeMethod(ii, lpszArray[ii]);
}

Nikdy vracet výsledek maker, pokud je vrácená hodnota znamená vytvoření kopie dat před návrat.Tento kód je například chybné:

LPTSTR BadConvert(ISomeInterface* pI)
{
   USES_CONVERSION;
   LPOLESTR lpsz = NULL;
   pI->GetFileName(&lpsz);
   LPTSTR lpszT = OLE2T(lpsz);
   CoMemFree(lpsz);
   return lpszT; // bad! returning alloca memory
}

Výše uvedený kód by stanovena změnou vrácenou hodnotu na něco zkopíruje hodnotu:

CString BetterConvert(ISomeInterface* pI)
{
   USES_CONVERSION;
   LPOLESTR lpsz = NULL;
   pI->GetFileName(&lpsz);
   LPTSTR lpszT = OLE2T(lpsz);
   CoMemFree(lpsz);
   return lpszT; // CString makes copy
}

Makra jsou jednoduchá a snadno vložit do kódu však můžete zjistit z výše uvedené upozornění, musíte být opatrní při jejich použití.

Viz také

Další zdroje

Technické poznámky podle čísla

Technické poznámky podle kategorie