WinApi DrawText и TextOut не могут отображать символ Юникода U+5167

Привет Windows-программистам!

Я новичок в программировании Windows с помощью winapi. Я читал эту очень хорошую книгу и столкнулся с проблемой (отображаемой в виде черного ящика), когда я отображаю символ Юникода U+5167 (內) в клиентской области с помощью DrawText и TextOut. Таинственным образом этот конкретный символ Юникода правильно отображается в области заголовка Windows. Этот символ Юникода также отображается правильно, когда я отображаю его с помощью MessageBox. Наконец, я попытался отобразить другие символы юникода, которые относительно близки к этому юникоду, такие как U+5166, U+5168, U+5157 и U+5177;

Вот ссылка для этого символа Юникода, как это определено стандартами. http://unicode-table.com/en/#5167

Примечание. Я компилирую этот код, используя Unicode, используя Visual Studio 2010.

Ниже мой код.


#include<windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szAppName[] = TEXT("HelloWin");
    HWND hwnd;
    MSG msg;

    WNDCLASS wndclass;
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = szAppName;

    if(!RegisterClass (&wndclass))
    {
        MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);
        return 0;
    }

    hwnd = CreateWindow(szAppName,
                            TEXT("內Sample text 內篇 日本国 渡瀬 內篇全兦兗具 кошка"),
                            WS_OVERLAPPEDWINDOW,
                            CW_USEDEFAULT,
                            CW_USEDEFAULT,
                            CW_USEDEFAULT,
                            CW_USEDEFAULT,
                            NULL,
                            NULL,
                            hInstance,
                            NULL);
    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);
    while(GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam ;
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;
    RECT rect;
    LPTSTR c = TEXT("內Sample text 內篇 日本国 渡瀬 內篇全兦兗具 кошка");

    switch(message)
    {
        case WM_CREATE:
            PlaySound(TEXT("shutda.wav"), NULL, SND_FILENAME | SND_ASYNC);
MessageBox(hwnd, c, c, 0);
            return 0;
        case WM_PAINT:
            hdc = BeginPaint(hwnd, &ps);
            GetClientRect(hwnd, &rect);         
            DrawTextEx(hdc, c, -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER, NULL);
            TextOut(hdc, 100, 100, TEXT("內篇 日本国 кошка unicode"), 19);
            EndPaint(hwnd, &ps);
            return 0;
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
    }

    return DefWindowProc(hwnd, message, wParam, lParam);
}

Для программистов, не работающих с Windows, вы можете скомпилировать и запустить этот код, скопировав и вставив его непосредственно в файл .cpp. Если вы используете VS2010, вам просто нужно создать новый проект «Приложение Win32» и выбрать «Пустой проект». После этого вам нужно добавить файл cpp, например, «test.cpp» в исходную папку вашего проекта. Затем скопируйте и вставьте код в «test.cpp», затем соберите и запустите его. Теперь вы должны увидеть мою проблему. :)


person wembikon    schedule 30.05.2014    source источник
comment
Вы проверили, что ваш шрифт по умолчанию содержит необходимые глифы?   -  person Richard    schedule 30.05.2014
comment
Привет Ричард. Я не проверял свой шрифт по умолчанию, но если виноват шрифт, как возможно, чтобы этот символ отображался правильно с использованием окна сообщений и области заголовка окна, но не при использовании функций TextOut или DrawText?   -  person wembikon    schedule 30.05.2014
comment
Окна сообщений, заголовки окон и шрифт окна по умолчанию могут быть разными.   -  person Richard    schedule 30.05.2014
comment
Я понимаю. Как проверить, использую ли я правильный шрифт для TextOut и DrawText?   -  person wembikon    schedule 30.05.2014
comment
Я не могу вспомнить, как узнать, почему шрифт в настоящее время установлен в контроллере домена (это может помочь: Отображать значения контекста устройства по умолчанию), но вы устанавливаете шрифт контроллера домена с помощью SelectObject передает дескриптор шрифта.   -  person Richard    schedule 30.05.2014
comment
Здесь бессмысленно использовать TEXT(). Код не может работать со сборкой ANSI, поэтому вы просто излишне усложняете его.   -  person David Heffernan    schedule 30.05.2014
comment
@Richard Привет, спасибо за ответ. Я решил проблему, создав шрифт с глифом для этого символа и используя SelectObject, чтобы установить его в DC.   -  person wembikon    schedule 30.05.2014
comment
Пожалуйста, не отменяйте правильные ответы, редактируя вопрос. Эта проблема решена, закройте свой вопрос, нажав на галочку слева от ответа, который решил вашу проблему.   -  person Hans Passant    schedule 30.05.2014
comment
@DavidHeffernan, как я уже упоминал, я создаю этот код, используя Unicode, а не ANSI. Кроме того, макрос TEXT IMHO не делает ничего сложного, а делает ваш код переносимым и более простым для масштабирования в будущем.   -  person wembikon    schedule 30.05.2014
comment
Шрифт по умолчанию, используемый контроллером домена, не содержит глифа для символа Юникода U+5167. Чтобы решить эту проблему, вы должны создать шрифт с помощью CreateFont, используя семейство шрифтов с соответствующим глифом для указанного символа Юникода. Используйте этот новый объект шрифта в контексте устройства с помощью SelectObject.   -  person wembikon    schedule 30.05.2014
comment
TEXT() не делает код переносимым. TEXT() используется для программ, предназначенных как для Win9x, поддерживающих только ANSI, так и для WinNT, поддерживающих Unicode. Те дни давно прошли, и ваша программа абсолютно не переносима. Это только Юникод. Так что используйте L"...".   -  person David Heffernan    schedule 30.05.2014
comment
L... то же самое с TEXT(...). Это просто вопрос предпочтений. Я имею в виду переносимый исходный код для версий ansi/unicode, и моя программа абсолютно не только для Unicode. Знаете ли вы что-нибудь об аргументах компилятора ANSI/UNICODE?   -  person wembikon    schedule 30.05.2014


Ответы (1)


Когда допустимый символ отображается в виде прямоугольного прямоугольника, это означает, что шрифт не содержит глифа для символов. Чтобы решить эту проблему, вам нужно использовать шрифт, в котором есть глиф для этого символа.

person David Heffernan    schedule 30.05.2014