Messages and Accompanying Arguments

Within the switch…case message structures, there are several important differences between Windows 3.x and 98/95/NT. As a reminder, under Windows 3.x, in response to a WM_COMMAND message, the usual response is a second switch…case structure using the wParam argument, appearing as:

   case WM_COMMAND:                                 // 3.x
      switch( wParam )
      {
         case IDD_FNAME: ...
         case IDD_FPATH: ...

Under Windows 3.x, the wParam value is a 16-bit argument identifying the menu item, accelerator entry, or dialog box control originating the message. In other cases, the wParam value does not originate with a control or accelerator entry but may simply be an application-supplied value used to direct a specific response.

Under 98/95/NT, the wParam argument is a 32-bit value. The item ID originating the message, which is still a 16-bit argument, is now contained in the low-order word of the wParam argument. Therefore, under Windows 98/95/NT, this item ID value must be extracted from the 32-bit argument, thus:

   case WM_COMMAND:                                 // 98/95/NT
      switch( LOWORD( wParam ) )
      {
         case IDD_FNAME: ...
         case IDD_FPATH: ...

Under 98/95/NT, the high-order word of the wParam argument accompanying a WM_COMMAND message is one (1) if the message originates from an accelerator message or zero (0) if the message originated from a menu or control element. Likewise, if the message originates with a menu, the lParam argument is NULL. Alternatively, if the message originates with a control element, lParam contains the window handle of the control.

WARNING

There is a potentially hazardous habit among programmers of ignoring the need to use the LOWORD macro when employing a wParam message in a switch…case statement. Because the messages originating with menu or control elements contain a 0 in the high word, omitting this provision normally does not cause any problems. If, however, the message originated with an accelerator table entry (a hotkey definition), the high word would contain a 1, and this would prevent the correct case statement from being recognized … unless, of course, you wished to distinguish between control/menu commands and hotkey entries.

The important element here is that the low-order word of the wParam argument must be explicitly used in response to the WM_COMMAND message; simply following the Windows 3.x format may or may not produce the appropriate response (depending on whether the high-order word is set or not). Also, in many cases, the high-order word of the wParam argument and the lParam argument can simply be ignored.

As an alternative, you could also use the high-order word to distinguish an application-generated message from a message generated by a menu or dialog box. For example, you could do this by setting the high word to 0x02. But, remember, this particular format applies only to WM_COMMAND messages. Also, it is not always completely valid, as you will see in a moment.

NOTE

If you are using MFC, the same restrictions apply to the wParam and lParam arguments reported to the CWnd::OnCommand handler.

Continuing with the WM_COMMAND message, consider a message sent from a list box. Under Windows 3.x, the high-order word of the lParam argument is tested for the EN_CHANGE secondary message, which reports a change in the list box selection.

      case IDD_FNAME:                               // 3.x
         if( HIWORD( lParam ) == EN_CHANGE )

Under Windows 98/95/NT, however, the EN_CHANGE message has moved. It’s now found in the high-order word of wParam, not lParam, thus:

      case IDD_FNAME:                               // 98/95/NT
         if( HIWORD( wParam ) == EN_CHANGE )

But this is only part of the information that will be extracted. Next, assuming the EN_CHANGE message was sent, the sample application needs to extract information from the list box, which is accomplished by sending a message back to the list box control.

            EnableWindow( GetDlgItem( hDlg, IDOK ),    // 3.x
                   (BOOL) SendMessage( LOWORD( lParam ),
                                       WM_GETTEXTLENGTH, 0, 0L ) );

Exactly which information is being used in the list box message is irrelevant at the moment. What is relevant is the list box handle which, for Windows 3.x, is found in the low-order word of the lParam argument, preceding. But in Windows 3.x, this handle is only a 16-bit value extracted from a 32-bit argument.

Under Windows 98/95/NT, the equivalent list box handle is a 32-bit argument and consists of the entire high- and low-order word values of the lParam argument.

            EnableWindow( GetDlgItem( hDlg, IDOK ),    // 98/95/NT
                   (BOOL) SendMessage( (HWND) lParam,
                                       WM_GETTEXTLENGTH, 0, 0L ) );

Comparing the two fragments immediately preceding, you should notice the differences in how the two version examples reference control handles. Note that in the second fragment, the (HWND) typecast is used simply to prevent the Microsoft C compiler from generating an irrelevant warning message.

© 1998 SYBEX Inc. All rights reserved.