以下示例包括一组应用程序定义的函数,用于实现对话框的工具提示控件。DoCreateDialogTooltip函数创建一个工具提示控件,并使用EnumChildWindows函数枚举对话框中的控件。枚举程序EnumChildProc使用工具提示控件注册每个控件。该过程将对话框指定为每个工具提示控件的父窗口,并为每个工具提示控件包含LPSTR_TEXTCALLBACK值。因此,每当工具提示控件需要控件的文本时,对话框将收到包含TTN_NEEDTEXT通知消息的WM_NOTIFY消息。对话框过程调用OnWMNotify函数来处理TTN_NEEDTEXT通知。OnWMNotify根据工具提示控件的标识符提供适当的字符串。
工具提示控件需要接收系统发送到控制窗口的鼠标消息。要访问消息,DoCreateDialogTooltip函数安装WH_GETMESSAGE类型的挂接过程。挂钩过程GetMsgProc监视针对其中一个控制窗口的鼠标消息的消息流,并将消息中继到工具提示控件。
// DoCreateDialogTooltip - 为对话框创建一个工具提示控件,
//枚举子控件窗口,并安装一个钩子
//监视发布的鼠标消息的消息流的过程
//到控制窗口。
//如果成功返回TRUE,否则返回FALSE。
//
//全局变量
// g_hinst __应用程序实例的句柄
// g_hwndTT __工具提示控件的句柄
// g_hwndDlg __对话框的句柄
// g_hhk __挂??钩过程的句柄
BOOL DoCreateDialogTooltip(void)
{
//确保加载公共控件DLL并创建
//一个工具提示控件。
InitCommonControls();
g_hwndTT = CreateWindowEx(0, TOOLTIPS_CLASS, (LPSTR) NULL,
TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, g_hwndDlg, (HMENU) NULL, g_hinst, NULL);
if (g_hwndTT == NULL)
return FALSE;
//枚举子窗口,使用工具提示注册它们
// 控制。
if(!EnumChildWindows(g_hwndDlg,(WNDENUMPROC)EnumChildProc,0))
return FALSE;
//安装一个挂钩程序来监视鼠标的消息流
//用于对话框中控件的消息。
g_hhk = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc,
(HINSTANCE) NULL, GetCurrentThreadId());
if (g_hhk == (HHOOK) NULL)
return FALSE;
return TRUE;
}
// EmumChildProc - 通过工具提示控制寄存器控制窗口
//使用TTM_ADDTOOL消息传递a的地址
// TOOLINFO结构。
//如果成功返回TRUE,否则返回FALSE。
// hwndCtrl - 控制窗口的句柄
// lParam - 应用程序定义的值(未使用)
BOOL EnumChildProc(HWND hwndCtrl, LPARAM lParam)
{
TOOLINFO ti;
char szClass[64];
//跳过静态控件。
GetClassName(hwndCtrl, szClass, sizeof(szClass));
if(lstrcmp(szClass,“STATIC”){
ti.cbSize = sizeof(TOOLINFO);
ti.uFlags = TTF_IDISHWND;
ti.hwnd = g_hwndDlg;
ti.uId = (UINT) hwndCtrl;
ti.hinst = 0;
ti.lpszText = LPSTR_TEXTCALLBACK;
SendMessage(g_hwndTT,TTM_ADDTOOL,0,
(LPARAM) (LPTOOLINFO) &ti);
}
return TRUE;
}
// GetMsgProc - 监视预期的鼠标消息的消息流
//在对话框中的控制窗口。
//返回与消息相关的值。
// nCode - 钩子代码
// wParam - message flag(not used)
// lParam - MSG结构的地址
LRESULT CALLBACK GetMsgProc(int nCode,WPARAM wParam,LPARAM lParam)
{
MSG *lpmsg;
lpmsg = (MSG *) lParam;
if(nCode < 0 ||!(IsChild(g_hwndDlg,lpmsg- > hwnd)))
return (CallNextHookEx(g_hhk, nCode, wParam, lParam));
switch(lpmsg- > message){
case WM_MOUSEMOVE:
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
if (g_hwndTT != NULL) {
MSG msg;
msg.lParam = lpmsg->lParam;
msg.wParam = lpmsg->wParam;
msg.message = lpmsg->message;
msg.hwnd = hwnd;
SendMessage(g_hwndTT,TTM_RELAYEVENT,0,
(LPARAM) (LPMSG) &msg);
}
break;
默认:
break;
}
return (CallNextHookEx(g_hhk, nCode, wParam, lParam));
}
// OnWMNotify - 提供具有相应文本的工具提示控件
//显示控制窗口。这个函数被调用
//响应WM_NOTIFY消息的对话框过程。
// lParam - WM_NOTIFY消息的第二个消息参数
VOID OnWMNotify(LPARAM lParam)
{
LPTOOLTIPTEXT lpttt;
int idCtrl;
if ((((LPNMHDR) lParam)->code) == TTN_NEEDTEXT) {
idCtrl = GetDlgCtrlID((HWND) ((LPNMHDR) lParam)->idFrom);
lpttt = (LPTOOLTIPTEXT) lParam;
switch(idCtrl){
case ID_HORZSCROLL:
lpttt->lpszText = "A horizontal scroll bar.";
return;
case ID_CHECK:
lpttt->lpszText = "A check box.";
return;
case ID_EDIT:
lpttt->lpszText = "An edit control.";
return;
}
}
return;
}