开发者

How do I prevent a non-Unicode application to convert charset of resources when loading them on a differently localized machine?

We have a non开发者_运维知识库-Unicode, C++ application, written with Visual Studio, that has been originally written for machines using the codepage 1252 character set.

Our application performs many post-processing steps on the contents of the resources after reading them, including looking up for resource strings in some files.

Now people in China are starting to use the application, and their machines use the PRC locale (which sets the default codepage for non-unicode applications to 936, which is a multibyte character set).

It appears that CString::LoadString will perform some conversion. This breaks further processing because the content that we are looking for in the other files is not the same.

The same goes for CMenu::GetMenuString or CWnd::GetWindowText.

Badly enough, we cannot simply use iconv on our files because LoadString, GetMenuString or GetWindowText will behave this way:

  • some characters which are valid in codepage 1252 are not valid in codepage 936 (e.g. î, û, ñ, œ) and get replaced with question marks
  • some characters which are valid in codepage 1252 are not valid in codepage 936 (e.g. É) but get replaced with an alternate character (É => é)
  • some characters exist in both codepages but do not have the same representation, often with two bytes in CP936
  • some characters (including all ASCII characters) match in both codepages.

I would like that those three functions which load resource contents load the binary content, without performing any character set conversion. I have tried to modify the .rc file with LANGUAGE LANG_INVARIANT, SUBLANG_NEUTRAL but this did not change anything.

The resource file also includes a #pragma code_page(1252); can this be safely removed? What is that pragma for?

Thank you for your answers.


Maybe you can use BOOL SetThreadLocale( LCID Locale );

MSDN : SetThreadLocale affects the selection of resources with a LANGUAGE statement. The statement affects such functions as CreateDialog, DialogBox, LoadMenu, LoadString, and FindResource. It sets the code page implied by CP_THREAD_ACP, but does not affect FindResourceEx. For more information, see Code Page Identifiers.


For LoadString, the obvious thing to do would be to call the Win32 API function LoadStringW() directly, which will give you the Unicode string directly. It might even work if you use the CStringW form of CString, like this (not tested!)

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

The menu and window functions will give more problems. It should work to call the Unicode form of the Win32 API GetMenuStringW() directly. The window function GetWindowText() is the really awkward one: you can, of course, call the Win32 function GetWindowTextW(), but what that returns will depend on whether the window you call it on has an ANSI or Unicode window procedure. If the underlying window is a Windows control then it's usually possible to get at the underlying window procedure and call that directly, but it's not pretty and it's not much fun.

Any chance of more detail on how you're trying to use it? It's worth noting that you list these functions as if all 3 access resources, but that's not true: only LoadString() does that. The other two operate directly on the menu or window that exists in the running process, not on resources.

As an example of how it's possible to get around the GetWindowTextW() problems, have a look at the UnicodeEdit class from this project. This is an ANSI application that needed to work on Windows 9X, but also needed to be able to get Unicode text from an edit control if possible. The trick is that the class remembers whether the window procedure before subclassing was Unicode or ANSI, and if Unicode, calls that directly in its GetWindowText(). Depending on what you need, this sort of approach might help.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜