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:

  1. The Windows message manager passed the event to the application's message filter callback function.
  2. The filter checked if the nCode parameter indicated an event inside a dialog box (MSGF_DIALOGBOX) or menu (MSGF_MENU).
  3. 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 via GetDlgCtrlID(), 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 as HELP_CONTEXT (to open the topic in the main Help window) or HELP_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.