3

我们有一个使用 Visual Studio 编写的非 Unicode C++ 应用程序,它最初是为使用代码页 1252 字符集的机器编写的。

我们的应用程序在读取资源内容后执行许多后处理步骤,包括在某些文件中查找资源字符串。

现在中国的人们开始使用该应用程序,他们的机器使用 PRC 语言环境(将非 unicode 应用程序的默认代码页设置为 936,这是一个多字节字符集)。

似乎CString::LoadString将执行一些转换。这会中断进一步处理,因为我们在其他文件中查找的内容不同。

CMenu::GetMenuString或也是如此CWnd::GetWindowText

糟糕的是,我们不能简单地iconv在我们的文件上使用,因为LoadString, GetMenuStringorGetWindowText会这样:

  • 某些在代码页 1252 中有效的字符在代码页 936 中无效(例如î、û、ñ、–)并被替换为问号
  • 某些在代码页 1252 中有效的字符在代码页 936 中无效(例如É),但被替换为替代字符(É => é)
  • 两个代码页中都存在一些字符,但表示方式不同,在 CP936 中通常有两个字节
  • 两个代码页中的某些字符(包括所有 ASCII 字符)匹配。

我希望加载资源内容的这三个函数加载二进制内容,而不执行任何字符集转换。我试图修改.rc文件,LANGUAGE LANG_INVARIANT, SUBLANG_NEUTRAL但这并没有改变任何东西。

资源文件还包括一个#pragma code_page(1252); 可以安全删除吗?那个 pragma 是干什么用的?

谢谢您的回答。

4

2 回答 2

3

也许你可以使用 BOOLSetThreadLocale( LCID Locale );

MSDN:SetThreadLocale 影响使用 LANGUAGE 语句的资源选择。该语句影响 CreateDialog、DialogBox、LoadMenu、LoadString 和 FindResource 等函数。它设置 CP_THREAD_ACP 隐含的代码页,但不影响 FindResourceEx。有关详细信息,请参阅代码页标识符。

于 2011-03-01T15:47:09.850 回答
2

对于 LoadString,显而易见的做法是直接调用 Win32 API 函数 LoadStringW(),这将直接为您提供 Unicode 字符串。如果您使用 CString 的 CStringW 形式,它甚至可能会起作用,就像这样(未经测试!)

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

菜单和窗口功能会带来更多问题。它应该可以直接调用 Win32 API GetMenuStringW() 的 Unicode 形式。窗口函数 GetWindowText() 是一个非常尴尬的函数:当然,您可以调用 Win32 函数 GetWindowTextW(),但返回的内容取决于您调用它的窗口是否具有 ANSI 或 Unicode 窗口过程。如果底层窗口是一个 Windows 控件,那么通常可以访问底层窗口过程并直接调用它,但它并不漂亮,也不是很有趣。

关于您如何尝试使用它的更多细节的机会?值得注意的是,您列出了这些函数,就好像所有 3 个访问资源一样,但事实并非如此:只有 LoadString() 这样做。另外两个直接对运行进程中存在的菜单或窗口进行操作,而不是对资源进行操作。

作为如何解决 GetWindowTextW() 问题的示例,请查看此项目中的 UnicodeEdit 类。这是一个 ANSI 应用程序,需要在 Windows 9X 上运行,但如果可能,还需要能够从编辑控件中获取 Unicode 文本。诀窍是该类记住子类化之前的窗口过程是 Unicode 还是 ANSI,如果是 Unicode,则直接在其 GetWindowText() 中调用它。根据您的需要,这种方法可能会有所帮助。

于 2011-03-01T12:39:54.473 回答