You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:26:47