c++ ANSI项目中的SetWindowTextW

0s0u357o  于 12个月前  发布在  其他
关注(0)|答案(6)|浏览(124)

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

n6lpvg4x

n6lpvg4x1#

SetWindowText()/SetWindowTextA()和SetWindowTextW()实际上都是WM_SETTEXT,这是在创建多字节/Ansi窗口时需要进行代码页转换的少数消息之一。这意味着消息没有W和A版本。
即便如此,在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有一个问题,即标题栏不正确显示,即使是在屏幕上。

jckbn6z7

jckbn6z72#

汤姆纳尔逊的答案可能是最好的,但我只是找到了另一个快速解决方案,并认为我会分享:

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

字符串
如果没有最后一行,我们在调试时会得到Assert错误,尽管单击Ignore似乎不会引起问题,Release模式也会正常运行。MFC对我们很多人来说仍然是一个谜,所以希望这段代码是合理的。

xsuvu9jc

xsuvu9jc3#

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

50few1ms

50few1ms4#

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));

ztigrdn8

ztigrdn85#

另外,您可以直接调用DefWindowProcW(handle,WM_SETTEXT,0,(LPARAM)L”缺省值”);

3pmvbmvn

3pmvbmvn6#

除了上面关于SetWindowTextA的正确答案外,作为类似问题的一般解决方案,您可以将Unicode字符串分配给CString,它将为您执行转换,然后使用CString。这很可能发生在编辑框的后台。通常,如果您不指定MFC下函数的Unicode或ANSI特定变体,你会得到更可移植的代码,它可以与任何一个一起工作。

相关问题