INF: Context-Sensitive Help in a Dialog Box Through F1

ID Number: Q72219

3.00

WINDOWS

Summary:

In an application developed with Windows version 3.0, to implement the

ability to request context-sensitive help by pressing the F1 key in a

dialog box, it is necessary to install a message filter.

This article describes the details of installing the message filter.

In particular, it describes code that could be added to the Generic

sample application (included with the Windows Software Development Kit

version 3.0) to install a message filter that would detect F1

keystrokes in the About Generic modal dialog box.

More Information:

Detecting F1 Keystrokes in a Dialog Box

---------------------------------------

Normally, the child control windows in a dialog box do not pass

keystroke messages on to the dialog box window. To detect F1

keystrokes in a dialog box, it is necessary to install a message

filter. Page 18-20 of the "Microsoft Windows Software Development Kit

Tools" manual describes the method for detecting F1 keystrokes in a

dialog box.

Installing a Filter Function

----------------------------

Page 1-65 of the "Microsoft Windows Software Development Kit

Reference, Volume 1" describes the method for installing a filter

function.

Sample Code

-----------

Perform the following six steps to add code to the Generic sample

application to provide context-sensitive help in the About Generic

modal dialog box:

1. Define a private message that the filter function can post to the

application. For example:

#define PM_CALLHELP WM_USER+1000

// wParam and lParam can be used to

// pass context information

2. Define global variables:

FARPROC lpfnFilterProc; // Our filter function

FARPROC lpfnOldHook; // Previous filter function

// in the chain

3. Add a filter function to the C-language source file. For example:

/*-------------------------- FilterFunc -------------------------*/

//

// PARAMETERS:

//

// nCode : Specifies the type of message being processed. It will

// be either MSGF_DIALOGBOX, MSGF_MENU, or less than 0.

//

// wParam: specifies a NULL value

//

// lParam: a FAR pointer to a MSG structure

//

//

// GLOBAL VARIABLES USED:

//

// lpfnOldHook

//

//

// NOTES:

//

// If (nCode < 0), return DefHookProc IMMEDIATELY.

//

// If (MSGF_DIALOGBOX==nCode), set the local variable ptrMsg to

// point to the message structure. If this message is an F1

// keystroke, ptrMsg->hwnd will contain the HWND for the dialog

// control that the user wants help information on. Post a private

// message to the application, then return 1L to indicate that

// this message was handled.

//

// When the application receives the private message, it can call

// WinHelp. WinHelp must NOT be called directly from the

// FilterFunc routine.

//

// In this example, post a private PM_CALLHELP message to the

// dialog box. wParam and lParam can be used to pass context

// information.

//

// If the message is not an F1 keystroke, or if nCode is

// MSGF_MENU, we return 0L to indicate that we did not process

// this message.

//

//

DWORD FAR PASCAL FilterFunc(nCode, wParam, lParam)

int nCode;

WORD wParam;

DWORD lParam;

{

MSG FAR * ptrMsg;

if (nCode < 0) // MUST return DefHookProc

return DefHookProc(nCode, wParam, lParam,

(FARPROC FAR *)&lpfnOldHook);

if (MSGF_DIALOGBOX == nCode)

{

ptrMsg = (MSG FAR *)lParam;

if ((WM_KEYDOWN == ptrMsg->message)

&& (VK_F1 == ptrMsg->wParam))

{

// Use PostMessage here to post an application-defined

// message to the application. Here is one possible call:

PostMessage(GetParent(ptrMsg->hwnd),

PM_CALLHELP, ptrMsg->hwnd, 0L);

return 1L; // Handled it

}

else

return 0L; // Did not handle it

}

else // I.e., MSGF_MENU

{

return 0L; // Did not handle it

}

}

/*--------------------- end FilterFunc ----------------------------*/

Note that FilterFunc returns a DWORD. The documentation in volume 1

of the SDK reference volume 1 that indicates that a filter function

should return an integer is incorrect. Note also that not all

messages are passed to DefHookProc. The message hook is for this

application only, so it is known that no other application needs to

see these messages. However, DefHookProc MUST be called when the

nCode parameter is less than zero.

4. Export the filter function in the module definition file.

5. Before calling DialogBox, set the hook. After DialogBox returns,

unhook the hook. For example, the About Generic dialog box could be

called as follows:

case IDM_ABOUT:

lpProcAbout = MakeProcInstance(About, hInst);

lpfnFilterProc = MakeProcInstance(FilterFunc, hInst);

lpfnOldHook = SetWindowsHook(WH_MSGFILTER, lpfnFilterProc);

DialogBox(hInst, "AboutBox", hWnd, lpProcAbout);

UnhookWindowsHook(WH_MSGFILTER, lpfnFilterProc);

FreeProcInstance(lpfnFilterProc);

FreeProcInstance(lpProcAbout);

break;

6. Have the application respond to the private message by calling

WinHelp.

Additional reference words: 3.00 3.0