Unicode 工具提示未显示

Posted

技术标签:

【中文标题】Unicode 工具提示未显示【英文标题】:Unicode tooltips not showing up 【发布时间】:2010-03-30 13:47:46 【问题描述】:

我试图在我的应用程序窗口中显示 unicode 工具提示,但它们似乎没有显示。非 unicode 文本正确显示,但只要我尝试执行 unicode,就不会显示任何工具提示。以下是我目前正在做的事情,感谢您的帮助。

     HWND parentHwnd = pickInfo->getViewer().getCachedHwnd();
  CWnd *pWnd = CWnd::FromHandlePermanent(parentHwnd);
  HINSTANCE hInstance = GetModuleHandle(NULL);

  if (isUnicode)
   m_toolInfoW.lpszText = L"This tooltip does not show up at all.";
  else
   m_toolInfoA.lpszText = "Non unicode text";

  if (!m_bTooltipInitialized)
   ::SendMessage(m_tooltipHwnd, WM_DESTROY, 0,0);

   if(isUnicode)
    m_tooltipHwnd = CreateWindowExW(WS_EX_TOPMOST,
     TOOLTIPS_CLASSW, NULL,
     WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,  
     CW_USEDEFAULT, CW_USEDEFAULT,
     CW_USEDEFAULT, CW_USEDEFAULT,
     parentHwnd, NULL, hInstance, NULL);
   else 
    m_tooltipHwnd = CreateWindowEx(WS_EX_TOPMOST,
     TOOLTIPS_CLASS, NULL,
     WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,  
     CW_USEDEFAULT, CW_USEDEFAULT,
     CW_USEDEFAULT, CW_USEDEFAULT,
     parentHwnd, NULL, hInstance, NULL);

   if (GetLastError() != 0)
    return;

   ::SetWindowPos(m_tooltipHwnd, HWND_TOPMOST,
    0, 0, 0, 0,
    SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);

   // Set the max text width before multi-line tooltip is used.
   ::SendMessage(m_tooltipHwnd, TTM_SETMAXTIPWIDTH, 0, m_nMaxWinTooltipWidth);

   if (isUnicode)
    m_toolInfoW.uFlags = TTF_SUBCLASS | TTF_IDISHWND | TTF_TRACK;
    m_toolInfoW.hinst = hInstance;
    m_toolInfoW.hwnd = parentHwnd;
    m_toolInfoW.uId = (UINT_PTR)parentHwnd;
    ::GetClientRect (parentHwnd, &m_toolInfoW.rect);

    ::SendMessage(m_tooltipHwnd, TTM_ADDTOOLW, 0, (LPARAM) (LPTOOLINFOW) &m_toolInfoW);
    ::SendMessage(m_tooltipHwnd, TTM_ACTIVATE, TRUE, (LPARAM)(LPTOOLINFOW) &m_toolInfoW);
   
   else
    m_toolInfoA.uFlags = TTF_SUBCLASS | TTF_IDISHWND;
    m_toolInfoA.hinst = hInstance;
    m_toolInfoA.hwnd = parentHwnd;
    m_toolInfoA.uId = (UINT_PTR)parentHwnd;
    ::GetClientRect (parentHwnd, &m_toolInfoA.rect);

    ::SendMessage(m_tooltipHwnd, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &m_toolInfoA);
    ::SendMessage(m_tooltipHwnd, TTM_ACTIVATE, TRUE, (LPARAM)(LPTOOLINFO) &m_toolInfoA);
   
   m_bTooltipInitialized = true;
  

  if (isUnicode)
   ::SendMessage(m_tooltipHwnd, TTM_UPDATETIPTEXTW, 0, (LPARAM) (LPTOOLINFOW) &m_toolInfoW);
  else
   ::SendMessage(m_tooltipHwnd, TTM_UPDATETIPTEXT, 0, (LPARAM) (LPTOOLINFO) &m_toolInfoA);

  //Repaint the screen so that the area beneath the previous location of the tooltip is restored correctly.
  ::UpdateWindow(pWnd->GetParentOwner()->GetSafeHwnd());
  pWnd = NULL;

【问题讨论】:

【参考方案1】:

问题是您尝试使用通用控件版本 6,但您无法使用它。

更多细节,

typedef struct tagTOOLINFOW 
    UINT cbSize;
    UINT uFlags;
    HWND hwnd;
    UINT_PTR uId;
    RECT rect;
    HINSTANCE hinst;
    LPWSTR lpszText;
    LPARAM lParam;
#if (NTDDI_VERSION >= NTDDI_WINXP)
    void *lpReserved;
#endif
 TTTOOLINFOW, NEAR *PTOOLINFOW, *LPTTTOOLINFOW;

对于 xp+,头文件 CommCtrl.h 假定您将使用 comctl 版本 6,但如果您没有明确 使用清单文件启用它,您仍将使用旧的 comctl 版本 5 。X。那么问题来了,5.x 版本的 TOOLINFO 的大小与 6.x 版本不同。

所以如果你需要在windows xp+下使用comctl version 5,你应该用下面的代码来初始化TOOLINFO,

TOOLINFO ti;
ti.cbSize = sizeof(TOOLINFO) - 4;

否则,您应该使用清单文件或 prgram 指令启用视觉样式外观:

#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

最后,我建议您始终在 xp+ 中启用视觉外观。以下是视觉效果对比:

注意:如果你使用 ANSI/MBCS 编译程序,sizeof(TOOLINFO) 将是 48,这已经删除了 lpReserved 成员。所以 ANSI 版本可以工作,但 UNICODE 会失败。

【讨论】:

非常感谢。我在 Windows 7 上使用 VS2008 尝试来自 MSDN 的简单工具提示示例代码,但很快遇到 ANSI 构建显示工具提示但 Unicode 构建从未出现的问题。发送 TTM_ADDTOOL 返回 0(失败)。我通过谷歌搜索到你的帖子并得到了确切的答案。微软的一大优势!但我仍然无法解释为什么 ANSI 构建不会触发错误。如果 M$ comctl32 pre-6.0 代码从调用者检查不兼容的TOOLINFO.cbSize,则 ANSI 和 Unicode 应该表现出相同的行为。【参考方案2】:

上面的 Jichao 提供了很好的解释和解决方案,但是硬连接 TOOLINFO 结构的大小只会修复工具提示。如果问题是该程序是使用通用控件 6.0+ 编译的,但可能在(例如)具有 6.0+ 的 Windows XP 系统上运行,要么未安装,要么未完全安装(就像有人安装了 IE,但从未使用过或更新它),那么更通用的解决方案是将应用程序限制为仅使用 5.x 通用控件。

正如here 所见,除了工具提示之外,还有更多的结构大小变化。

为了确保一切都可以在 Windows XP 上运行,我所做的是将以下内容放在我的程序的最顶部,在任何包含之前(在 Visual Studio 的情况下,一个好的位置应该是在 targetver.h 的顶部如果你有):

#define _WIN32_WINNT    0x0500

【讨论】:

【参考方案3】:

在 Unicode 情况下,您有 TTF_TRACK,我认为这需要您手动显示或隐藏工具提示。在 ANSI 情况下,您没有该选项。

http://msdn.microsoft.com/en-us/library/bb760252(VS.85).aspx

向下滚动到“实施跟踪工具提示”。

【讨论】:

感谢您注意到这一点。你是对的,不应该在那里,我在测试时忘记删除它。但是,这并不能解决我的问题。没有该标志,仍然不会显示工具提示。 父窗口也是 Unicode 吗?也许在使用 Unicode 工具提示和 ANSI 父窗口之间存在不兼容。

以上是关于Unicode 工具提示未显示的主要内容,如果未能解决你的问题,请参考以下文章

Unicode ☰ 汉堡包未在 Android 和 Chrome 中显示

Bangla unicode 字体未在 mpdf 中显示

Unicode 字体在 Chrome 上未正确显示

孟加拉语文本未显示在Unicode CSV文件中

在 Linux 上预览 unicode 字体

如何将unicode转换成汉字