Programming Common Controls
Because the common controls are separate from the core operating system, the DLL that contains them must be initialized before any of the common controls can be used. Under all versions of Windows, including Windows CE, you can call the functionvoid InitCommonControls (void);
to load the library and register many of the common control classes. This call doesn't initialize the month calendar, time picker, up/down, IP address, or other newer common controls. To initialize those controls, use the function
BOOL InitCommonControlsEx (LPINITCOMMONCONTROLSEX lpInitCtrls);
This function allows an application to load and initialize only selected common controls. This function is handy under Windows CE because loading only the necessary controls can reduce the memory impact. The only parameter to this function is a two-field structure that contains a size field and a field that contains a set of flags indicating which common controls should be registered. Table 5-1 shows the available flags and their associated controls.
Once the common control DLL has been initialized, these controls can be treated like any other control. But since the common controls aren't formally part of the Windows core functionality, an additional include file, CommCtrl.h, must be included.The programming interface for the common controls is similar to that for standard Windows controls. Each of the controls has a set of custom style flags that configure the look and behavior of the control. Messages specific to each control are sent to configure and manipulate the control and cause it to perform actions. One major difference between the standard Windows controls and common controls is that notifications of events or requests for service are sent via WM_NOTIFY messages instead of WM_COMMAND messages as in the standard controls. This technique allows the notifications to contain much more information than would be allowed using WM_COMMAND message notifications. In addition, the technique has allowed the WM_NOTIFY message to be extended and adapted for each of the controls that use it.At a minimum, the WM_NOTIFY message is sent with lParam pointing to an NMHDR structure defined as the following:
typedef struct tagNMHDR {
HWND hwndFrom;
UINT idFrom;
UINT code;
} NMHDR;
The hwndFrom field contains the handle of the window that sent the notify message. For property sheets, this is the property sheet window. The idFrom field contains the ID of the control if a control is sending the notification. Finally, the code field contains the notification code. While this basic structure doesn't contain any more information than the WM_COMMAND message, it's almost always extended, with additional fields appended to it. The notification code then indicates which, if any, additional fields are appended to the notification structure.
One additional difference in programming common controls is that most of the control-specific messages that can be sent to the common controls have predefined macros that make sending the message look as if your application is calling a function. So instead of using an LVM_INSERTITEM message to a list view control to insert an item, as in
nIndex = (int) SendMessage (hwndLV, LVM_INSERTITEM, 0, (LPARAM)&lvi);
an application could just as easily have used the line
nIndex = ListView_InsertItem (hwndLV, &lvi);
There's no functional difference between the two lines; the advantage of these macros is clarity. The macros themselves are defined in CommCtrl.h along with the other definitions required for programming the common controls. One problem with the macros is that the compiler doesn't perform the type checking on the parameters that would normally occur if the macro were an actual function. This is also true of the SendMessage technique, in which the parameters must be typed as WPARAM and LPARAM types, but at least with messages the lack of type checking is obvious. All in all, though, the macro route provides better readability. One exception to this system of macros is the calls made to the command bar control and the command bands control. Those controls actually have a number of true functions in addition to a large set of macro-wrapped messages. As a rule, I'll talk about messages as messages, not as their macro equivalents. That should help differentiate a message or a macro from a true function.