C++:为什么此窗口标题被截断
C++ : Why this window title gets truncated?
Visual C++ 2012 RC, Win7
简体中文
使用多字节字符集的项目属性>
当我运行这个程序时,窗口的标题显示一个字母"S",而不是一个完整的单词"Sample"。
#pragma comment(linker, "/SubSystem:Windows")
#include <windows.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR, int) {
WNDCLASSW wc = { 0 };
wc.style = CS_VREDRAW | CS_HREDRAW;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
wc.hbrBackground = reinterpret_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
wc.lpszClassName = L"MyWindowClass";
wc.lpfnWndProc = [](HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
if (uMsg - WM_DESTROY)
return DefWindowProc(hWnd, uMsg, wParam, lParam);
else {
PostQuitMessage(0);
return HRESULT();
}
};
RegisterClassW(&wc);
CreateWindowExW(0, L"MyWindowClass", L"Sample",
WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, SW_SHOW, CW_USEDEFAULT, 0,
nullptr, nullptr, hInstance, nullptr);
for (MSG msg; GetMessage(&msg, nullptr, 0, 0); DispatchMessage(&msg));
}
如果我使用 Unicode(项目属性),请保持源代码不变,窗口标题显示"示例",看起来正确。
如果我使用多字节,在源代码中我使用 WNDCLASS = { ..., "MyWindowClass" } 和 RegisterClassA,保持 CreateWindowExW 不变,窗口标题显示单词"Sample",看起来正确。
如果我使用多字节,在源代码中我使用CreateWindowExA("MyWindowClass","Sample"),保持WNDCLASSW和RegisterClassW不变,窗口标题显示字母"S"。
是什么让它显示一个"S",我做错了什么吗?
附加
如果我保持全部不变,即使用多字节,使用上面显示的代码,窗口标题显示字母"S"。
(如果您运行此程序并在窗口标题上看到"示例",而不是"S",那么它更有可能是 chs 版本的 vc++ 2012(或操作系统)上的特定问题)。
代码中的问题是您使用的是DefWindowProc
而不是DefWindowProcW
。更改它将修复代码。
理想情况下,您应该将项目设置更改为使用 Unicode,而不是多字节字符集。这将简化一切,您可以使用CreateWindowEx
和RegisterClassEx
等宏,而不是像现在这样显式使用 Unicode/ANSI 版本。
正如其他人所说,这是字符集之间的不匹配。
理想情况下,您应该在所有相互交互的 API 调用之间匹配字符集。所以如果你使用CreateWindowExW
你也应该使用RegisterClassExW
、DefWindowProcW
、DispatchMessageW
......
这是一个非常好的,学到了一些新东西!
你需要改变
return DefWindowProc(hWnd, uMsg, wParam, lParam);
自
if(IsWindowUnicode(hWnd))
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
else
return DefWindowProcA(hWnd, uMsg, wParam, lParam);
甚至更好:坚持一个字符编码。充其量只是使用RegisterClass
、CreateWindowEx
等,让编译器采用正确的 Unicode 或 ANSI 函数。
CreateWindowExA 将字符串解释为 8 位字符。L"Sample" 的后 8 位为零,因为它的第一个字符是0x0053 - L 表示使用宽字符。因此,该函数将其解释为 1 个字符的 null 终止字符串。
我认为 RegisterClass
的 msdn 页面暗示了这里失败的原因,在备注部分它提到了如果您使用宽字符或 ansi 支持,那么它将以这种格式传递内部文本参数/消息(宽字符/ansi)。 很可能这就是窗口标题发生的事情,即使我们说使用 CreateWindowExA
,这不起作用,因为内部 Windows SDK 已将该字符串编码为宽字符串,并且CreateWinowExA
尝试输出,就好像它是 Ansi 字符串一样。
简而言之,不要混合使用 W 和 A 方法,除非您有充分的理由这样做,并且如果您想要广泛的字符支持定义您的 UNICODE 宏,请让 windows 标头为您处理它。
在你的最后一个案例中,你的L"Sample"仍然是Unicode,不是吗?您可以使用 _T() 宏,它根据项目的 Unuicode 设置自动添加或删除 L 前缀。
正如@Pete已经说过的,Unicode L"Sample"在ascii中是"S\0...",这就是为什么只打印一个符号的原因。
我很高兴我找到了这个。 我到处寻找答案,似乎很难用谷歌等正确找到答案。 我确实发现了针对特定程序报告的类似问题,总是归咎于"某些插件"。
这很令人抓狂,因为WndProc的问题远不及对CreateWindowEx或RegisterClassEx的调用!
顺便说一句,我显式使用 -W 后缀,因为我想创建一个适用于以任何方式构建的程序的 DLL,或者克服我正在添加到的程序的非 Unicode 设置。
- 无法在 GLFW 窗口标题中显示'ä'
- 为什么抓取窗口标题的代码会导致应用崩溃?
- 如何正确获取 Unicode 窗口标题
- 如何随机化程序的窗口标题?
- 如何在QT中获取背景应用程序窗口标题
- 如何在 Ubuntu Qt 中获取活动窗口标题
- 最佳地将窗口标题替换为新的 QString
- 构造函数字符串参数未设置窗口标题
- 获取C++中的窗口标题
- C++:为什么此窗口标题被截断
- 窗口标题GLFW中的FPS计数器
- 如何永久删除主窗口标题栏
- 使用WM_GETTEXT获取窗口标题
- 在窗口标题和消息框中显示错误的语言:win32应用程序,opengl
- 在GLFW窗口标题中显示FPS
- 如何从其进程路径中获取窗口标题
- 无法获取窗口标题
- 在Qt中更改主窗口标题
- 如何在 Windows 上获取C++ 个字符 * 格式的当前窗口标题?
- 在c++和Neko目标中更改窗口标题