Поделиться через


TN059. Использование макросов преобразования MFC из MBCS в Юникод

Примечание

Следующее техническое примечание не было обновлено, поскольку сначала оно было включено в электронную документацию.В результате некоторые процедуры и разделы могут быть устаревшими или неверными.Для получения последних сведений рекомендуется выполнить поиск интересующей темы в алфавитном указателе документации в Интернете.

Эта заметка описание использования макросов для преобразования многобайтовых кодировок и юникода, определенных в AFXPRIV.H. Эти макросы наиболее полезны, если приложение обрабатывает непосредственно с OLE API или по какой-либо причине, часто для преобразования между юникод и многобайтовой кодировки.

Обзор

В MFC 3.x, специальные библиотеки DLL использовался (MFCANS32.DLL) автоматически для преобразования и многобайтовой кодировки юникод при интерфейсов OLE вызывались. Эта библиотека DLL были почти прозрачным уровнем, разрешившего приложения OLE записать если OLE и интерфейсы API в многобайтовой кодировке, даже если они всегда юникод (за исключением на macintosh). Хотя этот уровень, удобный и допустимые приложения быстро быть ported из Win16 в Win32 (MFC, Microsoft Word, Microsoft Excel и VBA, только некоторые из приложений Майкрософт, использовать эту технологию), она имела иногда значительно проверки производительности. По этой причине MFC 4.x не использует это библиотека DLL и вместо этого не позволяет непосредственно к интерфейсу OLE юникода. Задаче этого MFC для преобразования в юникод в многобайтовой кодировке звоня к интерфейсу OLE и часто выполняется преобразование из многобайтовой кодировки юникода, реализующий интерфейс OLE. Для обработки данного легко и эффективно несколько созданных макросов, чтобы это преобразование проще.

Одним из самых больших барьеров создать такой набор макросов выделение памяти. Так как строки не могут быть преобразованы на месте, новая память для хранения преобразованные результаты должны распределяться. Это можно сделать с помощью кода, аналогичного следующему:

// 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;

Этот подход как ряд проблем. Основная проблема заключается в том, что многие код для создания, выполнения и отладки. Элемент, был простым вызов функции, теперь гораздо более сложной. Кроме того, значительно рабочей среды выполнения при этом. Память должна быть выбрана в куче и освобождается при каждом преобразование осуществляется. Наконец, в коде выше будет иметь соответствующее #ifdefs добавлены для построения юникода и macintosh (которые не требуется это преобразование соединения).

Решение не обеспечивают вверх с создания некоторые макросы, 1) маска различие между различными платформами, и 2) использовать эффективна схема выделения памяти, и 3) просто для вставки в существующий код источника. Ниже приведен пример одного из определений.

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

С помощью этого макроса вместо приведенный выше действия и намного проще:

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

Дополнительные вызовы, преобразование, но использовать макрос просто и эффективно.

Реализация каждого макроса использует функцию _alloca() для выделения памяти из стека вместо кучи. Выделение памяти из стека намного быстрее, чем выделение памяти в куче и память освобождается автоматически, когда функция останется. Кроме того, макросы во избежание вызова MultiByteToWideChar (или WideCharToMultiByte) больше одного раза. Это делается путем выбора нескольких больше памяти, чем необходимо. Рекомендуется знаем, MBC преобразования в не более одного WCHAR и WCHAR, для каждого мы будем использовать максимум 2 байт MBC. Выбрав окажется необходимое, но всегда достаточно обрабатывать преобразование выполнении второй вызов второй вызов функции преобразования. Вызов вспомогательной функции AfxA2Whelper снижает число аргументов помещает, необходимо сделать для выполнения преобразования (это приводит к уменьшению коде, чем если она вызывает MultiByteToWideChar непосредственно).

Для макросов, чтобы иметь место для хранения временная длина, необходимо объявить локальную переменную с именем _convert, сделать в каждой функции, макросы используются преобразования. Это делается путем вызова макрос USES_CONVERSION, как показано в примере выше.

Макросы и универсальные преобразования OLE и определенные макросы. Эти 2 различных набора макроса рассматриваются ниже. Все макросы находятся в AFXPRIV.H.

Универсальные макросы преобразования

Универсальная форма макросов преобразования основной механизм. Пример макроса и реализация, показанная в предыдущем разделе, A2W, такой «универсальный» макрос. Он не связан с OLE специально. Набор универсальных макросов указаны ниже:

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

Помимо выполнения преобразования текста, также макросов и вспомогательные функции для преобразования TEXTMETRIC, DEVMODE, BSTR и OLE выбранные строки. Эти макросы выходящей за область данного материала — в разделе AFXPRIV.H дополнительные сведения об этих макросах.

Макросы преобразования OLE

Макросы преобразования OLE предназначены специально для обработки функции, ожидающие символов OLESTR. Если нужно просмотреть OLE заголовки, вы увидите большого количества ссылок на LPCOLESTR и OLECHAR. Эти типы используются для обращения к типу символов, используемых в интерфейсах OLE способом, не привязан к платформе. сопоставления OLECHAR в char в платформе macintosh Win16 и и WCHAR в Win32.

Чтобы поддерживать число директив #ifdef в коде MFC до минимума следует как макрос для каждого преобразования OLE, где строки включается. Следующие макросы чаще всего используется:

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

Опять же, как и макросы для получения TEXTMETRIC, DEVMODE, BSTR и OLE выбранные строки. В разделе AFXPRIV.H дополнительные сведения.

Другие вопросы

Не используйте макрос плотном в цикле. Например, не следует использовать следующий тип кода:

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

Приведенный выше код может привести к выбору мегабайты памяти в стеке в зависимости от нужное содержимое строки lpsz ! Он также имеет время преобразования строки для каждой итерации цикла. Вместо этого, переместите эти константы преобразования из цикла:

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

Если строка не является константой, инкапсулируйте вызов метода в функцию. Это позволяет буфер преобразование необходимо освобождать каждый раз. Примеры.

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]);
}

Никогда не возвращает результат одного из макросов, если возвращаемое значение не будет выведен копирования данных перед возвращением. Например, этот код неверны.

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

Приведенный выше код может быть зафиксирован путем изменения возвращаемое значение какого-либо объекта, который копирует значение:

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

Макросы просты в использовании и просто для вставки в код, но как можно говорят из предостережений выше, требуется осторожность при использовании их.

См. также

Другие ресурсы

Технические примечания по номеру

Технические примечания по категории