Windows 3.11 Context-Sensitive Help Processing
This article explains the underlying mechanism Microsoft Windows 3.11
used to process context-sensitive help requests within system
applications. In the 16-bit Windows environment, context-sensitive help
relied on a coordinated pipeline involving keyboard message loops,
Windows message filters, context identifiers, and inter-process
communication with the standalone Windows Help engine
(WINHELP.EXE) via the Windows API.
The Trigger: Keystroke and Menu Events
Context-sensitive help in Windows 3.11 was typically triggered in two
ways: pressing the F1 key while an element had focus,
or entering "Help Mode" via the Shift+F1 shortcut
(which changed the mouse cursor to a question mark). When a user
initiated help, the system generated standard window messages—primarily
WM_KEYDOWN with the virtual key code VK_F1, or
a WM_COMMAND message tied to a designated Help menu
item.
Message Filtering and Hooking
Because modal dialog boxes and active menus captured standard keyboard input, normal message loops could not always detect an F1 press directly. To resolve this, Windows 3.11 utilized system-level message hooks.
Applications installed a message filter hook using
SetWindowsHookEx() with the WH_MSGFILTER or
WH_SYSMSGFILTER hook type. When a user pressed F1 while
browsing a menu or inside a modal dialog:
- The Windows message manager passed the event to the application's message filter callback function.
- The filter checked if the
nCodeparameter indicated an event inside a dialog box (MSGF_DIALOGBOX) or menu (MSGF_MENU). - If an F1 press was detected, the filter processed the request rather than passing the keystroke through the standard input queue.
Context ID Resolution
Once the application confirmed a context-sensitive help request, it determined the exact topic to display by mapping the user interface element to a 32-bit Context ID:
- Dialog Controls: The application inspected the
control that currently had input focus using
GetFocus(), retrieved its control identifier viaGetDlgCtrlID(), and matched it to a predefined numeric constant. - Menus: If a menu was open, the hook intercepted the currently highlighted menu item’s identifier.
- General Context: If no specific child control or menu was selected, the ID defaulted to the active window or dialog itself.
These context numbers were defined as #define constants
in C/C++ header files and mirrored inside the help project's
.HPJ file using the [MAP] section, tying
control IDs directly to compiled help topics.
Invoking the WinHelp API
To display the help content, the application called the core Windows API function:
BOOL WinHelp(HWND hWndMain, LPCSTR lpszHelp, UINT uCommand, DWORD dwData);For context-sensitive requests:
hWndMain: Passed the handle of the requesting window.lpszHelp: Specified the path to the compiled binary help file (.HLP).uCommand: Set to execution flags such asHELP_CONTEXT(to open the topic in the main Help window) orHELP_CONTEXTPOPUP(to display the topic inside an unobtrusive, borderless popup window).dwData: Contained the numeric Context ID determined in the resolution step.
Execution by WINHELP.EXE
When WinHelp() was invoked, Windows 3.11 verified
whether the 16-bit help program (WINHELP.EXE) was already
running. If it was not, Windows launched it. The application
communicated the target file and context parameters to
WINHELP.EXE using internal Dynamic Data Exchange (DDE)
messages. WINHELP.EXE opened the specified
.HLP file, queried its internal B-tree index tables to
locate the topic matching the Context ID, and rendered the formatted
rich-text documentation on screen.