Как запретить приложению, не поддерживающему Unicode, преобразовывать кодировку ресурсов при загрузке их на другой локализованный компьютер? - PullRequest
2 голосов
/ 01 марта 2011

У нас есть не-Unicode, приложение C ++, написанное для Visual Studio, которое изначально было написано для машин, использующих набор символов кодовой страницы 1252.

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

Теперь люди в Китае начинают использовать приложение, а их машины используют локаль PRC (которая устанавливает кодовую страницу по умолчанию для не-Юникодприложения к 936, который является многобайтовым набором символов).

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

То же самое относится к CMenu::GetMenuString или CWnd::GetWindowText.

Достаточно плохо, мы не можемпросто используйте iconv в наших файлах, потому что LoadString, GetMenuString или GetWindowText будут вести себя следующим образом:

  • некоторые символы, допустимые в кодовой странице 1252, недопустимы в кодовой странице 936 ( например î, û, ñ, œ) и заменить на вопросительные знаки
  • некоторые символы, допустимые в кодовой странице 1252, недопустимы в кодовой странице 936 ( например É)но заменяются альтернативным символом (É => é)
  • некоторые символы существуют в обеих кодовых страницах, но не имеют одинакового представления, часто с двумя байтами в CP936
  • некоторые символы (включая всеСимволы ASCII) совпадают в обеих кодовых страницах.

Мне бы хотелось, чтобы эти три функции, которые загружают содержимое ресурса, загружали двоичное содержимое без выполнения какого-либо преобразования набора символов.Я пытался изменить файл .rc с помощью LANGUAGE LANG_INVARIANT, SUBLANG_NEUTRAL, но это ничего не изменило.

Файл ресурсов также включает #pragma code_page(1252);это можно безопасно удалить?Для чего эта прагма?

Спасибо за ваши ответы.

Ответы [ 2 ]

2 голосов
/ 01 марта 2011

Возможно, вы можете использовать BOOL SetThreadLocale( LCID Locale );

MSDN: SetThreadLocale влияет на выбор ресурсов с помощью оператора LANGUAGE.Этот оператор влияет на такие функции, как CreateDialog, DialogBox, LoadMenu, LoadString и FindResource.Он устанавливает кодовую страницу, подразумеваемую CP_THREAD_ACP, но не влияет на FindResourceEx.Для получения дополнительной информации см. Идентификаторы кодовой страницы.

2 голосов
/ 01 марта 2011

Для LoadString очевидное, что нужно сделать, это напрямую вызвать функцию WinStu API API LoadStringW (), которая даст вам строку Unicode напрямую.Это может даже работать, если вы используете CStringW в виде CString, например, (не проверено!)

CStringW str;
str.LoadString(...);

Функции меню и окна создадут больше проблем.Он должен работать для непосредственного вызова Unicode-формы Win32 API GetMenuStringW ().Оконная функция GetWindowText () действительно неудобна: вы можете, конечно, вызвать Win32-функцию GetWindowTextW (), но то, что она будет возвращать, будет зависеть от того, имеет ли окно, в котором вы ее вызываете, оконную процедуру ANSI или Unicode.Если нижележащее окно является элементом управления Windows, то обычно можно получить доступ к соответствующей процедуре окна и вызвать ее напрямую, но это не красиво и не очень весело.

Любой шанс получить более подробную информацию о том, как выпытаясь использовать это?Стоит отметить, что вы перечислите эти функции, как будто все 3 ресурса доступа, но это не так: только LoadString () делает это.Два других работают непосредственно с меню или окном, которое существует в запущенном процессе, а не с ресурсами.

В качестве примера того, как можно обойти проблемы GetWindowTextW (), взгляните на UnicodeEdit класс из этого проекта .Это приложение ANSI, которое необходимо для работы в Windows 9X, но также должно иметь возможность получать текст Unicode из элемента управления редактирования, если это возможно.Хитрость заключается в том, что класс запоминает, была ли оконная процедура до создания подкласса Unicode или ANSI, а если Unicode, вызывает это непосредственно в своем GetWindowText ().В зависимости от того, что вам нужно, такой подход может помочь.

...