ANSI项目中的SetWindowTextW

SetWindowTextW in an ANSI project

本文关键字:SetWindowTextW 项目 ANSI      更新时间:2023-10-16

我有一个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特定的函数变体,那么您将获得更可移植的代码,这些代码可以与任何一个一起使用。