代码之家  ›  专栏  ›  技术社区  ›  Anders Sandvig

如何使用动态Unicode文本设置win32工具提示控件?

  •  0
  • Anders Sandvig  · 技术社区  · 15 年前

    我在用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 . 但是,我希望文本是动态的,因此我设置 T.LPSZ文本 LPSTR_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 提供一个字符数组,但不支持Unicode…)

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

    更新
    还要注意,我的项目不是在unicoe模式下编译的(即,没有定义nicode,并且项目设置为使用多字节字符集)。这是有意的,我希望保持这样的状态,因为我不想重写整个应用程序以了解Unicode(至少还没有)。由于_unicode define用于选择各种函数和数据结构的*w版本,我希望通过在代码中显式使用这些函数和数据结构,可以获得相同的结果,如上图所示。

    3 回复  |  直到 15 年前
        1
  •  3
  •   Volker Voecking    15 年前

    得到ttn_getdispinfo通知代码而不是ttn_getdispinfow的事实表明您的项目设置为“使用多字节字符集”。

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

        2
  •  3
  •   Anders Sandvig    15 年前

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

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

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

    为了解决这个问题我改变了 ti.hwnd hwnd_main hwnd_control 发送ttm_addtoolw时,导致控件的窗口过程接收通知,而不是其父进程。为了拦截现在发送到控件窗口过程的Unicode事件,我使用setWindowLongW(hwnd_control,gwl_wndproc,(long)newControlWndProc)对其进行了子类化。

    请注意,hwnd_控件是用createWindowExw()创建的标准“列表框”窗口,因此具有Unicode意识,因为Windows类中的所有buildt都由系统以Unicode和ANSI版本自动注册。

        3
  •  1
  •   jitter    15 年前

    整个应用程序是否使用Unicode?否则你可以读这个 "Microsoft article" . 特别是 “12步到Unicode启用” 部分。

    或者像这家伙那样尝试

    Robert Scott Unicode Tooltips