JavaScript EditorFree JavaScript Editor     Ajax Editor 



Main Page
  Previous Section Next Section

Playing with Controls

Window child controls are really little windows themselves. Here's a short list of some of the more popular child controls:

  • Static text boxes

  • Edit boxes

  • Buttons

  • List boxes

  • Scroll bars

In addition, there are a number of sub-button types, such as

  • Push buttons

  • Check boxes

  • Radio buttons

There are even further sub-types of each. Nevertheless, most complex window controls that you see are conglomerations of these basic types. For example, a file directory control is just a few list boxes, some text edit boxes, and some buttons. If you can work with the basic controls listed here, you can handle anything. Once you have mastered one, they're all roughly the same, give or take a few details, so I'm just going to show you how to work with a few of the child controls, including buttons.

Buttons

There are a number of button types that Windows supports. If you're reading this book, hopefully you have used Windows and are at least familiar with push buttons, check boxes, and radio buttons, so I'm not go into the details of each. Rather, I'm going to show you how to create any type of button you want and respond to messages sent from it. The rest is up to you. Let's begin by taking a look at Table 4.5, which lists all the available button types.

Table 4.5. Button Styles
Value Description
BS_PUSHBUTTON Creates a push button that posts a WM_COMMAND message to the owner window when the user selects the button.
BS_RADIOBUTTON Creates a small circle with text. By default, the text is displayed to the right of the circle.
BS_CHECKBOX Creates a small empty check box with text. By default, the text is displayed to the right of the check box.
BS_3STATE Creates a button that is the same as a check box, except that the box can be grayed as well as checked or unchecked.
BS_AUTO3STATE Creates a button that is the same as a three-state check box, except that the box changes its state when the user selects it. The state cycles through checked, grayed, and unchecked.
BS_AUTOCHECKBOX Creates a button that is the same as a check box, except that the check state automatically toggles between checked and unchecked each time the user selects the check box.
BS_AUTORADIOBUTTON Creates a button that is the same as a radio button, except that when the user selects it, Windows automatically sets the button's check state to checked and automatically sets the check state for all other buttons in the same group to unchecked.
BS_OWNERDRAW Creates an owner-drawn button. The owner window receives a WM_MEASUREITEM message when the button is created and a WM_DRAWITEM message when a visual aspect of the button has changed.

To create a child control button you simply create a window using "button" as the class string along with one of the button styles in Table 4.5. Then, when the button is manipulated, it sends WM_COMMAND messages to your window, as shown in Figure 4.11. You process the wparam and lparam as usual to see what child control sent the message and what the message was.

Figure 4.11. Child window message passing.

graphics/04fig11.gif

Let's begin by seeing the exact parameters you'll need to send to CreateWindowEx() to create a child button control. First, you need to set the class name to "button". Then you need to set the style flags to WS_CHILD | WS_VISIBLE logically ORed with a button style from Table 4.5. Then in the place where you would normally put the handle to the menu or HMENU, you send the ID you want to refer to the button with (of course you must cast it to a HMENU). That's about it.

As an example, here's how you would create a push button with ID equal to 100 and the text "Push Me" on it:

CreateWindowEx(NULL,      // extended style
              "button",   // class
              "Push Me", // text on button
              WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
             10,10,       // initial x,y
             100,24,    // initial width, height
             main_window_handle,    // handle to parent
            (HMENU)(100),            // id of button, notice cast to HMENU
            hinstance,  // instance of this application
            NULL);      // extra creation parms

Simple, isn't it? When you press the button, a WM_COMMAND message is sent to the WinProc() of the parent window with the following paramaterization:

msg: WM_COMMAND
LOWORD(wparam): Child Window ID
HIWORD(wparam): Notification Code
lparam: Child Window Handle

Seem reasonable? The only mystery is the notification code. Notification codes describe what happened to the button control and begin with BN_. Table 4.6 lists all the possible notification codes and values.

Table 4.6. Notification Codes for Buttons
Code Value
BN_CLICKED 0
BN_PAINT 1
BN_HLITE 2
BN_UNHILITE 3
BN_DISABLE 4
BN_DOUBLECLICKED 5

The most important of the notification codes are of course BN_CLICKED and BN_DOUBLECLICKED. To process a button child control like a simple push button, you might do something like this in the WM_COMMAND event handler:

// assume a child button was created with id 100
case WM_COMMAND:
     {
     // test for id
     if (LOWORD(wparam) == 100)
     {
     // do whatever
     } // end if

     // process all other child controls, menus, etc.

     // we handled it
     return(0);

     } break;

As an example, take a look at DEMO4_8.CPP; it creates a list of all button types and then displays all the messages along with the wparam and lparam for each message as you click and manipulate the buttons. Figure 4.12 shows the program in action. By experimenting with it, you will get a much better idea of how button child controls work.

Figure 4.12. The DEMO4_8.EXE child control program.

graphics/04fig12.gif

If you play with DEMO4_8.EXE, you'll quickly realize that although your WinProc() is sending messages indicating what the user (you) is doing to the controls, you don't know how to change or manipulate the controls programmatically. In essence, many of the controls don't seem to do anything when you click them. This is important, so let's briefly cover it.

Sending Messages to Child Controls

Because child controls are windows, they can receive messages just like any other window. But because they are children of a parent the messages are sent onto the parent in the case of the WM_COMMAND message. However, it's possible to send a child control (like a button) a message and it will itself process the message with its own default WinProc(). This is exactly how you change the state of any control—by sending messages to it.

In the case of buttons, there are a number of messages you can send button controls, using SendMessage() to change the state of the button and/or retrieve the state of the button. Remember that SendMessage() returns a value too. Here's a list of some of the more interesting messages for use with the parameterizations of wparam and lparam.

Purpose: To simulate clicking the button.

msg: BM_CLICK
wparam: 0
lparam: 0

Example:

// this would make the button look like it was pressed
SendMessage(hwndbutton, BM_CLICK,0,0);

Purpose: Used to set the check on a check box or radio button.

msg: BM_SETCHECK
wparam: fCheck
lparam: 0

fCheck can be one of the following:

Value Description
BST_CHECKED Sets the button state to checked.
BST_INDETERMINATE Sets the button state to grayed, indicating an indeterminate state. Use this value only if the button has the BS_3STATE or BS_AUTO3STATE style.
BST_UNCHECKED Sets the button state to unchecked.

Example:

// this would check a check button
SendMessage(hwndbutton, BM_SETCHECK, BST_CHECKED, 0);

Purpose: Used to retrieve the current state of the button check. Possible return values are shown here.

msg: BM_GETCHECK
wparam: 0
lparam: 0

Value Description
BST_CHECKED Button is checked.
BST_INDETERMINATE Button is grayed, indicating an indeterminate state (applies only if the button has the BS_3STATE or BS_AUTO3STATE style).
BST_UNCHECKED Button is unchecked.

Example:

// this would get the check state of a checkbox
if (SendMessage(hwndbutton,BM_GETCHECK,0,0) == BST_CHECKED)
   {
   // button is checked
   } // end if
else
   {
   // button is not checked
   } // end else

Purpose: Used to highlight the button as if it were selected by the user.

msg: BM_SETSTATE
wparam: fState
lparam: 0

Where fState is a TRUE for highlighted and FALSE otherwise.

Example:

// this would highlight the button control
SendMessage(hwndbutton, BM_SETSTATE, 1, 0);

Purpose: To get the general state of the button control. Possible return values are shown below.

msg: BM_GETSTATE
wparam: 0
lparam: 0

Value Description
BST_CHECKED Indicates the button is checked.
BST_FOCUS Specifies the focus state. A nonzero value indicates that the button has the keyboard focus.
BST_INDETERMINATE Indicates the button is grayed because the state of the button is indeterminate. This value applies only if the button has the BS_3STATE or BS_AUTO3STATE style.
BST_PUSHED Specifies the highlight state. A nonzero value indicates that the button is highlighted. A button is automatically highlighted when the user positions the cursor over it and presses and holds the left mouse button. The highlighting is removed when the user releases the mouse button.
BST_UNCHECKED Indicates the button is unchecked.

Example:

// this code can be used to get the state of the button
switch(SendMessage(hwndbutton, BM_GETSTATE, 0, 0))
      {
      // what is the button state
      case BST_CHECKED:       { } break;
      case BST_FOCUS:         { } break;
      case BST_INDETERMINATE: { } break;
      case BST_PUSHED:      { } break;
      case BST_UNCHECKED:     { } break;
      default: break;
      } // end switch

Well, that's it for child controls. At least you have an idea of what they are and how to handle them. Now it's time to move onto querying information from Windows.

      Previous Section Next Section
    



    JavaScript EditorAjax Editor     JavaScript Editor