Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
WinAPI.docx
Скачиваний:
49
Добавлен:
16.12.2018
Размер:
3.43 Mб
Скачать

5.8.7 Ресурсы

Компилятор ресурсов генерирует двоичное представление всех ресурсов, используемых Вашей программой. Строки в ресурсах (таблицы строк, шаблоны диалоговых окон, меню и др.) всегда записываются в Unicode.

5.8.8 Текстовые файлы

Далеко не все текстовые файлы представлены в кодировке Unicode. Многим приложениям, которые открывают и обрабатывают текстовые файлы (например, компиляторам), было бы удобнее, если после открытия файла можно было бы определить, содержит он символы в ANSI или в Unicode. B этом может помочь функция IsTextUnicode:

DWORD IsTextUnicode(CONST PVOID pvBuffer, int cb, PINT pResult);

Проблема с текстовыми файлами в том, что не существует четких и строгих правил относительно их содержимого. Это крайне затрудняет определение того, содержит файл символы в ANSI или в Unicode. Поэтому IsTextUnicode применяет набор статистических и детерминистских методов для того, чтобы сделать взвешенное предположение о содержимом буфера. Поскольку тут больше алхимии, чем точной науки, нет гарантий, что Вы не получите неверные результаты от IsTextUnicode.

Первый ее парамегр, pvBuffer, указывает на буфер, подлежащий проверке. При этом используется указатель типа void, поскольку неизвестно, в какой кодировке данный массив символов.

Параметр cb определяет число байтов в буфере, на который указывает pvBuffer. Так как содержимое буфера не известно, сb - счетчик именно байтов, а не символов. Заметьте: вовсе не обязательно задавать всю длину буфера. Но чем больше байтов проанализирует функция, тем больше шансов получить правильный результат.

Параметр pResult — это адрес целочисленной переменной, которую надо инициализировать перед вызовом функции. Ее значение сообщает, какие тесты должна провести IsTextUnicode. Если pResult равен NULL, функция IsTextUnicode делает все проверки. (Подробнее об этом см. документацию Platform SDK.)

Функция возвращает TRUE, если считает, что буфер содержит текст в Unicode, и FALSE — в ином случае. Да-да, она возвращает именно булево значение, хотя в прототипе указано DWORD. Если через целочисленную переменную, на которую указывает pResuIt, были запрошены лишь определенные тесты, функция (перед возвратом управления) устанавливает ее биты в соответствии с результатами этих тестов.

5.8.9 Перекодировка строк из Unicode в ansi и обратно

Windows-функция MultiByteToWideChar преобразует мультибайтовые символы строки в широкобайтовые:

int MultiByteToWideChar( UINT uCodePage, DWORD dwFlags, PCSTR pMultiByteStr, int cchMultiByte, PWSTR pWideCharStr, int cchWideChar);

Параметр uCodePage задает номер кодовой страницы, связанной с мультибайтовой строкой. Параметр dwFlags влияет на преобразование букв с диакритическими знаками. Обычно эти флаги не используются, и dwFlags равен 0. Параметр pMultiByteStr указывает на преобразуемую строку, a cchMultiByte определяет ее длину в байтах Функция самостоятельно определяет длину строки, если cchMultiByte равен -1.

Unicode-версия строки, полученная в результате преобразования, записывается в буфер по адресу, указанному в pWideCharStr. Максимальный размер этого буфера (в символах) задается в параметре cchWideCbar. Если он равен 0, функция ничего не преобразует, а просто возвращает размер буфера, необходимого для сохранения результата преобразования. Обычно конверсия мультибайтовой строки в ее Unicode-эквивалент проходит так:

1. Вызывают MultiByteToWideChar, передавая NULL в параметре pWideCharStr и 0 в параметре cchWideChar. 2. Выделяют блок памяти, достаточный для сохранения преобразованной строки. Его размер получают из предыдущего вызова MultiByteToWideChar.

3. Снова вызывают MultiByteToWideChar, на этот раз передавая адрес выделенного буфера в параметре pWideCharStr, а размер буфера, полученный при первом обращении к этой функции, — в параметре cchWideChar. 4. Работают с полученной строкой. 5. Освобождают блок памяти, занятый Unicode-строкой.

Обратное преобразование выполняет функция WideCharToMultiByte

int WideCharToMultiByte( UINT uCodePage, DWORD dwFlags, PCWSTR pWideCharStr, int cchWideChar, PSTR pMultiByteStr, int cchMultiByte, PCSTR pDefaultChar, PBOOL pfUsedDefaultChar);

Она очень похожа на MultiByteToWideChar. И опять uCodePage определяет кодовую страницу для строки — результата преобразования Дополнительный контроль над процессом преобразования дает параметр dwFlags. Его флаги влияют на символы с диакритическими знаками и на символы, которые система не может преобразовать. Такой уровень контроля обычно не нужен, и dwFlags приравнивается 0.

Параметр pWideCharStr указывает адрес преобразуемой строки, a cchWideChar задает ее длину в символах. Функция сама определяет длину исходной строки, если cchWideChar равен -1.

Мультибайтовый вариант строки, полученный в результате преобразования, записывается в буфер, на который указывает pMultiByteStr, Параметр cchMultiByte определяет максимальный размер этого буфера в байтах. Передав нулевое значение в ccbMultiByte, Вы заставите функцию сообщить размер буфера, требуемого для записи результата. Обычно конверсия широкобайтовой строки в мультибайтовую проходит в той же последовательности, что и при обратном преобразовании.

Очевидно, Вы заметили, что WideCharToMultiByte принимает на два параметра больше, чем MultiByteToWideCbar, это pDefauItChar pfUsedDefaultChar. Функция WideCharToMultiByte использует их, только если встречает широкий символ, не представленный в кодовой странице, на которую ссылается uCodePage. Если его преобразование невозможно, функция берет символ, на который указывает pDefaultChar. Если этот параметр равен NULL (как обычно и бывает), функция использует системный символ по умолчанию. Таким символом обычно служит знак вопроса, что при операциях с именами файлов очень опасно, поскольку он является и символом подстановки.

Параметр pfUsedDefaultChar указывает на переменную типа BOOL, которую функция устанавливает как TRUE, если хоть один символ из широкосимвольной строки не преобразован в свой мультибайтовый эквивалент. Если же все символы преобразованы успешно, функция устанавливает переменную как FALSE. Обычно Вы передаете NULL в этом параметре.

Подробнее эти функции и их применение описаны в документации Platform SDK.

Эти две функции позволяют легко создавать ANSI- и Unicode-версии других функций, работающих со строками. Например, у Вас есть DLL, содержащая функцию, которая переставляет все символы строки в обратном порядке. Unicode-версию этой функции можно было бы написать следующим образом.

BOOL StringReverseW(PWSTR pWidoCharStr) { // получаем указатель на последний символ в строке PWSTR pEndOfStr = pWideCharStr + wcslen(pWideCharStr) - 1;

wchar_t cCharT;

// повторяем, пока не дойдем до середины строки while (pWideCharStr < pEndOfStr) { // записываем символ во временную переменную cCharT = *pWideCharStr;

// помещаем последний символ на место первого *pWideCharStr = *pEndOfStr;

// копируем символ из временной переменной на место последнего символа *pEndOfStr = cCharT;

// продвигаемся на 1 символ вправо pWideCharStr++;

// продвигаемся на 1 символ влево pEndOfStr--; }

// строка обращена; сообщаем об успешном завершении return(TRUE); }

ANSI-версию этой функции можно написать так, чтобы она вообще ничем не занималась, а просто преобразовывала ANSI-строку в Unicode, передавала ее в функцию StringReverseW и конвертировала обращенную строку снова в ANSI. Тогда функция должна выглядеть примерно так:

BOOL StringReverseA(PSTR pMultiByteStr) { PWSTR pWideCharStr; int nLenOfWideCharStr; BOOL fOk = FALSE;

// вычисляем количество символов, необходимых // для хранения широкосимвольной версии строки nLenOfWideCharStr = MultiRyteToWideChar(CP_ACP, 0, pMultiByteStr, -1, NULL, 0);

// Выделяем память из стандартной кучи процесса, // достаточную для хранения широкосимвольной строки, // Не забудьте, что MultiByteToWideChar возвращает // количество символов, а не байтов, поэтому мы должны // умножить это число на размер широкого символа. pWideCharStr = HeapAlloc(GetProcessHeap(), 0, nLenOfWideCharStr * sizeof(WCHAR));

if (pWideCharStr == NULL) return(fOk);

// преобразуем нультибайтовую строку в широкосимвольную MultiByteToWideChar(CP_ACP, 0, pMulti8yteStr, -1, pWideCharStr, nLenOfWideCharStr);

// вызываем широкосимвольную версию этой функции для выполнения настоящей работы fOk = StnngReverseW(pWideCharStr);

if (fOk} { // преобразуем широкосимвольную строку обратно в мультибайтовую WideCharToMultiByte(CP_ACP, 0, pWideCharStr, -1, pMultiByteStr, strlen(pMultiByteStr), NULL, NULL); }

// освобождаем память, выделенную под широкобайтовую строку HeapFree(GetProcessHeap(), 0, pWideCharStr);

return(fOk), }

И, наконец, в заголовочном файле, поставляемом вместе с DLL, прототипы этих функций были бы такими:

BOOL StringReverseW (PWSTR pWideCharStr); BOOL StringReverseA (PSTR pMultiByteStr);

#ifdef UNICODE #define StnngReverse StringReverseW #else #define StringRevcrsc StringReverseA #endif // UNICODE

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]