Processing User Input from Custom Controls

Windows uses a 'Dialog Procedure' created by the developer to handle the users manipulation of the controls in the dialog,. As the user works with the controls, Windows sends messages to the dialog procedure. The developer is responsible for responding to these messages and implementing the logic to process the user input. A full description of this messaging system is beyond the scope of this documentation, but below is a brief overview.

When you create a dialog box or add a rollup page, you specify the dialog procedure to process the input. The basic structure of this dialog proc is listed below:

BOOL CALLBACK DialogProc(HWND hDlg, UINT message,
            WPARAM wParam, LPARAM lParam)
{
   switch (message)
   { // Respond to the message ...
     case WM_INITDIALOG: // Initialize the Controls here.
      return TRUE;
     case WM_DESTROY: // Release the Controls here.
      return FALSE;
     case WM_COMMAND: // Various messages come in this way.
      break;
     case WM_NOTIFY: // Others this way...
      break;
     // Other cases...
     default:
     break;
   }
   return FALSE;
}

Windows passes in four parameters to the dialog procedure. These are the handle of dialog box, the message, and two parameters which hold message-specific information. Except in response to the WM_INITDIALOG message, the dialog box procedure should return TRUE if it processes the message, and FALSE if it does not.

When the dialog box is initialized, the WM_INITDIALOG message is sent. At this time the custom controls should be initialized. Each control has methods to initialize it. The methods used to initialize the control are discussed in the next section, or you may see the sample program CUSTCTRL.CPP for how this is done for each control.

When the user is finished with the dialog box, the WM_DESTROY message is sent. This is where you release the controls. Again, the next section discusses this, or you may take a look at the sample program to see how this is done.

When the user works with any of the custom controls, Windows sends in specific messages to the dialog procedure. For example, when the user changes a spinner control, Windows sends in a CC_SPINNER_CHANGE message. The developer would add this case to the dialog proc code above and handle the processing required when the spinner changed. The dialog box may have several spinner controls: how does the developer know which spinner changed? The lParam and wParam arguments to the dialog procedure contain message-specific information. It is here that the ID of the control is provided. (This is the ID entered in the ID field of the user control properties dialog when the control was created). For example, the developer could add a case such as the one below to handle spinner change messages:

case CC_SPINNER_CHANGE:
   switch (LOWORD(wParam)) { // Switch on ID
case IDC_ANGLE_SPINNER: // A specific spinner ID.
   angle = (( ISpinnerControl *)lParam)->GetFVal();
   break;
case IDC_RADIUS_SPINNER: // A specific spinner ID.
   // Code to handle the Radius spinner...
   break;
};
break;

This code fragment presents several important concepts. The LOWORD macro used above retrieves the low-order word from the given 32-bit value. The spinner control provides the ID of the spinner which changed in the low order word of wParam. (Another macro, HIWORD, retrieves the high-order word from the given 32-bit value). Splitting the argument into low and high order words allows more information to be packed into the parameter.

A pointer to the spinner control is provided in the lParam parameter. This pointer is used to call a method of the spinner to get the new floating point value ((ISpinnerControl *) lParam >GetFVal()).

As another example, let's look at the color change message sent in from the Color Swatch control. When the user is changing the colors in the dialog box, and the developer has asked to be notified on each change, Windows sends the CC_COLOR_CHANGE message. Again, the developer would add a case to the switch to handle this message. The LOWORD of wParam contains the ID of the color swatch control. The HIWORD of wParam contains 0 if the mouse button is down as the user is changing colors, and 1 if the mouse is up.

Sometimes, the message sent to the dialog proc is WM_COMMAND, and the programmer must look at both the high and low words of wParam to determine the nature of the message and the ID of the control which sent the message. For example, the code below demonstrates how custom button messages may be handled.

   caseWM_COMMAND:
     switch(LOWORD(wParam))
     { // Switch on ID
      case IDC_BUTTON: // A specific button's ID.
         switch (HIWORD(wParam)) { // Notification codes
      case BN_BUTTONDOWN: // Button is pressed.
         break;
      case BN_BUTTONUP: // Button is released.
         break;
      case BN_RIGHTCLICK: // User right clicked.
         break;
     };
     break;
   caseIDC_FLYOFF: // A specific fly off control ID
     switch (HIWORD(wParam))
     { // Notification codes
      case BN_FLYOFF:
     // This notification code is sent when the
     // user chooses a new fly off.
         break;
     };
     break;

In summary, when the user works with controls in a dialog, Windows sends messages to the plugin's dialog proc. The developer responds to these messages to process the user input.