关于工具提示控件

当用户将鼠标指针停在工具或其他用户界面元素上时,工具提示就会自动出现或弹出。 工具提示会出现在指针附近,当用户单击鼠标按钮、将指针从工具上移开或等待几秒钟后,工具提示就会消失。

下图中的工具提示控件会显示有关 Windows 桌面上文件的信息。 当鼠标移到图示上时,还会显示一个包含描述性文字的实时工具提示。

screen shot showing text in a tooltip that appears over a file on the desktop

本节将介绍工具提示控件的工作原理和创建方法。

工具提示行为和外观

工具提示控件可以显示单行文本或多行文本。 它们的边角可以是圆的,也可以是方的。 它们可能有也可能没有像卡通语音气球那样指向工具的箭头。 工具提示文本可以是静止的,也可以随鼠标指针移动(称为跟踪)。 静态文本可以在工具旁边显示,也可以在工具上方显示,而这被称为就地显示。 标准工具提示是固定的,只会显示一行文字,四角为方形,并且没有指向工具的箭头。

通用控件版本 4.70 支持跟踪工具提示,可以动态更改屏幕上的位置。 通过快速更新位置,这些工具提示控件看起来会平滑移动或“跟踪”。如果希望工具提示文本跟随鼠标指针的位置移动,这些控件就非常有用。 有关跟踪工具提示的详细信息,以及如何创建跟踪工具提示的代码示例,请参阅跟踪工具提示

版本 4.70 常用控件也支持多行工具提示,可在多行上显示文本。 这对显示冗长的信息非常有用。 有关创建多行工具提示的详细信息和示例,请参阅多行工具提示

气球工具提示显示在一个带有圆角和指向工具的箭头的框中。 它们可以包含单行或多行。 下图显示了一个气球工具提示,其箭头和矩形处于默认位置。 有关气球工具提示的更多信息,以及如何创建气球工具提示的示例,请参阅使用工具提示控件

screen shot showing a tooltip containing one line of text, positioned above a button on a dialog box

工具提示还可以包含标题文本和图标,如下图所示。 请注意,工具提示必须包含文本;如果只有标题文本,则工具提示将不会显示。 此外,除非有标题,否则图标不会出现。

screen shot showing a tooltip with an icon, title, and text, positioned below a button on a dialog box

有时,由于文本字符串太长,无法在小窗口中完整显示,因此它们会被剪切。 就地工具提示用于显示已剪切对象的文本字符串,例如下图中的文件名。 有关如何创建就地工具提示的示例,请参阅就地工具提示

screen shot showing a tooltip containing a file name positioned next to a file icon in a tree control

光标必须悬停在工具上一段时间后才会出现工具提示。 此超时的默认持续时间由用户的双击时间控制,通常约为半秒。 要指定非默认超时值,请向工具提示控件发送 TTM_SETDELAYTIME 消息。

创建工具提示控件

要创建工具提示控件,请调用 CreateWindowEx 并指定 TOOLTIPS_CLASS 窗口类。 此类会在加载通用控制 DLL 时注册。 为确保加载此 DLL,请在应用程序中包含 InitCommonControlsEx 函数。 必须将工具提示控件显式定义为最顶层。 否则,它可能会被父窗口所覆盖。 以下代码片段展示了如何创建工具提示控件。

HWND hwndTip = CreateWindowEx(NULL, TOOLTIPS_CLASS, NULL,
                            WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
                            CW_USEDEFAULT, CW_USEDEFAULT,
                            CW_USEDEFAULT, CW_USEDEFAULT,
                            hwndParent, NULL, hinstMyDll,
                            NULL);

SetWindowPos(hwndTip, HWND_TOPMOST,0, 0, 0, 0,
             SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);

工具提示控件的窗口程序会自动设置控件的大小、位置和可见性。 工具提示窗口的高度取决于当前在设备上下文中为工具提示控件选择的字体高度。 宽度会随工具提示窗口中当前字符串的长度而变化。

激活工具提示控件

工具提示控件可以是活动的,也可以是非活动的。 如果处于活动这条,当鼠标指针位于工具上时,就会出现工具提示文本。 当处于非活动状态时,即使指针位于工具上,也不会显示工具提示文本。 TTM_ACTIVATE 消息可激活或取消激活工具提示控件。

支持工具

工具提示控件可以支持任意数量的工具。 要支持特定工具,必须通过向工具提示控件发送 TTM_ADDTOOL 消息,在工具提示控件中注册该工具。 该消息包括 TOOLINFO 结构的地址,而该结构提供了工具提示控件显示工具文本所需的信息。 TOOLINFO 结构中的 uID 成员由应用程序定义。 每次添加工具时,应用程序都会提供一个唯一的标识符。 需要使用 TOOLINFO 结构中的 cbSize 成员,该成员必须指定结构的大小。

工具提示控件支持作为窗口(如子窗口或控制窗口)和窗口客户区内的矩形区域实现的工具。 在添加作为矩形区域实现的工具时,TOOLINFO 结构中的 hwnd 成员必须指定包含该区域的窗口句柄,而 rect 成员必须指定该区域边界矩形的客户坐标。 此外,uID 成员还必须指定应用程序定义的工具标识符。

在添加作为窗口实现的工具时,TOOLINFO 结构的 uID 成员必须包含工具的窗口句柄。 此外,uFlags 成员必须指定 TTF_IDISHWND 值,该值将告诉工具提示控件将 uID 成员解释为窗口句柄。

显示文本

在向工具提示控件添加工具时,TOOLINFO 结构的 lpszText 成员必须指定要显示的工具字符串的地址。 在添加工具后,可以使用 TTM_UPDATETIPTEXT 消息来更改文本。

如果 lpszText 的高序字为零,则低序字就必须是字符串资源的标识符。 当工具提示控件需要文本时,系统会从 TOOLINFO 结构的 hinst 成员标识的应用程序实例中加载指定的字符串资源。

如果在 lpszText 成员中指定了 LPSTR_TEXTCALLBACK 值,则工具提示控件会在需要显示工具文本时通知 TOOLINFO 结构的 hwnd 成员中指定的窗口。 工具提示控件会向窗口发送 TTN_GETDISPINFO 通知代码。 该消息包括 NMTTDISPINFO 结构的地址,其中包含窗口句柄以及应用程序定义的工具标识符。 该窗口会检查结构以确定需要文本的工具,并在适当的结构成员中填充工具提示控件显示字符串所需的信息。

注意

标准工具提示文本的最大长度为 80 个字符。 有关详细信息,请参阅 NMTTDISPINFO 结构。 多行工具提示文本可以更长。

 

很多应用程序都会创建工具栏,其中包含与菜单命令相对应的工具。 对于此类工具,工具提示控件可以方便地显示与相应菜单项相同的文本。 除非控件具有 TTS_NOPREFIX 样式,否则系统会自动从传递给工具提示控件的所有字符串中删除 and 符号 (&) 加速键,并在第一个制表符 (\t) 处终止字符串。

要检索工具的文本,请使用 TTM_GETTEXT 消息。

消息传送和通知

工具提示文本通常在鼠标指针悬停在某个区域(通常是按钮控件等工具定义的矩形区域)时显示。 但是,Microsoft Windows 只会向包含指针的窗口发送与鼠标相关的信息,而不是工具提示控件本身。 与鼠标相关的信息必须传递给工具提示控件,以便它在适当的时间和位置显示工具提示文本。

您可以在以下情况下自动转发消息:

  • 工具是一个控件,或者在工具的 TOOLINFO 结构中被定义为一个矩形。
  • 工具关联的窗口与工具提示控件位于同一线程中。

如果满足这两个条件,则在使用 TTM_ADDTOOL 将工具添加到工具提示控件时,请在工具的 TOOLINFO 结构的 uFlags 成员中设置 TTF_SUBCLASS 标志。 然后,必要的鼠标消息会被自动转发给工具提示控件。

设置 TTF_SUBCLASS 以便将鼠标信息转发给控制器,这足以满足大多数情况的需要。 但是,如果工具提示控件与工具窗口之间没有直接连接,则它不起作用。 例如,如果工具是作为应用程序定义窗口中的一个矩形区域来实现的,那么窗口过程就会接收鼠标信息。 设置 TTF_SUBCLASS 即可确保将它们传递给控件。 不过,如果工具是作为系统定义的窗口实现的,则鼠标信息将被发送到该窗口,而应用程序将无法直接使用。 在这种情况下,必须要么子类化窗口,要么使用消息挂钩来访问鼠标消息。 然后,必须使用 TTM_RELAYEVENT 将鼠标信息显式转发给工具提示控件。 有关如何使用 TTM_RELAYEVENT 的示例,请参阅跟踪工具提示

当工具提示控件收到 WM_MOUSEMOVE 消息时,它会确定鼠标指针是否位于工具的边界矩形内。 如果是,工具提示控件就会设置一个计时器。 在超时间隔结束时,工具提示控件会检查指针的位置,确认它是否已经移动。 如果没有,工具提示控件就会检索工具的文本并显示工具提示。 工具提示控件将继续显示窗口,直到收到转发的按钮释放或按钮按下消息,或者收到 WM_MOUSEMOVE 消息指示指针已移出工具的边界矩形为止。

工具提示控件实际上有三种与之关联的超时持续时间。 初始持续时间是指在显示工具提示窗口之前,鼠标指针必须在工具的边界矩形内保持静止的时间。 重新显示持续时间是指当指针从一个工具移动到另一个工具时,显示后续工具提示窗口之前的延迟时长。 弹出持续时间是工具提示窗口在隐藏之前的显示时间。 也就是说,如果在工具提示窗口显示后指针仍停留在边界矩形内,则工具提示窗口就会在弹出持续时间结束时自动隐藏。 可以使用 TTM_SETDELAYTIME 消息来调整所有超时持续时间。

如果应用程序包含以矩形区域形式实现的工具,而控件的大小或位置发生了变化,则应用程序可以使用 TTM_NEWTOOLRECT 消息来报告工具提示控件的变化。 应用程序无需报告作为窗口实施的工具的大小和位置变化,因为工具提示控件会使用工具的窗口句柄来确定鼠标指针是否在工具上,而不是工具的边界矩形。

在即将显示工具提示时,工具提示控件会向所有者窗口发送 TTN_SHOW 通知代码。 当工具提示即将被隐藏时,所有者窗口会收到一个 TTN_POP 通知代码。 每个通知代码都是在 WM_NOTIFY 消息的上下文中发送的。

命中测试

通过 TTM_HITTEST 消息可以检索工具提示控件维护的有关占用特定点的工具的信息。 该消息包括一个 TTHITTESTINFO 结构,其中包含一个窗口句柄、一个点坐标和一个 TOOLINFO 结构的地址。 工具提示控件会确定是否有工具占用该点,如有,则会在 TOOLINFO 中填充有关该工具的信息。

默认消息处理

下表列出了窗口过程为工具提示控件处理的消息。

消息 说明
WM_CREATE 确保工具提示控件具有 WS_EX_TOOLWINDOWWS_POPUP 窗口样式。 它还会分配内存并初始化内部变量。
WM_DESTROY 释放为工具提示控件分配的资源。
WM_GETFONT 返回工具提示控件用于绘制文本的字体句柄。
WM_MOUSEMOVE 隐藏工具提示窗口。
WM_PAINT 绘制工具提示窗口。
WM_SETFONT 设置工具提示控件用于绘制文本的字体句柄。
WM_TIMER 如果工具改变了位置,或者鼠标指针移出了工具,则隐藏工具提示窗口。 否则,它会显示工具提示窗口。
WM_WININICHANGE 重置基于系统指标的内部变量。