我的字符集有什么问题(Win32 API)

Wil*_*ler 1 c winapi menu windows-messages

我目前正在使用本教程学习Win32 ,并且我很难用我显示的角色.

比如这段代码在创建时向我的窗口添加一个菜单:

    case WM_CREATE: {
            HMENU hMenu, hSubMenu;
            HICON hIcon, hIconSm;

            hMenu = CreateMenu();
            hSubMenu = CreatePopupMenu();

            AppendMenu(hSubMenu, MF_STRING, ID_FILE_EXIT, "Exit");
            AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "File");

            hSubMenu = CreatePopupMenu();
            AppendMenu(hSubMenu, MF_STRING, ID_STUFF_GO, "&GO");
            AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&Stuff");

            SetMenu(hwnd, hMenu);

            hIcon = LoadImage(NULL, "Stuff.ico", IMAGE_ICON, 32, 32, LR_LOADFROMFILE);

            if (hIcon)
                SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
            else
                MessageBox(hwnd, "Could not load large icon!", "Load Error", MB_OK | MB_ICONERROR);

            hIconSm = LoadImage(NULL, "Stuff.ico", IMAGE_ICON, 16, 16, LR_LOADFROMFILE);

            if(hIconSm)
                SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hIconSm);
            else
                MessageBox(hwnd, "Could not load small icon!", "Load Error", MB_OK | MB_ICONERROR);
        }
        break;
Run Code Online (Sandbox Code Playgroud)

这是switch我的WndProc函数中的一个块内部,它处理从消息循环接收的Windows消息.

要显示的每个字符串:

"Exit"
"File"
"&GO"
"&Stuff"
Run Code Online (Sandbox Code Playgroud)

在运行时是不可读的,因为它们显示为小方块,就像代码页不是正确的那样或类似的东西.当我运行教程时,所有字符串都正确显示.我倾向于完全坚持教程所说的内容,以帮助我把事情做好,而且它的教学法很好.无论如何!...

我正在使用:

  1. Microsoft Visual Studio 2008团队系统;
  2. Microsoft Windows Server 2003使用RDP;
  3. 本地操作系统是Windows Vista Ultimate.

任何人都有关于它的线索?

RBe*_*eig 6

您对Unicode与Windows ANSI字符编码存在问题.从历史上看,Windows使用扩展的ASCII,他们错误地命名为ANSI.这带来了对代码页的需求,因为即使是8位字符也无法提供足够的代码点来代表所有的欧洲书写系统,更不用说世界其他地方了.在开发Win32时,他们将Unicode作为首选字符集.(实际上,他们确定了Unicode字符集的UTF-16LE编码,但这个细节现在并不完全相关.)但是,有太多的现有代码需要考虑要求从Win16移植到Win32也需要更改所有字符串的字符编码.

他们的解决方案很聪明(有些人认为它太聪明了).每个带字符串的Win32 API入口点都有两种形式.第一种风格采用ANSI字符串并在内部处理转换为UTF-16LE.第二种(现在是首选的)风味直接使用UTF-16LE字符串.他们还与Visual C团队密谋定义wchar_t为16位类型,并确保L""字符串文字使用从ASCII文本到UTF-16LE的映射.

为了方便从现有的Win16代码移植,MessageBox函数和其他每个带字符串的Win32 API在编译时由宏映射到MessageBoxA或者MessageBoxW取决于是否UNICODE定义了预处理器符号.

这种映射无法修复字符串文字,因此它们还引入了一个宏来指定字符串文字,这些文字要么是窄的,要么是宽的UNICODE,以及匹配的typedef,这样可以声明变量来保存指向它们的指针.

因此,为了获得Win16的最佳可移植性,您可以#include <tchar.h>使用TCHAR代替charwchar_t包装_T()宏中包含所有包含文本的字符串文字,并使用非后缀名称调用Win32 API MessageBox.

然而,这不是一个完美的解决方案.在您的代码需要操作或计算将向用户显示的字符串的那一刻,您会发现编写在该TCHAR机制中完全可移植的代码是很困难的.所有操作TCHARs 的标准字符串函数都有替换,但很难通过自动化测试验证您是否正确使用它们,以便代码可以编译并在有UNICODE定义和无定义的情况下正常工作.

如果今天编写新的Win32代码,我的建议是在项目中定义UNICODE,添加一个检查,它确实在一个公共头文件中定义,并明确使用L""字符串和W所有包装调用的风格.

最后,整个文章是由显示缺失字符字形的代码提示的(空方框字符是字体缺少特定字符时显示的字形).这是因为您的ASCII字符串文字被Win32代码解释为好像它们是UTF-16LE,因此字符串"Exit"将被视为两个Unicode字符,U+7845并且U+7469它们都是统一汉字表意文字.除非您安装了Han字体,否则两者都不太可能以系统中的任何字体出现,因此您将获得缺少的字符字形.

发生这种情况是因为您正在将包装器宏与ASCII字符串文字混合.你有:

AppendMenu(hSubMenu, MF_STRING, ID_FILE_EXIT, "Exit");
Run Code Online (Sandbox Code Playgroud)

但是您应该具有以下之一:

AppendMenu(hSubMenu, MF_STRING, ID_FILE_EXIT, _T("Exit"));
AppendMenuA(hSubMenu, MF_STRING, ID_FILE_EXIT, "Exit");
AppendMenuW(hSubMenu, MF_STRING, ID_FILE_EXIT, L"Exit");
Run Code Online (Sandbox Code Playgroud)

在哪里我更喜欢推荐最后一个例子.