ANSI项目中的SetWindowTextW

时间:2012-02-23 09:55:06

标签: c++ winapi unicode mfc

我有一个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。

5 个答案:

答案 0 :(得分:6)

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有一个问题,即使任务栏是。

,标题栏也无法正确显示

答案 1 :(得分:2)

如果您无法将项目转换为Unicode,那么您只需要接受这些限制。您的对话框是ANSI对话框。如果您愿意,可以使用SetWindowTextW,但是当系统想要绘制对话框时,它将使用ANSI API来获取窗口文本。它将使用ANSI文本绘图GDI函数来执行绘制。如果需要Unicode对话框,则需要编译Unicode。

答案 2 :(得分:2)

汤姆尼尔森的答案可能是最好的,但我刚刚找到另一个快速的解决方案并且认为我会分享:

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

如果没有最后一行,我们在调试时会遇到断言错误,尽管单击忽略似乎不会导致问题,而释放模式的行为应该如此。 MFC对我们很多人来说仍然是个谜,所以希望这段代码合理。

答案 3 :(得分:1)

Microsoft以多种方式定义了许多API函数。 PathFindFileName()有三个版本(未指定,由编译器设置。在您的情况下为ANSI。),PathFindFileNameW()(Unicode)和PathFindFileNameA()(ANSI)。 Here是MSDN上的描述。

我认为你需要改变你的行(最终你需要照顾filename):

::SetWindowTextW(GetSafeHwnd(), PathFindFileNameW(filename));

您说您派生自Unicode类,因此您无法使用以下内容。这将是一个纯ANSI项目:

::SetWindowTextA(GetSafeHwnd(), PathFindFileNameA(filename));

或者如果未指定所有内容:

::SetWindowText(GetSafeHwnd(), PathFindFileName(filename));

答案 4 :(得分:0)

除了上面与SetWindowTextA相关的正确答案之外,作为类似问题的一般解决方案,您可以将一个unicode字符串分配给CString,它将为您执行转换,然后使用CString。这很可能发生在编辑框的引擎盖下。通常,如果您没有在MFC下指定函数的Unicode或ANSI特定变体,那么您将获得更易于使用的可移植代码。