Как правильно настроить поддержку вкладок Windows в Юникоде? - PullRequest
0 голосов
/ 20 октября 2018

Я скомпилировал следующий полный код C как WinMain.c на 64-разрядной платформе Windows 7 с TDM GCC 5.1.0 (64-разрядная версия).

#include <windows.h>
#include <commctrl.h>

#define szAppWndClassName L"MyApp"


HINSTANCE g_hInstance;  


HWND createTabCtrlW (HWND hwndParent, LPRECT lprectPlace, PWCHAR* pszLabels)
{
    TCITEMW ti = {0};
    HWND tab_ctrl = CreateWindowW(WC_TABCONTROLW, L"", WS_CHILD | WS_VISIBLE,
                                  lprectPlace->left,
                                  lprectPlace->top,
                                  (lprectPlace->right) - (lprectPlace->left),
                                  (lprectPlace->bottom) - (lprectPlace->top),
                                  hwndParent, NULL, g_hInstance, NULL);
    if (tab_ctrl != NULL)
    {
        ti.mask = TCIF_TEXT;
        ti.iImage = -1;

        /* Test code begin*/
        ti.pszText = L"Mon";
        SendMessageW(tab_ctrl, TCM_SETUNICODEFORMAT, TRUE, 0);  /* This seems can
                                                                    get the tab ctrl 
                                                                    to support Unicode,
                                                                    but in fact it won't do */
        SendMessageW(tab_ctrl, TCM_INSERTITEM, 1, (LPARAM)&ti); /* Insert tabs */
        /* Test code end */
    }

    return tab_ctrl;
}

static void createControls(HWND hwndParent)
{
    PWCHAR labels[]={L"Mon", L"Tue", L"Wed", NULL};
    RECT position, client_area;

    GetClientRect(hwndParent, &client_area);

    position.left = client_area.left;
    position.top = client_area.top;
    position.right = client_area.right;
    position.bottom = position.top + 200;

    INITCOMMONCONTROLSEX icc={sizeof(INITCOMMONCONTROLSEX), ICC_TAB_CLASSES};
    InitCommonControlsEx(&icc);

    HWND hTab=createTabCtrlW(hwndParent, &position, labels);
}

LRESULT CALLBACK MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_CREATE:
        createControls(hWnd);
        return 0;
    case WM_DESTROY:
        PostQuitMessage (0);
        return 0;
    }
    return DefWindowProcW(hWnd, uMsg, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszCmdln, int nShowState)
{
    WNDCLASSW wc;
    HWND hMainFrame;
    MSG msg;
    WINBOOL msgResult;

    g_hInstance = hInst;   

    wc.style         = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc   = MainWndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInst;
    wc.hIcon         = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION);
    wc.hCursor       = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW);
    wc.hbrBackground = CreateSolidBrush(GetSysColor(COLOR_MENU));
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = szAppWndClassName;

    if (!RegisterClassW(& wc))
    {
        MessageBoxW(NULL, L"WinMain: RegisterClass() failed", L"Error", MB_OK);
        return 1;
    }

    hMainFrame = CreateWindowW (szAppWndClassName,
                        L"Window Title",
                        WS_OVERLAPPEDWINDOW,
                        544,375,800,600,
                        NULL, NULL, hInst,
                        NULL) ;

    if (NULL == hMainFrame)
    {
        MessageBoxW(NULL, L"WinMain: CreateWindow() returns NULL", L"Error", MB_OK);
        return 1;
    }

    ShowWindow(hMainFrame, nShowState);

    while (TRUE)
    {
        msgResult = GetMessageW(&msg, NULL, 0, 0);
        if (0 == msgResult)
        {
            break;
        }
        else if (-1 == msgResult)
        {
            MessageBoxW(NULL, L"WinMain: GetMessage() error", L"Error", MB_OK);
            return 1;
        }
        else
        {
            TranslateMessage(&msg);
            DispatchMessageW(&msg);
        }
    }

    return msg.wParam;
}

Компиляция командной строки:

gcc -mwindows -o WinMain WinMain.c -lcomctl32

В разделе тестового кода предполагается создать вкладку с меткой «Mon», но на самом деле метка отображает только одну букву «M».

Внешний вид окна

Некоторые попытки отладки показывают, что проблема возникает из-за нулевого байта, следующего за каждой буквой в представлении Unicode (например, L"Mon" -> 0x4D 0x00 0x6F 0x00 0x6E 0x00). Нулевой байт был обработан как терминатор строки ANSI где-то внутри Windows, так что результат.

Но это не то поведение, которое предполагается приложением Юникода.

Даже если «Установка элемента управления вкладкой в ​​Юникод» с помощью SendMessageW(tab_ctrl, TCM_SETUNICODEFORMAT, TRUE, 0) не помогла.

Как правильно получить Unicode с поддержкой Tab Control, не могу ли я использовать что-то вроде WideCharToMultiByte?

1 Ответ

0 голосов
/ 20 октября 2018

Вам нужно либо использовать W-форму TCM_INSERTITEM (TCM_INSERTITEMW), либо определить UNICODE, прежде чем включать заголовки Windows.В этом виде на вкладке ожидается строка ANSI.

...