1

我在使用 unicode 格式的动态文本提供 Win32 工具提示控件时遇到了一些麻烦。我使用以下代码来设置控件:

INITCOMMONCONTROLSEX icc;
icc.dwSize = sizeof(INITCOMMONCONTROLSEX);
icc.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&icc);

HWND hwnd_tip = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, 
  WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP, 
  CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  NULL, NULL, hinst, NULL
);
SetWindowPos(hwnd_tip, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);

TOOLINFOW ti;
memset(&ti, 0, sizeof(TOOLINFOW));
ti.cbSize = sizeof(TOOLINFOW);
ti.hwnd = hwnd_main;
ti.uId = (UINT) hwnd_control;
ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
ti.lpszText = L"This tip is shown correctly, including unicode characters.";
SendMessageW(hwnd_tip, TTM_ADDTOOLW, 0, (LPARAM) &ti);

只要我在ti.lpszText. 但是,我希望文本是动态的,所以我设置ti.lpszTextLPSTR_TEXTCALLBACKW处理我的 WindowProc() 中的回调,如下所示:

...
case WM_NOTIFY:
{
  NMHDR *nm = (NMHDR *) lParam;
  switch (nm->code)
  {
    case TTN_GETDISPINFOW:
    {
      static std::wstring tip_string = L"Some random unicode string.";
      NMTTDISPINFOW *nmtdi = (NMTTDISPINFOW *) lParam;              
      nmtdi->lpszText = (LPWSTR) tip_string.c_str();
    }
    break;
  }
}
break;
...

这不起作用,因为我从未收到过TTN_GETDISPINOW消息。(注意:如果我处理它TTN_GETDISPINFO并使用它NMTTDISPINFO来提供一个 char 数组,那么它就可以工作,但是没有 unicode 支持......)

我猜我在这里的设置或消息处理中做错了什么?有关如何正确执行此操作的任何建议?

更新
另请注意,我的项目不是在 unicoe 模式下编译的(即未定义 _UNICODE 并且项目设置为使用多字节字符集)。这是故意的,我想保持这种状态,因为我不想重写整个应用程序以支持 unicode(至少现在还没有)。由于 _UNICODE 定义用于选择各种函数和数据结构的 *W 版本,我希望通过在我的代码中显式使用这些实现相同的结果,如上所示。

4

3 回答 3

3

您收到 TTN_GETDISPINFO 通知代码但未收到 TTN_GETDISPINFOW 的事实表明您的项目设置为“使用多字节字符集”。

检查项目属性页:“配置属性”->“常规”->“字符集”
此属性应设置为“使用 Unicode 字符集”。

于 2009-06-14T15:24:39.090 回答
3

感谢罗伯特斯科特链接。我现在找到了解决方法。

简而言之,诀窍是确保接收窗口是一个 unicode 窗口并为其注册一个 unicode 窗口过程。

问题是我没有WindowProc()处理TTN_GETDISPINFOW通知消息的父窗口的 unicode。由于这个窗口(类)是用RegisterClassEx()/CreateWindowEx() and not RegisterClassExW()/CreateWindowExW(), it did not have registered window procedure for unicode messages.

To get around the problem I changed ti.hwnd from hwnd_main to hwnd_control when sending TTM_ADDTOOLW, resulting in the control's window procedure receving the notifications instead of its parent. In order to intercept the unicode events now sent to the control's window procedure, I subclassed it using SetWindowLongW(hwnd_control, GWL_WNDPROC, (LONG) NewControlWndProc).

请注意,hwnd_control 是使用 CreateWindowExW() 创建的标准“LISTBOX”窗口,因此可以识别 unicode,因为系统会自动在 unicode 和 ANSI 版本中注册所有内置 Windows 类。

于 2009-06-14T21:26:58.113 回答
1

您的整个应用程序是否使用 unicode?否则,您可能会阅读此“Microsoft 文章”。尤其是“启用 Unicode 的十二个步骤”部分。

或者像这个人一样尝试

罗伯特·斯科特 Unicode 工具提示

于 2009-06-14T15:15:35.867 回答