Let me preface by saying I have tried to find a solution, seen similar queries but, being new to win32, failed to transport those answers into my own problem. I also noticed that every answer seems to have a common root for the issue (unicode) but slightly different technical solutions.
This is an old game institute tutorial. Objective is to create a dialog(1), which contains a combo box, to be populated via a text box for the user to enter a bit of text. Selecting items from the combo box displays a new dialog(2) showing the contents of the selected item. Everything works, bar the display of the items in the combo box, they don;t display correctly instead displaying oriental chars. Text in dialog (2) displays correctly.
#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;
}
潍楪慢敫
This is Mojibake for "Mojibake
" when its ASCII, ANSI, or UTF-8 encoding is interpreted as UTF-16LE. This should look familiar.
The (unintended) transliteration is instigated here:
char msgText[256];
GetWindowTextA(hEditBox, msgText, 256);
if (strlen(msgText) > 0)
SendMessage(hComboBox, CB_ADDSTRING, 0, (LPARAM)msgText);
GetWindowTextA
instructs the system to return the "window text" and (optionally) convert it to the system default ANSI code page encoding (CP_ACP
). The SendMessage
preprocessor macro expands to SendMessageW
(assuming that UNICODE
is defined), and subsequently fools the recipient into interpreting the lParam
argument as UTF-16-encoded.
This is how to generate Mojiabke (and a potential buffer overrun vulnerability on the side).
The "least amount of keystrokes required to address the issue" solution would be to replace SendMessage
with SendMessageA
. A more rational approach is to acknowledge, that UTF-16 is the internal character encoding pretty much everywhere. The following is both correct as well as computationally cheaper:
wchar_t msgText[256] = {};
if (::GetWindowTextW(hEditBox, msgText, std::size(msgText)) > 0)
::SendMessageW(hComboBox, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(msgText));