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

WinAPI组合框显示东方字符乱码问题求助

Win32组合框东方字符乱码问题排查与解决

问题描述

我是Win32开发新手,查过类似问题但没法套用现有解决方案,知道这类问题根源大多和Unicode有关,但具体实现方案各有不同。
目前基于旧游戏学院教程开发程序:创建带组合框的对话框(1),通过文本框输入内容填充组合框;选中组合框选项时,用MessageBox(对话框2)显示选中内容。程序功能正常,但组合框内的选项显示东方字符乱码,MessageBox显示正常。相关代码如下:

#include <windows.h>
#include <string>
#include "resource.h"
using namespace std;
// Dialog handle.
HWND ghDlg = 0;
// Dialog window procedure.
INT_PTR CALLBACK
MsgDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
    // Text buffer to be filled with string user entered
    // into edit control.
    char msgText[256];
    // Handles to the combo box controls.
    static HWND hComboBox = 0;
    static HWND hEditBox = 0;
    static HWND hAddButton = 0;
    int index = 0;
    switch (msg)
    {
    case WM_INITDIALOG:
        // Controls are child windows to the dialog they lie on.
        // In order to get and send information to and from a
        // control we will need a handle to it. So save a handle
        // to the controls as the dialog is being initialized.
        // Recall that we get a handle to a child control on a
        // dialog box with the GetDlgItem.
        hComboBox = GetDlgItem(hDlg, IDC_COMBOBOX);
        hEditBox = GetDlgItem(hDlg, IDC_EDIT_MSG);
        hAddButton = GetDlgItem(hDlg, IDC_ADDBUTTON);
        return true;
    case WM_COMMAND:
        switch (HIWORD(wParam))
        {
            // User selected a combo box item.
        case CBN_SELENDOK:
            index = SendMessage(hComboBox, CB_GETCURSEL, 0, 0);
            SendMessage(hComboBox, CB_GETLBTEXT, (WPARAM)index,
                (LPARAM)msgText);
            MessageBoxA(0, msgText, "Combo Message", MB_OK);
            return true;
        }
        switch (LOWORD(wParam))
        {
            // User pressed the "Add" button.
        case IDC_ADDBUTTON:
            // Get the text from the edit box.
            GetWindowTextA(hEditBox, msgText, 256);
            // Add the text to the combo box only if the
            // user entered a string that is greater than zero.
            if (strlen(msgText) > 0)
                SendMessage(
                    hComboBox,
                    CB_ADDSTRING,
                    0,
                    (LPARAM)msgText);
            return true;
        }
        return true;
    case WM_CLOSE:
        DestroyWindow(hDlg);
        return true;
    case WM_DESTROY:
        PostQuitMessage(0);
        return true;
    }
    return false;
}
int WINAPI
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    PSTR cmdLine, int showCmd)
{
    // Create the modeless dialog window.
    ghDlg = CreateDialog(
        hInstance, // Application instance.
        MAKEINTRESOURCE(IDD_COMBODLG), // Dialog resource ID.
        0, // Parent window--null for no parent.
        MsgDlgProc); // Dialog window procedure.
    // Show the dialog.
    ShowWindow(ghDlg, showCmd);
    // Enter the message loop.
    MSG msg;
    ZeroMemory(&msg, sizeof(MSG));
    while (GetMessage(&msg, 0, 0, 0))
    {
        // Is the message a dialog message? If so the function
// IsDialogMessage will return true and then dispatch
// the message to the dialog window procedure.
// Otherwise, we process as the message as normal.
        if (ghDlg == 0 || !IsDialogMessage(ghDlg, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    return (int)msg.wParam;
}

解决方案

问题核心是你的项目默认启用了Unicode字符集,但代码全程使用ANSI版本API(带A后缀的函数,如MessageBoxA、GetWindowTextA),而组合框控件默认以Unicode模式处理文本,导致编码不匹配出现乱码。提供两种解决方式:

方式一:统一使用Unicode API(推荐)

现代Win32程序优先使用Unicode编码,兼容性更好:

  • 将字符缓冲区类型从char改为wchar_t:wchar_t msgText[256];
  • 替换所有ANSI后缀API为宽字符版本(W后缀):
    • GetWindowTextA → GetWindowTextW
    • MessageBoxA → MessageBoxW
  • 字符串常量前添加L前缀,标记为宽字符字符串,如L"Combo Message"
  • 字符串长度判断用wcslen替代strlen

修改后的关键代码片段:

// 替换char为wchar_t
wchar_t msgText[256];

// 选中组合框项的分支修改
case CBN_SELENDOK:
    index = SendMessage(hComboBox, CB_GETCURSEL, 0, 0);
    SendMessage(hComboBox, CB_GETLBTEXT, (WPARAM)index, (LPARAM)msgText);
    MessageBoxW(0, msgText, L"Combo Message", MB_OK);
    return true;

// 添加按钮的分支修改
case IDC_ADDBUTTON:
    GetWindowTextW(hEditBox, msgText, 256);
    if (wcslen(msgText) > 0)
        SendMessage(hComboBox, CB_ADDSTRING, 0, (LPARAM)msgText);
    return true;

方式二:修改项目字符集为多字节(不推荐)

如果不想修改代码,可以在项目属性中找到「字符集」选项,改为「使用多字节字符集」。这样控件会以ANSI模式处理文本,和现有代码的API匹配,但这种方式在高版本Windows系统上兼容性不如Unicode。

额外注意

CreateDialog会根据项目字符集自动映射为CreateDialogA或CreateDialogW,如果用Unicode模式,确保对话框资源的字符集设置和代码一致,避免额外的编码问题。

内容的提问来源于stack exchange,提问作者jmlima

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 17:11:00