Текст UTF-8 в приложении MFC, использующий многобайтовый набор символов - PullRequest
0 голосов
/ 01 февраля 2019

Я работаю над приложением, которое получает текст, закодированный в UTF-8, и должно отображать его на каком-либо элементе управления MFC.Приложение создается с использованием набора символов MultiByte (MBCS), и давайте предположим, что это не может измениться.

Я надеялся, что, если я преобразую текст, полученный от UTF-8, в широкую строку символов, я смогу правильно отобразить его, используя метод SetWindowTextW.Чтобы попробовать это, я использовал игрушечное приложение, которое читает входные данные из файла и устанавливает тексты моих элементов управления.

std::wstring utf8_decode(const std::string &str)
{
    if (str.empty()) return std::wstring();
    int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
    std::wstring wstrTo(size_needed, 0);
    MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
    return wstrTo;
}

BOOL CAboutDlg::OnInitDialog()
{
    std::vector<std::string> texts;
    texts.resize(6);
    std::fstream f("D:\\code\\sample-utf8.txt", std::ios::in);
    for (size_t i=0;i<6;++i)
        std::getline(f, texts[i]);

    ::SetWindowTextW(GetDlgItem(IDC_BUTTON1)->m_hWnd, utf8_decode(texts[0]).c_str());
    ::SetWindowTextW(GetDlgItem(IDC_BUTTON2)->m_hWnd, utf8_decode(texts[1]).c_str());
    ::SetWindowTextW(GetDlgItem(IDC_BUTTON3)->m_hWnd, utf8_decode(texts[2]).c_str());
    ::SetWindowTextW(GetDlgItem(IDC_BUTTON4)->m_hWnd, utf8_decode(texts[3]).c_str());
    ::SetWindowTextW(GetDlgItem(IDC_BUTTON5)->m_hWnd, utf8_decode(texts[4]).c_str());
    ::SetWindowTextW(GetDlgItem(IDC_BUTTON6)->m_hWnd, utf8_decode(texts[5]).c_str());
    return TRUE;
}

Создав игрушечное приложение с MBCS, я не получаю то, что хотел бы,enter image description here

Как только я создаю приложение, используя Unicode, все работает нормально enter image description here

Означает ли это, что нетнадеюсь на использование текста Unicode для отдельных элементов управления при сборке с MBCS?Если это возможно, вы можете дать мне какие-нибудь указатели?Спасибо.

Ответы [ 2 ]

0 голосов
/ 04 февраля 2019

Я получил эту работу, благодаря предложениям Эдриана Маккарти и Джозефа Уилкоксона.Я создаю элементы управления с помощью метода CreateWindowExW, а затем устанавливаю текст с помощью SetWindowTextW.Ниже приведен пример кода на случай, если он поможет:

std::wstring utf8_decode(const std::string &str)
{
    if (str.empty()) return std::wstring();
    int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
    std::wstring wstrTo(size_needed, 0);
    MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
    return wstrTo;
}

HWND CreateButtonW(int x, int y, int width, int height, HWND parent)
{
    HWND hwndButton = ::CreateWindowExW(
        WS_EX_CLIENTEDGE,
        L"BUTTON",  // Predefined class; Unicode assumed 
        L"", WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
        x, y, width, height, parent,
        NULL, // No menu.
        (HINSTANCE)GetWindowLong(parent, GWL_HINSTANCE),
        NULL);      // Pointer not needed.
    return hwndButton;
}

BOOL CAboutDlg::OnInitDialog()
{
    std::vector<std::string> texts;
    texts.resize(6);
    std::fstream f("D:\\code\\sample-utf8.txt", std::ios::in);
    for (size_t i=0;i<6;++i)
        std::getline(f, texts[i]);


    ::SetWindowTextW(GetDlgItem(IDC_BUTTON1)->m_hWnd, utf8_decode(texts[0]).c_str());
    ::SetWindowTextW(GetDlgItem(IDC_BUTTON2)->m_hWnd, utf8_decode(texts[1]).c_str());
    ::SetWindowTextW(GetDlgItem(IDC_BUTTON3)->m_hWnd, utf8_decode(texts[2]).c_str());
    ::SetWindowTextW(GetDlgItem(IDC_BUTTON4)->m_hWnd, utf8_decode(texts[3]).c_str());
    ::SetWindowTextW(GetDlgItem(IDC_BUTTON5)->m_hWnd, utf8_decode(texts[4]).c_str());
    ::SetWindowTextW(GetDlgItem(IDC_BUTTON6)->m_hWnd, utf8_decode(texts[5]).c_str());

    auto width  = [](RECT& r) { return r.right - r.left; };
    auto height = [](RECT& r) { return r.bottom - r.right; };

    RECT r;
    GetDlgItem(IDC_BUTTON1)->GetWindowRect(&r); ScreenToClient(&r);
    HWND hBtnWnd = CreateButtonW(r.right+20, r.top, width(r), height(r), m_hWnd);
    ::SetWindowTextW(hBtnWnd, utf8_decode(texts[0]).c_str());

    GetDlgItem(IDC_BUTTON2)->GetWindowRect(&r); ScreenToClient(&r);
    hBtnWnd = CreateButtonW(r.right+20, r.top, width(r), height(r), m_hWnd);
    ::SetWindowTextW(hBtnWnd, utf8_decode(texts[1]).c_str());

    GetDlgItem(IDC_BUTTON3)->GetWindowRect(&r); ScreenToClient(&r);
    hBtnWnd = CreateButtonW(r.right+20, r.top, width(r), height(r), m_hWnd);
    ::SetWindowTextW(hBtnWnd, utf8_decode(texts[2]).c_str());

    GetDlgItem(IDC_BUTTON4)->GetWindowRect(&r); ScreenToClient(&r);
    hBtnWnd = CreateButtonW(r.right+20, r.top, width(r), height(r), m_hWnd);
    ::SetWindowTextW(hBtnWnd, utf8_decode(texts[3]).c_str());

    GetDlgItem(IDC_BUTTON5)->GetWindowRect(&r); ScreenToClient(&r);
    hBtnWnd = CreateButtonW(r.right+20, r.top, width(r), height(r), m_hWnd);
    ::SetWindowTextW(hBtnWnd, utf8_decode(texts[4]).c_str());

    GetDlgItem(IDC_BUTTON6)->GetWindowRect(&r); ScreenToClient(&r);
    hBtnWnd = CreateButtonW(r.right+20, r.top, width(r), height(r), m_hWnd);
    ::SetWindowTextW(hBtnWnd, utf8_decode(texts[5]).c_str());

    return TRUE;
}

И результат - слева кнопки, созданные по умолчанию, справа при создании с использованием CreateWindowExW:

enter image description here

0 голосов
/ 02 февраля 2019

Приложение MBCS создает окна MBCS, которые, вообще говоря, будут иметь возможность отображать текст только с одной кодовой страницы, даже если вы используете широкоформатный интерфейс.

Для приложения MBCS,широкая строковая версия SetWindowTextW по существу преобразует широкую строку в MBCS, используя текущую локаль пользователя (которая имеет кодовую страницу по умолчанию), а затем передает ее в версию -A функции.

Когда вывы видели в своем опыте "Unicode", вы делаете в целом правильные вещи, но вы ограничены тем фактом, что приложение - MBCS.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...