我有一个 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 字符串。
在我自己的例子中,所有 char 字符串都被假定为 UTF-8 字符。这意味着普通的 ANSI 字符串仍然像以前一样工作。当我在窗口中拦截 WM_SETTEXT 消息时,我使用 MultiByteToWideChar() 将 UTF-8 字符转换为 wchar_t,然后将结果显式传递给 DefWindowProcW()。
好的副作用是它也会在任务栏上显示 unicode 字符。
XP 存在一个问题,即使任务栏显示,标题栏也无法正确显示。
汤姆·尼尔森的答案可能是最好的,但我刚刚找到了另一个快速解决方案并认为我会分享:
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 特定变体,您将获得可与其中任何一个一起使用的更可移植的代码。
另外,你可以直接调用 DefWindowProcW(handle, WM_SETTEXT, 0, (LPARAM)L"✈✌❦♫");