Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SetWindowTextW in an ANSI project

I have an ANSI project. I need to set the titlebar of a CDialog derived class to a Unicode text.

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
}

When the unicode text contains non-ANSI characters however, they display as question marks. I get something like "?????.doc". I have similar problems with static controls, but, curiously enough, with edit boxes SetWindowTextW works.

Oh, and this project is a big legacy project which can't be converted to Unicode.

like image 906
sashoalm Avatar asked Dec 17 '22 03:12

sashoalm


2 Answers

SetWindowText()/SetWindowTextA() and SetWindowTextW() are all really WM_SETTEXT which is one of the few messages subject to code-page translation when you create a multibyte/Ansi window. This means there is no W and A versions of the message.

Even so, it is easy to display Unicode in a Vista/Win7 titlebar built as an Ansi/Multibyte application. All you need to do is intercept the WM_SETTEXT message in your window and pass the arguments to DefWindowProcW() instead of the usual DefWindowProcA/DefWindowProc(). This works because internally all windows are actually unicode.

Note that if you simply pass the arguments to DefWindowProcW() then you must be absolutely sure that the argument really does point to a wchar_t string.

In my own case all char strings are assumed to be UTF-8 characters. This means that normal ANSI strings still work as before. When I intercept the WM_SETTEXT message in the window I convert the UTF-8 char to wchar_t using MultiByteToWideChar() and then explictly pass the result to DefWindowProcW().

The nice side effect is that it will also display the unicode characters on the taskbar too.

XP has an issue where the titlebar is not displayed correctly even though the taskbar is.

like image 166
Tom Nelson Avatar answered Jan 07 '23 17:01

Tom Nelson


Tom Nelson's answer is probably the best, but I just found another quick solution and thought I'd share:

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

Without that last line, we were getting assertion errors when debugging, though clicking Ignore didn't seem to cause problems and Release mode behaved as it should. MFC is still a mystery to a lot of us, so hopefully this code is sound.

like image 24
Michael Buchoff Avatar answered Jan 07 '23 18:01

Michael Buchoff