ANSI项目中的SetWindowTextW
SetWindowTextW in an ANSI project
我有一个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。
SetWindowText()/SetWindowTextA()和SetWindowTextW()都是真正的WM_SETTEXT,这是创建多字节/Ansi窗口时少数需要进行代码页翻译的消息之一。这意味着没有W和A版本的消息。
即便如此,在作为Ansi/Multibyte应用程序构建的Vista/Win7标题栏中显示Unicode还是很容易的。您所需要做的就是截取窗口中的WM_SETTEXT消息,并将参数传递给DefWindowProcW(),而不是通常的DefWindowProcA/DefWindowProc()。这是因为在内部所有的窗口实际上都是unicode。
请注意,如果您只是将参数传递给DefWindowProcW(),那么您必须绝对确保该参数确实指向wchar_t字符串。
在我自己的例子中,所有的字符串都被假定为UTF-8字符。这意味着普通ANSI字符串仍然像以前一样工作。当我在窗口中截获WM_SETTEXT消息时,我使用MultiByteToWideChar()将UTF-8字符转换为wchar_t,然后显式地将结果传递给DefWindowProcW()。
好的副作用是它也会在任务栏上显示unicode字符。
XP有一个问题,即使任务栏是,标题栏也不能正确显示。
Tom Nelson的答案可能是最好的,但我刚刚找到了另一个快速解决方案,并想与大家分享:
LONG_PTR originalWndProc = GetWindowLongPtrW(hwnd, GWLP_WNDPROC);
SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR) DefWindowProcW);
SetWindowTextW(hwnd, L"✈✌❦♫");
SetWindowLongPtrW(hwnd, GWLP_WNDPROC, originalWndProc);
如果没有最后一行,我们在调试时会遇到断言错误,尽管单击"忽略"似乎不会引起问题,发布模式也会正常运行。MFC对我们很多人来说仍然是个谜,所以希望这个代码是健全的。
如果您不能将项目转换为Unicode,那么您只能接受这些限制。您的对话框是ANSI对话框。如果愿意,可以使用SetWindowTextW
,但当系统想要绘制对话框时,它将使用ANSI API来获取窗口文本。它将使用ANSI文本绘制GDI函数来执行绘制。如果您想要一个Unicode对话框,您需要为Unicode进行编译。
Microsoft以多种风格定义了许多API函数。PathFindFileName()
有三个版本(未指定,由编译器设置。如您所说。ANSI)、PathFindFileNameW()
(Unicode)和PathFindFileNameA()
(ANSI)。以下是MSDN上的描述。
我认为你需要把你的线路改成这样(最终你也需要处理filename
):
::SetWindowTextW(GetSafeHwnd(), PathFindFileNameW(filename));
您说您派生自Unicode类,因此不能使用以下内容。这将是一个纯粹的ANSI项目:
::SetWindowTextA(GetSafeHwnd(), PathFindFileNameA(filename));
或者如果所有内容都未指定:
::SetWindowText(GetSafeHwnd(), PathFindFileName(filename));
除了上面与SetWindowTextA
有关的正确答案外,作为类似问题的通用解决方案,您可以将unicode字符串分配给将为您执行转换的CString
,然后使用CString。这很可能是在编辑框的掩护下发生的。一般来说,如果您没有在MFC下指定Unicode或ANSI特定的函数变体,那么您将获得更可移植的代码,这些代码可以与任何一个一起使用。