vbpslogo2.gif (19593 bytes)
Brad's VB-32 Programs & Samples

Posted: 06/20/97, last update: 06/20/97

Home

MenuHelp Revealed...

What follows is an extensive elaboration of the information found in the book "Programming Windows 95" by Charles Petzold and Paul Yao, published by Microsoft Press, 1996.

The information contained herein is solely a result of this author's observations and conclusions and should by no means be taken as fact. Every effort has been made in an attempt to provide the most clear and accurate information possible. If for any reason this information is not found to be clear or accurate, the author would appreciate notification via the e-mail link at the top of this page.

Thank you.
Brad Martinez


Overview


The MenuHelp function processes the WM_MENUSELECT message and displays help text for the currently selected menu in the specified status window. It's SDK documentation indicates that handling is also provided for the WM_COMMAND message, but may have never been fully implemented.

The MenuHelp function is designed to be used in a message procedure.

MenuHelp also automatically displays help strings for an application's system submenus and system submenu commands.
Declare Sub MenuHelp Lib "comctl32" (ByVal uMsg As Long, _
                                     ByVal wParam As Long, _
                                     ByVal lParam As Long, _
                                     ByVal hMainMenu As Long, _
                                     ByVal hInst As Long, _
                                     ByVal hwndStatus As Long, _
                                     lpwIDs As Any)

Because the MenuHelp function may have been initially designed to handle both the WM_MENUSELECT and WM_COMMAND messages, it can become terribly complicated if both messages are taken into consideration. To simplify MenuHelp as much as possible, it's functionality for the WM_COMMAND message will be ignored.

Parameter Description
uMsg WM_MENUSELECT message
wParam Added with lpwIDs to calculate the string resource ID. If the WM_MENUSELECT wParam value is used, only it's low word value is evaluated. Can be 0.
lParam The parent menu handle of the selected menu item. Used only for retrieving submenu help strings. Is ignored if the selected menu item is a menu command. Can be 0.
hMainMenu Indicates that the lpwIDs parameter points to an array or structure of submenu handle/string resource ID value pairs. This parameter must be set to the submenu handle value in order for the function to evaluate the string resource ID value. Otherwise this parameter is ignored and should be set to 0. See Remarks below.
hInst Handle to the module that contains the string resources
hwndStatus Handle to the status window
lpwIDs Pointer to a value which is added with wParam to calculate the string resource ID. May point to an array or structure of submenu handle/string resource ID value pairs as described above. Must point to a Long data type (4 bytes), set to a value of 0, in order for the system submenu's help string to be displayed. Otherwise this parameter can be Null. See Remarks below.

This function does not return a value.

Description

When MenuHelp receives the first WM_MENUSELECT message at menu mode initialization, it places it's associated status bar in "simple mode" by sending it a SB_SIMPLE message (wParam = True).

While receiving the initial and subsequent WM_MENUSELECT messages, MenuHelp uses the WM_MENUSELECT parameters passed to it to reference resource strings in the specified module. It displays the strings by sending SB_SETTEXT messages to the status bar, drawing the text on the simple mode's part (255), and using the SB_NOBORDERS drawing operation.

When MenuHelp receives a final WM_MENUSELECT message indicating menu mode termination (the low word in WM_MENUSELECT's wParam equals 0xFFFF), MenuHelp again sends the SB_SIMPLE message (wParam = False) to the status bar, restoring it to it's non-simple state.

Remarks

Concerning the lpwIDs parameter, the Win32 documentation states:

"Pointer to an array that contains pairs of string resource identifiers and menu handles. The function searches the array for the handle to the selected menu and, if found, uses the corresponding resource identifier to load the appropriate help string."

This does not appear to be accurate. MenuHelp uses the value pointed to by the lpwIDs parameter to "calculate" a string ID. It does not "search" it's data.

The function actually *adds* the value pointed to by lpwIDs to the low word of the wParam value (a submenu's position or a menu command's ID) . lpwIDs can point to a *single value*. lpwIDs can also point to an element in an array (or a structure) that contains menu handle/string resource ID pairs. In this case, the menu handle is ignored, the corresponding resource ID value is added to the low word of the wParam value, and the resource ID is determined.

To clarify this, the following shows three examples of parameter values in which MenuHelp will evaluate to a resource string ID value of 10:

wParam + lpwIDs = resource ID
0 10
5 5
10 9

Implementation

Menu commands

Since menu commands have their own IDs, it's easiest to set lpwIDs to 0 and pass WM_MENUSELECT's wParam value directly to MenuHelp's wParam parameter.

System submenu commands

The same applies to system submenu menu commands with regard to the wParam value. But WM_MENUSELECT's lParam value (the system submenu) must also be directly passed to MenuHelp's lParam parameter.

System submenu

As well, in order for the help string of the system submenu itself to be displayed, hMainMenu cannot be the lParam value (the system submenu's parent menu) and lpwIDs must also point to a Long data type which should be set to 0.

Submenus

Non-system submenus pose a bit of a problem. Since the low word of the wParam value returned by the WM_MENUSELECT message contains the submenu's position with respect to it's parent menu, there's no direct way of associating the selected submenu with a particular string resource ID value without programmatically determining the value.

Submenus Method 1

As one alternative to handling submenu resource string IDs, the following structure can be filled and passed as MenuHelp's lpwIDs parameter.

  Type MENUHELPID        'mhid
     hMenu As Long      'submenu handle
     wStringID As Long  'resource string ID of 1st menu item in hMenu
  End Type
    

In order for this structure to be effective, it should be placed in an array and each element contain -the first menu item of each submenu- that contains a submenu.

When a submenu is selected, since MenuHelp itself will not search the array, the array must be searched through code. The element in the array whose hMenu member matches the lParam value returned by the WM_MENUSELECT message (the submenu's handle) must be found. This specific structure element will then be passed to MenuHelp's lpwIDs parameter.

To have MenuHelp correctly evaluate resource ID value from the structure, it's hMainMenu parameter must also be set to the value of the structure's corresponding hMenu member. MenuHelp will then recognize lpwIDs as a submenu handle/string resource ID value pair, ignore the hMenu member and subsequently use the wStringID member in it's calculation.

Submenus Method 2
As a simpler approach to handling submenu resource string IDs as described above, foregoing MenuHelp's calculation, submenu resource string ID values can be passed directly to either it's wParam or lpwIDs parameter, so long as the other equals the value of 0. This also allows the hMainMenu parameter to be entirely ignored and set to 0.

In order to implement this method, the application's entire menu structure could be placed in an array of structures similar to the one used above. Each structure could contain the same value returned by WM_MENUSELECT when the item is selected, i.e. uItem and MF_POPUP flag from wParam's respective low and high word values, and the submenu's parent menu handle from the lParam value. Each structure could then occupy the position in the array which would equal it's associated menu item's string resource ID value. A simple search routine could be employed to retrieve any selected menu item's position in the array, and this value be could then be passed directly to either the wParam or lpwIDs parameter.

MenuHelp page