CreateWindowExA将常规字符串解释为Unicode,在标题

时间:2016-04-18 16:08:01

标签: winapi visual-c++ unicode

现在,我知道在微软的无限智慧中,他们错误地命名了一切。在Visual Studio中,设置Unicode表示UTF-16,而多字节字符是Microsoft所称的ANSI,它根本不是ANSI,而是Windows代码页1251。

无论如何,在WinAPI中有宏函数调用不同的函数,A或W版本取决于是否定义了Unicode。每个人都建议使用Unicode创建代码。所以我将我的设置设置为Unicode,因此编译器在任何字符串文字之前需要字母L,或者LPWSTR而不是LPSTR。问题是(这不是一个大问题),但在UTF-16中,每个字符都是两个或四个字节,每个字节大多是两个字节。我只打算主要使用ASCII字符,所以即使设置了Unicode,我实际上也会调用A版本的函数。

现在,我觉得这无关紧要,因为ASCII在所有代码页和所有Unicode编码中都是通用的,即UTF-8,UTF-16,UTF-32,甚至是旧的代码, ASCII几乎是通用的,前127个字符,或者至少罗马字母和阿拉伯数字都不会改变。

所以我的问题是,输入“AAAAA”作为我的窗口标题为什么会出现中文字符?那是五个As。所以我做了一些研究,发现A Unicode是0x0041,两个As是0x4141,两个字节。这就是结果。

enter image description here

所以在某种程度上,我知道为什么会发生这种情况。 UTF-8要好得多,因为它只是ASCII字符的一个字节,然后是较少使用的字符。但问题是,当我用MessageBoxA或其他任何东西写A时,它很好,它只是窗口标题来做这个奇怪的事情。

1 个答案:

答案 0 :(得分:5)

在阐述上述评论时,我认为问题在于您正在混合使用Unicode和ANSI调用。我的意思是,你可以混合它们,但你必须要小心。

在Windows中有两种类型的窗口:Unicode窗口和ANSI窗口。您可以通过致电IsWindowUnicode(HWND)来说明差异。

窗口类是在注册窗口类时确定的:使用RegisterClassA()并且您将拥有ANSI类;使用RegisterClassW(),你将拥有一个Unicode。然后它们之间的区别在于收到的消息:Unicode窗口将接收Unicode消息,ANSI窗口将接收ANSI消息。

请注意,窗口类型不依赖于CreateWindowExA()CreateWindowExW()的使用。这是有道理的:窗口类型由窗口类的设计者决定,而不是由用户决定。

如果那时,例如,您使用ANSI窗口(或反之亦然)调用SendMessageW()和一条众所周知的消息,Windows将自动转换wParamlParam的字符集参数。

所以这就是我认为它正在发生的事情:

  1. 您调用RegisterClassA()创建ANSI窗口类。
  2. 您调用CreateWindowExA()但使用Unicode变体不会改变任何内容。
  3. 在窗口功能中,您调用DefWindowProcW()进行默认处理。这是错误! ANSI窗口应该调用DefWindowProcA()。或者更好的是,您应该使用RegisterClassW()注册课程。
  4. 创建窗口时,通过向自身发送WM_SETTEXT来设置窗口标题。此邮件会在lParam中以LPCTSTR
  5. 的形式接收文本
  6. 由于您的窗口是ANSI,lParam实际上是LPCSTR(ANSI字符串) 指向你的"AAAAA"。但是您将它传递给期望DefWindowProcW()(Unicode字符串)的LPCWSTR。因此,您实际上是将指向ANSI字符串的指针转换为指向Unicode字符串的指针。
  7. 你在窗口标题中出现乱码。
  8. 请注意,此不匹配的不良影响不仅限于窗口标题。潜伏在那里的各种不良行为!。