Using a Tooltip Control with a Dialog Box

The following example includes a set of application-defined functions that implement a tooltip control for a dialog box. The DoCreateDialogTooltip function creates a tooltip control and uses the EnumChildWindows function to enumerate the controls in the dialog box. The enumeration procedure, EnumChildProc, registers each control with the tooltip control. The procedure specifies the dialog box as the parent window of each tooltip control and includes the LPSTR_TEXTCALLBACK value for each tooltip control. As a result, the dialog box receives a WM_NOTIFY message that contains the TTN_NEEDTEXT notification message whenever the tooltip control needs the text for a control. The dialog box procedure calls the OnWMNotify function to process the TTN_NEEDTEXT notifications. OnWMNotify provides the appropriate string based on the identifier of the tooltip control.

The tooltip control needs to receive mouse messages that the system sends to the control windows. To access the messages, the DoCreateDialogTooltip function installs a hook procedure of the WH_GETMESSAGE type. The hook procedure, GetMsgProc, monitors the message stream for mouse messages intended for one of the control windows and relays the messages to the tooltip control.

// DoCreateDialogTooltip - creates a tooltip control for a dialog box,

// enumerates the child control windows, and installs a hook

// procedure to monitor the message stream for mouse messages posted

// to the control windows.

// Returns TRUE if successful or FALSE otherwise.

//

// Global variables

// g_hinst ¾ handle of the application instance

// g_hwndTT ¾ handle of the tooltip control

// g_hwndDlg ¾ handle of the dialog box

// g_hhk ¾ handle of the hook procedure

BOOL DoCreateDialogTooltip(void)

{

// Ensure that the common control DLL is loaded, and create

// a tooltip control.

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;

// Enumerate the child windows to register them with the tooltip
// control.

if (!EnumChildWindows(g_hwndDlg, (WNDENUMPROC) EnumChildProc, 0))

return FALSE;

// Install a hook procedure to monitor the message stream for mouse

// messages intended for the controls in the dialog box.

g_hhk = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc,

(HINSTANCE) NULL, GetCurrentThreadId());

if (g_hhk == (HHOOK) NULL)

return FALSE;

return TRUE;

}

// EmumChildProc - registers control windows with a tooltip control by
// using the TTM_ADDTOOL message to pass the address of a

// TOOLINFO structure.

// Returns TRUE if successful or FALSE otherwise.

// hwndCtrl - handle of a control window

// lParam - application-defined value (not used)

BOOL EnumChildProc(HWND hwndCtrl, LPARAM lParam)

{

TOOLINFO ti;

char szClass[64];

// Skip static controls.

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 - monitors the message stream for mouse messages intended

// for a control window in the dialog box.

// Returns a message-dependent value.

// nCode - hook code

// wParam - message flag (not used)

// lParam - address of an MSG structure

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;

default:

break;

}

return (CallNextHookEx(g_hhk, nCode, wParam, lParam));

}

// OnWMNotify - provides the tooltip control with the appropriate text

// to display for a control window. This function is called by

// the dialog box procedure in response to a WM_NOTIFY message.

// lParam - second message parameter of the WM_NOTIFY message

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;

}