C++ WinAPI开发:ListBox窗口文本显示乱码问题求助
解决ListBox显示窗口标题乱码的问题
嘿,我看了你的代码,乱码问题根源很明确——字符集不匹配!你混合使用了宽字符API和未明确字符集的调用,导致Unicode字符串被错误解析成多字节格式了。下面给你一步步拆解问题和解决方案:
问题出在哪?
你用GetWindowTextW拿到了Unicode格式的窗口标题(存在WCHAR数组里),但给ListBox发LB_ADDSTRING消息时用的是SendMessage——如果你的项目默认是多字节字符集,SendMessage会被自动替换成SendMessageA(多字节版本),它会把宽字符数组当作多字节字符串读取,直接就出现乱码了。另外,你创建ListBox时用的"LISTBOX"没加TEXT()宏,也会导致字符集不兼容。
怎么修复?
我给你整理了几个关键修复点,还有修改后的完整代码:
- 明确用宽字符版消息发送API:把
SendMessage改成SendMessageW,确保发送的是Unicode字符串。 - 所有字符串字面量加
TEXT()宏:比如CreateWindow("LISTBOX", ...)改成CreateWindow(TEXT("LISTBOX"), ...),让字符串适配项目的字符集设置。 - 初始化全局变量
hin:你之前没给这个全局的实例句柄赋值,创建ListBox时会传个垃圾值,这是个潜在bug。 - 先更新窗口再枚举:加个
UpdateWindow确保ListBox完全创建好,再枚举窗口添加标题,避免消息发空。
修改后的完整代码
#include <windows.h> ATOM RegMyWindowClass(HINSTANCE, LPCTSTR); HWND hListBox; HINSTANCE hin; BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) { WCHAR str[255]; if (GetWindowTextW(hwnd, str, 255)) { if (IsWindowVisible(hwnd) && (!GetWindow(hwnd, GW_OWNER))) // 用SendMessageW确保发送宽字符格式的字符串 SendMessageW(hListBox, LB_ADDSTRING, 0, (LPARAM)str); } return TRUE; // 用TRUE替代1,更符合Windows API的返回值规范 } LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_LBUTTONUP: MessageBox(hWnd, TEXT("Вы кликнули!"), TEXT("событие"), 0); break; case WM_DESTROY: PostQuitMessage(0); break; case WM_CREATE: // 用TEXT宏包裹控件类名和标题,适配字符集 hListBox = CreateWindow(TEXT("LISTBOX"), TEXT(""), WS_CHILD | WS_VISIBLE | LBS_NOTIFY | WS_VSCROLL, 0, 0, 400, 400, hWnd, (HMENU)1111, hin, NULL); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { hin = hInstance; // 初始化全局hin变量,之前漏掉了这一步! LPCTSTR lpzClass = TEXT("My Window Class!"); if (!RegMyWindowClass(hInstance, lpzClass)) return 1; RECT screen_rect; GetWindowRect(GetDesktopWindow(), &screen_rect); int x = screen_rect.right / 2 - 200; int y = screen_rect.bottom / 2 - 200; HWND hWnd = CreateWindow(lpzClass, TEXT("Window"), WS_OVERLAPPEDWINDOW | WS_VISIBLE, x, y, 400, 400, NULL, NULL, hInstance, NULL); if (!hWnd) return 2; ShowWindow(hWnd, SW_SHOW); UpdateWindow(hWnd); // 确保窗口和控件完全创建后再枚举窗口 EnumWindows(&EnumWindowsProc, 0); MSG msg = { 0 }; int iGetOk = 0; while ((iGetOk = GetMessage(&msg, NULL, 0, 0)) != 0) { if (iGetOk == -1) return 3; TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } ATOM RegMyWindowClass(HINSTANCE hInst, LPCTSTR lpzClassName) { WNDCLASS wcWindowClass = { 0 }; wcWindowClass.lpfnWndProc = WndProc; wcWindowClass.style = CS_HREDRAW | CS_VREDRAW; wcWindowClass.hInstance = hInst; wcWindowClass.lpszClassName = lpzClassName; wcWindowClass.hCursor = LoadCursor(NULL, IDC_ARROW); wcWindowClass.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE; return RegisterClass(&wcWindowClass); }
额外优化建议
如果你想彻底避免这类字符集问题,建议把你的Visual Studio项目设置改成Unicode字符集(项目属性 -> 配置属性 -> 常规 -> 字符集),这样所有不带后缀的API(比如SendMessage、CreateWindow)都会自动映射到宽字符版本,后续写代码就不用纠结A/W后缀了。
内容的提问来源于stack exchange,提问作者synd
相关产品推荐
相关产品推荐

