SetWindowTextW в проекте ANSI - PullRequest
       14

SetWindowTextW в проекте ANSI

3 голосов
/ 23 февраля 2012

У меня есть проект ANSI. Мне нужно установить заголовок класса, производного от CDialog, в текст Unicode.

BOOL CMyDialog::OnInitDialog()
{
    CDialog::OnInitDialog();

    ::SetWindowTextW(GetSafeHwnd(), PathFindFileNameW(filename));

    return TRUE;  // return TRUE unless you set the focus to a control
    // EXCEPTION: OCX Property Pages should return FALSE
}

Однако, когда текст в Unicode содержит символы, отличные от ANSI, они отображаются в виде вопросительных знаков. Я получаю что-то вроде «?????. Doc». У меня похожие проблемы со статическими элементами управления, но, как ни странно, с полями редактирования SetWindowTextW работает.

О, и этот проект - большой унаследованный проект, который не может быть преобразован в Unicode.

Ответы [ 5 ]

6 голосов
/ 17 июля 2012

SetWindowText () / SetWindowTextA () и SetWindowTextW () действительно являются WM_SETTEXT, который является одним из немногих сообщений, подлежащих переводу кодовой страницы при создании многобайтового окна / окна Ansi.Это означает, что версии сообщений W и A отсутствуют.

Несмотря на это, Unicode легко отобразить в заголовке Vista / Win7, построенном как приложение Ansi / Multibyte.Все, что вам нужно сделать, это перехватить сообщение WM_SETTEXT в вашем окне и передать аргументы в DefWindowProcW () вместо обычного DefWindowProcA / DefWindowProc ().Это работает, потому что внутри все окна на самом деле являются юникодом.

Обратите внимание, что если вы просто передаете аргументы в DefWindowProcW (), то вы должны быть абсолютно уверены, что аргумент действительно указывает на строку wchar_t.

В моем собственном случае предполагается, что все строки символов состоят из символов UTF-8.Это означает, что нормальные строки ANSI все еще работают как прежде.Когда я перехватываю сообщение WM_SETTEXT в окне, я преобразую символ UTF-8 в wchar_t, используя MultiByteToWideChar (), а затем явно передаю результат в DefWindowProcW ().

Приятным побочным эффектом является то, что он также отображаетсимволы Юникод на панели задач тоже.

В XP есть проблема, из-за которой заголовок отображается неправильно, даже если панель задач есть.

2 голосов
/ 10 октября 2014

Ответ Тома Нельсона, вероятно, лучший, но я просто нашел другое быстрое решение и решил поделиться:

LONG_PTR originalWndProc = GetWindowLongPtrW(hwnd, GWLP_WNDPROC);
SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR) DefWindowProcW);
SetWindowTextW(hwnd, L"✈✌❦♫");
SetWindowLongPtrW(hwnd, GWLP_WNDPROC, originalWndProc);

Без этой последней строки мы получали ошибки утверждения при отладке, хотя нажимали IgnoreПохоже, проблем не возникло, и режим Release вел себя как следует.MFC все еще остается загадкой для многих из нас, так что, надеюсь, этот код является надежным.

2 голосов
/ 23 февраля 2012

Если вы не можете преобразовать проект в Unicode, тогда вам просто нужно принять ограничения.Ваш диалог - это диалог ANSI.Вы можете использовать SetWindowTextW, если хотите, но когда система хочет нарисовать диалоговое окно, она будет использовать ANSI API для получения текста окна.Это будет использовать функции рисования текста GSI GDI для выполнения рисования.Если вы хотите диалог Unicode, вам нужно скомпилировать для Unicode.

1 голос
/ 23 февраля 2012

Microsoft определяет многие функции API в нескольких вариантах.Существует три версии PathFindFileName() (не указано, устанавливается компилятором. ANSI, как вы говорите в вашем случае.), PathFindFileNameW() (Unicode) и PathFindFileNameA() (ANSI). Здесь - это описание в MSDN.

Я думаю, вам нужно изменить свою строку на эту (в конечном итоге вам тоже нужно позаботиться о filename):

::SetWindowTextW(GetSafeHwnd(), PathFindFileNameW(filename));

Вы говорите, что унаследованы от класса Unicode, поэтому вы не можете использовать следующее.Это может быть для чистого проекта ANSI:

::SetWindowTextA(GetSafeHwnd(), PathFindFileNameA(filename));

или если все не указано:

::SetWindowText(GetSafeHwnd(), PathFindFileName(filename));
0 голосов
/ 23 февраля 2012

В дополнение к правильным ответам выше, относящимся к SetWindowTextA, в качестве общего решения подобных проблем вы можете назначить строку Unicode для CString, которая выполнит преобразование для вас, а затем использовать CString.Скорее всего, это происходит под капотом с полями редактирования.В общем, если вы не указываете специфичные для Unicode или ANSI варианты функции в MFC, вы получите более переносимый код, который будет работать с любым из них.

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