Windows 标准控件ToolTips简要介绍
参考文档 MSDN
https://msdn.microsoft.com/en-us/library/ff486072(v=vs.85).aspx
一,什么是ToolTips
ToolTips 就是一个类似于一个悬浮的文本框,在鼠标指针移动上去能显示特定的文本。
各种ToolTips样式。
二,创建ToolTips
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);
此后ToolTips的窗口函数自动维护Tooltips的尺寸,位置和显示隐藏状态等。 ToolTips的高度基于所设置的字体的高度。
1.激活ToolTips
Tooltips可以处于激活和未激活的状态。激活状态下ToolTips会显示文本。 当ToolTips未激活,其文本讲不被显示。即使鼠标指针放在一个Tools上发送TTM_ACTIVE可以激活和关闭激活一个ToolTips的状态。
2.将ToolTips关联Tools
创建一个TOOLINFO的结构体对象,设置uID为关联工具的ID
设置uFlags为 TTF_IDISHWND
并发送TTM_ADDTOOL消息给ToolTips的句柄。后面的完整的例子。
3.显示文本
默认使用TOOLINFO的 lpszText为显示问题。 可以发送TTM_UPDATETIPTEXT消息来更新显示值。
如果将lpszText 设置为 LPSTR_TEXTCALLBACK ToolTips需要显示文本时候,会Call之前注册的父窗口句柄的窗口函数并发送 TTN_GETDISPINFO通知码,
该消息包含了指向NMTTDISPINFO 结构的指针用于修改相应的文本,以供后续显示使用。
4.消息和通知
windows默认只发送消息给包含鼠标指针的窗口,并不会发送消息给ToolTips。因此需要关联ToolTips和其对应的父窗口活控件ID来控制其显示(恰当的位置和恰当的时间)。
ToolTips会自动处理一下的消息。
1.通过TOOLINFO绑定过的控件或者父窗口的矩形区域。
2.绑定ToolTip的父窗口在同一个线程内。
满足以上两个条件 将TOOLINFO的uFlags设置为 TTF_SUBCLASS 然后发送TTM_ADDTOOL消息给Tooltip的句柄。 但是ToolTips和关联的窗口必须有直接的消息通路。也就是父窗口和子窗口的关系。 如果你关联了别的进程的窗口,还是收不到消息的。可能要使用HOOK。此时你应该发送TTM_RELAYEVENT消息给tooltip 参考Tracking Tooltip
当Tooltip要显示的时候会发送给其拥有者窗口TTN_SHOW通知码。 TTN_POP表明Tooltip即将要隐藏。 通过WM_NOTIFY消息发送。
三,ToolTips应用
1.一个简单的ToolTips的例子
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include "resource.h"
#pragma comment(lib, "comctl32.lib")
LRESULT CALLBACK MyDlgProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE g_hInst;
HWND hTTWnd;
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
{
g_hInst = hInstance;
INITCOMMONCONTROLSEX cx = { sizeof(INITCOMMONCONTROLSEX), ICC_BAR_CLASSES };
BOOL ret = InitCommonControlsEx(&cx);
return DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, (DLGPROC)MyDlgProc);
}
// Description:
// Creates a tooltip for an item in a dialog box.
// Parameters:
// idTool - identifier of an dialog box item.
// nDlg - window handle of the dialog box.
// pszText - string to use as the tooltip text.
// Returns:
// The handle to the tooltip.
//
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;
}
void CreateToolTipForRect(HWND hwndParent)
{
// Create a tooltip.
HWND hwndTT = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL,
WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
hwndParent, NULL, g_hInst, NULL);
SetWindowPos(hwndTT, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
// Set up "tool" information. In this case, the "tool" is the entire parent window.
TOOLINFO ti = { 0 };
ti.cbSize = sizeof(TOOLINFO);
ti.uFlags = TTF_SUBCLASS;
ti.hwnd = hwndParent;
ti.hinst = g_hInst;
ti.lpszText = TEXT("This is your tooltip string.");
GetClientRect(hwndParent, &ti.rect);
// Associate the tooltip with the "tool" window.
SendMessage(hwndTT, TTM_ADDTOOL, 0, (LPARAM)(LPTOOLINFO)&ti);
}
LRESULT CALLBACK MyDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_INITDIALOG:
{
CreateToolTipForRect(hDlg);
break;
}
case WM_CLOSE:
EndDialog(hDlg, FALSE);
break;
}
return FALSE;
}
这个代码很简单就是在Windows对话框上显示ToolTips。可是编译以后死活不显示,初始化InitCommonControlsEx的调用也没有问题。观察到自己创建的对话框风格非常复古。
和MSDN上的大相径庭。
后来查阅相关资料。这是由于项目缺少了Manifest定义。在网上找了一个Manifest的定义文件在项目加载此文件就解决了此问题。关于Manifest文件的定义参考此文章
MSDN: Enable Visual Style in your program.
https://msdn.microsoft.com/en-us/library/windows/desktop/bb773175(v=vs.85).aspx#no_extensions
Windows.Manifest定义如下
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
name="Microsoft.Windows.XXXX"
processorArchitecture="x86"
version="5.1.0.0"
type="win32"/>
<description>Windows Shell</description>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="x86"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>
运行结果如下。