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.
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.
If you can't convert the project to Unicode then you will just have to accept the limitations. Your dialog is an ANSI dialog. You can use
SetWindowTextW
if you like, but when the system wants to paint the dialog it is going to use the ANSI API to obtain the window text. It is going to use the ANSI text drawing GDI functions to perform the painting. If you want a Unicode dialog, you need to compile for Unicode.Tom Nelson's answer is probably the best, but I just found another quick solution and thought I'd share:
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.
Microsoft defines many of the API functions in several flavors. There are three versions of
PathFindFileName()
(unspecified, set by the compiler. ANSI as you say in your case.),PathFindFileNameW()
(Unicode) andPathFindFileNameA()
(ANSI). Here is the description at MSDN.I think you need to change your line to this (eventually you need to take care of
filename
too):You say you derive from a Unicode class, therefore you cannot use the following. This would be for a pure ANSI project:
or if everything is left unspecified:
In addition to the correct answers above relating to
SetWindowTextA
, as a general solution to similar problems, you can assign a unicode string to aCString
which will perform the conversion for you, and then use the CString. This is most likely happening under the hood with the edit boxes. In general, if you don't specify Unicode or ANSI specific variants of the function under MFC, you get the more portable code which will work with either.