【问题标题】:Is it necessary to destroy a tooltip?是否有必要销毁工具提示?
【发布时间】:2011-01-31 12:22:51
【问题描述】:

在我的应用程序中,我正在处理 WM_HELP 消息,然后使用此方法为控件创建工具提示:

取自:http://msdn.microsoft.com/en-us/library/bb760252(v=vs.85).aspx

HWND CreateToolTip(int toolID, HWND hDlg, PTSTR pszText)
{
    if (!toolID || !hDlg || !pszText)
    {
        return FALSE;
    }
    // Get the window of the tool.
    HWND hwndTool = GetDlgItem(hDlg, toolID);

    // Create the tooltip. g_hInst is the global instance handle.
    HWND hwndTip = CreateWindowEx(NULL, TOOLTIPS_CLASS, NULL,
                              WS_POPUP |TTS_ALWAYSTIP | TTS_BALLOON,
                              CW_USEDEFAULT, CW_USEDEFAULT,
                              CW_USEDEFAULT, CW_USEDEFAULT,
                              hDlg, NULL, 
                              g_hInst, NULL);

   if (!hwndTool || !hwndTip)
   {
       return (HWND)NULL;
   }                              

    // Associate the tooltip with the tool.
    TOOLINFO toolInfo = { 0 };
    toolInfo.cbSize = sizeof(toolInfo);
    toolInfo.hwnd = hDlg;
    toolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
    toolInfo.uId = (UINT_PTR)hwndTool;
    toolInfo.lpszText = pszText;
    SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM)&toolInfo);

    return hwndTip;
}

只要我移动鼠标指针,工具提示就会消失。

我的问题是:

  1. 工具提示是被破坏了还是只是隐藏了?
  2. 如果隐藏了,如何销毁,何时销毁?

谢谢。

【问题讨论】:

    标签: c++ winapi tooltip destroy


    【解决方案1】:

    我已经有一段时间没有进行任何 WinAPI 编程了,但如果我没记错的话......

    CreateWindowEx 的调用将hDlg 作为hWndParent 参数传递,这意味着对话框窗口现在是工具提示的父级。

    从关于 DestroyWindow 函数的 MSDN 文档中它说:

    如果指定的窗口是父窗口或所有者窗口,则 DestroyWindow 在销毁父窗口或所有者窗口时会自动销毁关联的子窗口或拥有的窗口。该函数首先销毁子窗口或拥有的窗口,然后销毁父窗口或所有者窗口。

    因此您可以假设您的工具提示窗口将被销毁最终。如果您调用CreateToolTip 来响应每条WM_HELP 消息,请小心,因为在您关闭对话框并最终调用DestroyWindow 之前,内存中会出现许多工具提示窗口。

    正如 vz0 指出的那样,您可以创建一次工具提示,挂在窗口句柄上,然后显示工具提示以响应帮助消息,而不是再次创建它。

    在您对 vz0 的回答的评论中,您说:

    工具提示有多种失效方式。例如:鼠标移动、超时等

    所有这些只会导致窗口被隐藏,因此工具提示的句柄仍然有效,并且可以使用 ShowWindow 重新显示。

    【讨论】:

    • 谢谢:)。其实我想通了。这个 msdn 论坛链接很有帮助 (social.msdn.microsoft.com/Forums/en-US/vssmartdevicesnative/…)。通过它之后,我为工具提示编写了一个包装类并重用了工具提示窗口。同样,一旦实例超出范围,我就会破坏析构函数中的工具提示。将您的答案标记为已接受。再次感谢:)。
    • 实际上,您需要销毁它。它不是一个子窗口或拥有,正如人们所假设的那样。我刚刚经历了艰难的方式(尽管“父级”被破坏了数百个工具提示窗口),可能取决于它的创建方式。为了安全起见(为了对称):去做吧。
    • 顺便说一句:SPY++ 对查找窗口及其状态(隐藏/显示、大小...)有很大帮助
    • @chksr - 当你创建工具提示窗口时,你传递了HWND hWndParentCreateWindowEx 函数的参数 9?如果没有,传递 NULL,意味着你必须销毁工具提示自己开窗。
    • 虽然我当然传递了一个父级,但当父级离开时工具提示并没有被破坏......或者至少,我可能会在一个窗口上附加几个工具提示,并不是所有的都是被摧毁。我没有进一步检查,我很高兴我摆脱了在我的窗口上悬停一段时间后创建的数百个工具提示窗口......;)
    【解决方案2】:

    对于每个CreateWindowEx 呼叫,您都需要一个匹配的DestroyWindow 呼叫。

    作为替代方案,您可以使用带有SW_SHOWSW_HIDEShowWindow 调用来显示和隐藏弹出窗口,而不是每次都创建和销毁窗口。

    【讨论】:

    • 您能否解释一下“这如何适合工具提示场景?”。因为工具提示有多种方式消失。例如:鼠标移动、超时等。如何处理所有情况。
    【解决方案3】:

    根据我的经验,我必须在工具提示上使用DestroyWindow(),以便正确释放HFONT(字体 GDI 资源)。一次有两个窗口的父子关系 - 但我的系统在运行时改变了这一点,可能是罪魁祸首。如果您的系统将其泛化,这样做可能没有害处。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-06
      相关资源
      最近更新 更多