Цієї записці описується використання макросів для Азійських/Юнікод перетворення, які визначаються в AFXPRIV.H. ці макроси є найбільш корисна, якщо ваші пропозиції застосування безпосередньо з OLE API або з деяких причин, часто необхідно перетворити Unicode та Азійських.
Огляд
В 3. x MFC, використовується спеціальний DLL (MFCANS32.Бібліотеку DLL), щоб автоматично перетворити Unicode та Азійських під OLE інтерфейсів називалися. Цієї DLL була майже прозорий шар, що дозволило додатків OLE повинна бути написана як ніби OLE API та інтерфейсів Азійських, навіть якщо вони завжди Юнікод (за винятком на комп'ютері Macintosh). Хоча цей шар був зручний і дозволяється додатків буде швидко перенести з Win16 для Win32 (MFC, Microsoft Word, Microsoft Excel і VBA, є лише деякі з додатками Microsoft, що використовував цю технологію), він також був іноді значні продуктивність хіт. З цієї причини MFC 4. x не підтримує цієї DLL і замість цього переговори безпосередньо до Unicode OLE інтерфейсів. Для цього MFC необхідно перетворити на Юнікод MBCS при здійсненні дзвінка до інтерфейсу OLE і часто необхідно перетворити MBCS від Юнікоду, при реалізації інтерфейсу OLE. Для того, щоб впоратися з цією ефективно і легко, ряд макросів були створені, щоб полегшити цей перетворення.
Один з найбільших бар'єрів створення набір макросів, виділення пам'яті. Оскільки строк не може бути перетворено на місці, нові пам'яті провести перетворені результати повинні бути виділені. Це можна було б зробити з кодом, подібні до таких:
/ / Ми хочемо перетворити на Азійських рядок у lpszA
Int nLen = MultiByteToWideChar (CP_ACP, 0, lpszA, -1, NULL, NULL);
LPWSTR-lpszW = новий WCHAR [nLen];
MultiByteToWideChar (CP_ACP, 0, lpszA, -1, lpszW, nLen);
/ / використовувати його називати OLE тут
Пі >SomeFunctionThatNeedsUnicode(lpszW);
/ / вільний рядок
видалити [] lpszW
Такий підхід, як кількість проблем. Основною проблемою є те, що багато коду, щоб написати, тестування та налагодження. Те, що був виклик проста функції, є набагато більш складною. Крім того, існує значний час виконання накладні витрати в цьому. Пам'ять повинна бути виділені в купі і звільнений під час кожного перетворення робиться. Нарешті, код вище б необхідно мати відповідні #ifdefs додано для кодування Юнікод і Macintosh будує, (які не потребують цього перетворення).
Рішення, ми прийшли з є створення деякі макроси, 1) маска різниця між різних платформ і 2) використання схеми розміщення ефективний пам'яті і 3) є легко вставити в існуючих вихідним кодом. Ось приклад того, одне з визначень:
# визначити A2W(lpa) (\
nbsp; ((LPCSTR) lpa = = &NULL)? NULL: (\
_convert = (strlen (lpa) + 1), \
AfxA2WHelper((LPWSTR) alloca(_convert*2), lpa, _convert) \
)\
)
Використовуючи цей макрос замість того, щоб код вище і речей є набагато простіше:
/ / використовувати його називати OLE тут
USES_CONVERSION;
Пі >SomeFunctionThatNeedsUnicode(T2OLE(lpszA))
Існують додаткові дзвінки, де перетворення є необхідним, але використання макросів є простим і ефективним.
Виконання кожного макросу використовується функція _alloca() виділити пам'ять зі стосу замість того, щоб купу. Виділення пам'яті зі стосу, набагато швидше, ніж виділення пам'ять в купі, і пам'ять звільняється автоматично, коли вийшов функції. Крім того, макроси уникнути, що закликають MultiByteToWideChar (або WideCharToMultiByte) більше, ніж один раз. Це робиться шляхом розподілу трохи більше пам'яті, ніж це необхідно. Ми знаємо, що є на МБК буде конвертувати в більше одного WCHAR і що для кожного WCHAR нас максимум два байти на МБК. Шляхом розподілу трохи більше, ніж потрібно, але завжди достатньо для обробки перетворення другий виклик другий виклик функції перетворення уникнути. Заклик до допоміжні функції AfxA2Whelper зменшує кількість штовхає аргумент, що потрібно зробити, щоб виконати перетворення (це призводить до менших код, ніж якщо вона називається MultiByteToWideChar безпосередньо).
Щоб макросів мати простір для зберігання на тимчасове довжини, варто оголосити локальної змінної, називається _convert, що робить це в кожної функції, що використовує перетворення макросів. Це робиться шляхом застосування USES_CONVERSION макрос, як показано у прикладі вище.
Є загальним перетворення макросів і конкретні макроси OLE. Ці два набори різних макросів розглядаються нижче. Всі макроси містяться в AFXPRIV.H.
Загальний перетворення макросів
Загальний перетворення макросів форми основний механізм. Макрос приклад і впровадження показано в попередньому розділі, A2W, це один такий "Загальні" макрос. Це не має відношення до OLE конкретно. Набір загальних макросів, перерахованих нижче:
A2CW (LPCSTR) - gt; (LPCWSTR)
A2W (LPCSTR) - > (LPWSTR)
W2CA (LPCWSTR) - > (LPCSTR)
W2A (LPCWSTR) - > (LPSTR)
Крім того, що роблять перетворення тексту, є також макроси та допоміжні функції для перетворення TEXTMETRIC, DEVMODE БУЛта OLE виділені рядки. Ці макроси виходять за рамки обговорення-зверніться до AFXPRIV.H більш докладну інформацію про ці макроси.
OLE: Перетворення макросів
Перетворення макросів OLE призначені спеціально для обробки функцій, які очікують OLESTR символів. Якщо ви перевірте заголовки OLE, ви побачите багато посилань на LPCOLESTR і OLECHAR. Ці типи використовуються для позначення типу символи використовуються в OLE інтерфейсів таким чином, що не специфічні для платформи. OLECHAR карти char в Win16 і Macintosh платформ та WCHAR в Win32.
Щоб зберегти номер #ifdef директиви в коді MFC до мінімуму ми повинні аналогічні макросу для кожного перетворення, де OLE рядки що беруть участь. Найбільш часто використовуються такі макроси:
T2COLE (LPCTSTR) - gt; (LPCOLESTR)
T2OLE (LPCTSTR) - > (LPOLESTR)
OLE2CT (LPCOLESTR) - > (LPCTSTR)
OLE2T (LPCOLESTR) - > (LPCSTR)
Знову є аналогічні макроси для цього TEXTMETRIC, DEVMODE, БУЛі OLE виділених рядків. Зверніться до AFXPRIV.H для отримання додаткової інформації.
Інші міркування
Не використовувати макроси в цикл. Наприклад, ви не хочете написати такого виду коду:
недійсним BadIterateCode(LPCTSTR lpsz)
{
USES_CONVERSION;
для (int ii = 0; ii lt 10000; ii + +)
Пі - > SomeMethod (ii, T2COLE(lpsz));
}
Код вище може призвести до розподілу мегабайт пам'яті в стеку, залежно від того, що вміст рядка lpsz є! Також потрібен час, щоб перетворити рядок для кожної ітерації цикл. Замість переміщення таких постійна переходи з петлі:
недійсним MuchBetterIterateCode(LPCTSTR lpsz)
{
USES_CONVERSION;
LPCOLESTR-lpszT = T2COLE(lpsz);
для (int ii = 0; ii lt 10000; ii + +)
Пі - > SomeMethod (ii, lpszT);
}
Якщо рядок не є постійним, потім інкапсуляції метод виклик функції. Це дозволить буфер перетворення, щоб бути звільнені кожного разу. Наприклад:
недійсним CallSomeMethod (int ii, LPCTSTR lpsz)
{
USES_CONVERSION;
Пі gt;SomeMethod (ii, T2COLE(lpsz));
}
втрати MuchBetterIterateCode2 (LPCTSTR * lpszArray)
{
для (int ii = 0; ii < 10000; ii + +)
CallSomeMethod (ii, lpszArray[ii]);
}
Ніколи не повернутися у результаті однієї з макросами, якщо значення має на увазі прийняття копію даних до повернення. Наприклад, цей код буде погано:
LPTSTR BadConvert(ISomeInterface* pI)
{
USES_CONVERSION;
LPOLESTR-lpsz = NULL;
Пі gt;GetFileName(&lpsz);
LPTSTR-lpszT = OLE2T(lpsz);
CoMemFree(lpsz);
повернення lpszT; / / погано! повернення alloca пам'ять
}
Код вище, можуть бути встановлені шляхом зміни значення, що повертається до чогось копіювання значення:
CString BetterConvert(ISomeInterface* pI)
{
USES_CONVERSION;
LPOLESTR-lpsz = NULL;
Пі gt;GetFileName(&lpsz);
LPTSTR-lpszT = OLE2T(lpsz);
CoMemFree(lpsz);
повернення lpszT; / / CString копію
}
Вони прості у використанні і легко вставити у ваш код, але як ви можете сказати з застереженнями, вище, ви повинні бути обережні при використанні їх.
Технічні примітки за номером |nbsp; Технічні примітки за категоріями