The Message-Handling Structure

Under Windows 3.x, a common practice in the message handling is to have all message cases end by returning a NULL or 0. Any messages that are not handled internally are returned via the DefWindowProc procedure. Here is an example of a skeleton WndProc message format:

   switch( msg )                                    // 3.x
   {
      case WM_PAINT:  ...    return( NULL );
      case WM_DESTROY:  ...  return( NULL );
   }
   return( DefWindowProc( hwnd, msg, wParam, lParam ) );

The preceding example is fairly simple. Only two case statements require handling, and all other messages (if any) receive default handling. However, under 98/95/NT, this specific handling has produced some conflicts in some cases. A slight variation, shown below, produces much cleaner results.

   switch( msg )                                    // 98/95/NT
   {
      case WM_PAINT:  ...    break;
      case WM_DESTROY:  ...  break;
      default:
         return( DefWindowProc( hwnd, msg, wParam, lParam ) );
   }
   return( FALSE );

This variation has the following differences:

You might have expected a NULL return value here, assuming that NULL and FALSE would have the same value. In one sense, both are a 0 (zero) but, because these do not have the same type, you will get a compiler warning—not an error—by returning a NULL.

But remember, this handling is used only for the WndProc procedure. Other exported procedures, such as dialog box handlers and other child window procedures, even though these are called with similar parameters and provide similar message handling, do not use the DefWindowProc API call to return any messages. Instead, each message case handled returns TRUE to report having handled the message. Any unhandled messages, by default, return FALSE. The default message handling for all child window processes is just that—provided by default.

Child window message handling is illustrated by the following skeletal DialogProc procedure:

BOOL APIENTRY DialogProc( HWND hDlg,   UINT msg,    // 98/95/NT 
                          UINT wParam, LONG lParam )
{
   switch( msg ) 
   {
      case WM_INITDIALOG:   ...  return( TRUE );
      case WM_COMMAND:
         switch( LOWORD( wParam ) )
         {
            case IDOK:      ...  return( TRUE );
            case IDCANCEL:  ...  return( TRUE );
         }
         break;
   }
   return( FALSE );
}

Alternatively, if the calling procedure doesn’t really care about the response returned by this child window process, the three return ( TRUE ) provisions in the above example could be replaced by break statements.

In most cases, both the OK and Cancel buttons are used to close a dialog box, but only the OK button returns TRUE; the Cancel button returns FALSE. In this fashion, a TRUE result indicates that the actions or settings in the dialog box should be implemented, and a FALSE result indicates that no changes should be made.

© 1998 SYBEX Inc. All rights reserved.