Introduction to STRICT and Message Crackers

This article was previously published under Q83456
Retired KB Content Disclaimer
This article was written about products for which Microsoft no longer offers support. Therefore, this article is offered "as is" and will no longer be updated.
The WINDOWS.H and WINDOWSX.H header files in version 3.1 of theMicrosoft Windows Software Development Kit (SDK) provide new featuresto make developing applications for the Windows environment faster andeasier. These features enable the C compiler to find many commonprogramming errors at compile time.

This article provides an overview and examples of the new features, aswell as a road map to other resources in the SDK that explain them.
The WINDOWS.H and WINDOWSX.H header files provide the followingfeatures:

  • New data types and their associated definitions
  • A preprocessor variable, STRICT, which enforces the strictest possible type checking by the compiler
  • Macros to simplify many common operations in Windows programming
  • Control macros to simplify communication with Windows controls
  • Message crackers (which are a convenient, portable, and type-safe method to handle messages) and their associated parameters and return values in the Windows environment
The new types and STRICT type checking are implemented in theWINDOWS.H file; the macros, control macros, and message crackers areimplemented in WINDOWSX.H. The Windows SDK installation program copieseach of these files into the include directory (by default,C:\WINDEV\INCLUDE).

The SDK also provides the following resources:

  • WINDOWS.TXT, which explains the new types and STRICT features provided by WINDOWS.H.
  • WINDOWSX.TXT, which explains the macros, control macros, and message crackers provided by WINDOWSX.H.
  • MAKEAPP sample application, which uses all the new features of WINDOWS.H and WINDOWSX.H. MAKEAPP can create application templates that use all the new features.
  • MAKEAPP.TXT, which explains how to use MAKEAPP as an application template generator.
Any new code developed for Windows should use the new data types anddefine the STRICT preprocessor variable. Doing so provides powerfultype checking and enables the C compiler to find many problems atcompile time.

Using the macros, control macros, and message crackers assists in theprocess of finding errors and increases code portability; however,using these features is a matter of taste. Some developers like themand find them useful, others do not.

The simplest way to become familiar with the new features is to reviewthe WINDOWS.H and WINDOWSX.H header files, the associated WINDOWS.TXTand WINDOWSX.TXT text files, and the MAKEAPP sample application. Eachof the new features is implemented in one of the header files (usuallyas a fairly simple macro) and is explained in one of the text files.

Each of the new features is designed to address three goals:

  • Make the source code for an application easier to read
  • Enable the C compiler to catch programming errors
  • Ease porting to 32-bit Windows
In general, the new features can be used as appropriate throughout anapplication. Some of the code can use traditional methods and othercode can use various combinations of the new features. The oneexception to this is the STRICT preprocessor variable--if STRICT isdefined in any source module, the entire module must be "STRICTcompliant" before it will compile successfully.

Each of the new features is compatible with Windows 3.0. You can usethe new features in an application that will run under version 3.0 andyou can modify existing code to use the new features.

The remainder of this article provides an introduction to each of thenew features.

New Data Types, Type Definitions, and Helper Macros

The new data types are implemented in WINDOWS.H and described inWINDOWS.TXT. Examples of new data types are WPARAM, LPARAM, and UINT.Examples of new handle types are HINSTANCE, HMODULE, and HTASK. Usingthe new data types can make source code easier to read and simplifyporting to 32-bit Windows.

STRICT Preprocessor Variable

The STRICT preprocessor variable is implemented in WINDOWS.H anddescribed in WINDOWSX.TXT. When an application defines STRICT, the Ccompiler enforces the highest possible level of type checking, whichenables the compiler to find as many errors as possible. It is muchmore productive to find errors at compile time than to find them laterusing a debugger.

While an application can use the new data types described abovewithout defining STRICT, it must use the new types if STRICT isdefined.

To enable STRICT type checking, an application must define the STRICTenvironment variable before including WINDOWS.H, as follows:
   #define STRICT   #include windows.h				
The STRICT environment variable and the new data types are compatiblewith Windows 3.0, C++, the Microsoft C Compiler's highest warninglevel (specified by the -W4 option switch), and ANSI C.

An Example of Using STRICT

The ReleaseDC function is prototyped as follows:
   int WINAPI ReleaseDC(HWND, HDC);				
In an application, a programmer might mistakenly switch the twoparameters to the ReleaseDC function, as follows:
   ReleaseDC(hDC, hWnd);				
Traditionally, the compiler will not catch this error because both theHDC and HWND data types are defined to be UINT variables. However, ifSTRICT is enabled, the HDC and HWND data types are defined ascompletely different types, which enables the compiler to catch theerror at compile time. (For more information about how the HWND andHDC data types are defined, see the DECLARE_HANDLE macro inWINDOWS.H.)

The WINDOWS.TXT file contains step-by-step instructions for writingSTRICT-compliant Windows code. WINDOWS.TXT also lists the most commoncompiler errors generated while compiling an application with STRICTdefined, and methods to address these errors.

Converting Existing Code to STRICT

WINDOWS.TXT describes how to convert existing Windows code to becompatible with STRICT. However, this conversion requires a fairamount of effort. If the existing code is stable and not modified veryoften, the effort to convert the code may not be worthwhile.


The macros are implemented in WINDOWSX.H. Each one is listed anddescribed in WINDOWSX.TXT.

The macros can be used to simplify many common Windows programmingoperations. Macros are designed to make code easier to read and write.They can eliminate much typing and prevent type casting errors. Themacros are compatible with 32-bit Windows.

As an example, the traditional method to subclass a window involvescode such as the following:
   lpfnOldWndProc = SetWindowLong(hwnd, GWL_WNDPROC,                                  (LPARAM)(WNDPROC)lpfnNewWndProc);				
The following code, which uses a new macro, accomplishes the sametask:
   lpfnOldWndProc = SubclassWindow(hwnd, lpfnNewWndProc);				
Other macros include: GlobalAllocPtr, DeletePen, SelectBitmap, andGetWindowID.

Control Message Macros

The control message macros are implemented in WINDOWSX.H. Each one islisted and described in WINDOWSX.TXT.

The control message macros simplify dealing with Windows controls(edit controls, list boxes, and so forth). Using the control messagemacros makes code smaller, potentially more readable, and handles alltype casting required. When used in conjunction with the STRICTpreprocessor variable, the control message functions prevent typeerrors and incorrect parameter passing.

Examples of control message macros are: Static_Enable,Button_GetCheck, Edit_GetLineCount, and ScrollBar_SetRange.

Each control message macro corresponds to an existing control messageor window manager function. For example, Button_GetCheck can be usedin place of the BM_GETCHECK message and Button_SetText can be used inplace of SetWindowText.

A Control Message Macro Example

The following example illustrates the power of the control messagemacros.

The following code uses traditional SendMessage calls to retrieve allthe lines of text from an edit control:
   void PrintLines(HWND hwndEdit)   {      int line;      int lineLast = (int)SendMessage(hwndEdit, EM_GETLINECOUNT,                                      0, 0L);      for (line = 0; line < lineLast; line)      {         int cch;         char ach[80];         *((LPINT)ach) = sizeof(ach);         cch = (int)SendMessage(hwndEdit, EM_GETLINE,                                line, (LONG)(LPSTR)ach);         printf(ach); // or whatever ...      }   }				
The following code uses control message macros to perform the sametask, retrieving all the lines of text from an edit control:
   void PrintLines(HWND hwndEdit)   {      int line;      int lineLast = Edit_GetLineCount(hwndEdit);      for (line = 0; line < lineLast; line++)      {         int cch;         char ach[80];         cch = Edit_GetLine(hwndEdit, line, ach, sizeof(ach));         printf(ach); // or whatever ...      }   }				

Message Crackers

The message crackers are implemented in WINDOWSX.H. The messagecrackers are described in WINDOWSX.TXT, which also explains in somedetail how to use them. WINDOWSX.TXT does not list all messagecrackers; the list is available in WINDOWSX.H.

The two biggest advantages to using message crackers are:

  • Data type safety, because the message crackers perform a great deal of type casting
  • Simplified porting to 32-bit Windows
An application can use message crackers whether or not it definesSTRICT. Also, an application can use message crackers to process somemessages and traditional code to process others.

Using message crackers radically alters the appearance of a windowprocedure (see the example below). Whether or not this change ofappearance is a desirable side effect depends on the coding tastes ofthe application developer.

Typically, a window procedure will handle many messages, with code inthe procedure to process each message. This often leads to the sourcecode for a window procedure continuing on for many pages. When anapplication uses message crackers, almost any window procedure can belisted very concisely. The bulk of the code is transferred to message-handling functions that the message crackers call.

A Simple Message Cracker Example

The following code sample demonstrates using the HANDLE_WM_* messagecrackers in a window procedure:
   LRESULT _export CALLBACK Template_WndProc(HWND hwnd, WORD msg,                                             WPARAM wParam,                                             LPARAM lParam)   {      switch (msg)      {      case WM_MOUSEMOVE:         return HANDLE_WM_MOUSEMOVE(hwnd, wParam, lParam,                                    Template_OnMouseMove);      case WM_LBUTTONDOWN:         return HANDLE_WM_LBUTTONDOWN(hwnd, wParam, lParam,                                      Template_OnLButtonDown);      case WM_LBUTTONUP:         return HANDLE_WM_LBUTTONDUP(hwnd, wParam, lParam,                                     Template_OnLButtonUp);      case WM_CTLCOLOR:         return HANDLE_WM_CTLCOLOR(hwnd, wParam, lParam,                                   Template_OnCtlColor);      default:         return Template_DefProc(hwnd, msg, wParam, lParam);      }   }				
The application must also contain the following message-handlingfunctions that are called by the message crackers:
   void Template_OnMouseMove(HWND hwnd, int x, int y, UINT keyFlags)   {      // code to handle WM_MOUSEMOVE...   }   void Template_OnLButtonDown(HWND hwnd, BOOL fDoubleClick, int x,                               int y, UINT keyFlags)   {      // code to handle WM_LBUTTONDOWN...   }   void Template_OnLButtonUp(HWND hwnd, int x, int y, UINT keyFlags)   {      // code to handle WM_LBUTTONUP   }   HBRUSH Template_OnCtlColor(HWND hwnd, HDC hdc, HWND hwndChild,                              int type)   {      // code to handle WM_CTLCOLOR   }				
While the window procedure code given above is compact, the HANDLE_MSGmacro simplifies the code even further. For example:
   LRESULT _export CALLBACK Template_WndProc(HWND hwnd, WORD msg,                                             WPARAM wParam,                                             LPARAM lParam)   {       switch (msg)       {       HANDLE_MSG(hwnd, WM_MOUSEMOVE, Template_OnMouseMove);       HANDLE_MSG(hwnd, WM_LBUTTONDOWN, Template_OnLButtonDown);       HANDLE_MSG(hwnd, WM_LBUTTONDBLCLK, Template_OnLButtonDown);       HANDLE_MSG(hwnd, WM_LBUTTONUP, Template_OnLButtonUp);       default:           return Template_DefProc(hwnd, msg, wParam, lParam);       }   }				

Message Cracker Basics

If a window procedure uses a message cracker to process a particularmessage, it must also implement a function to process that message.This function must have a specific "signature" (the order and types ofparameters and the function's return type). The correct signature foreach function is listed in WINDOWSX.H next to the correspondingmessage cracker.

For example, if the window procedure in the example above uses theHANDLE_WM_MOUSEMOVE message cracker, it must also implement theTemplate_OnMouseMove function, which the message cracker calls.

Once the application implements Template_OnMouseMove, the messagecracker processes the message as follows:

  1. Splits wParam and lParam into component parts
  2. Type casts the parts correctly
  3. Passes the values as parameters to the application-supplied function (in this case, the Template_OnMouseMove function)
  4. Returns an appropriate value from processing the message
For more information on the inner workings of the message crackers,see the section titled "How Message Crackers Work" in WINDOWSX.TXT.

Message Crackers Have Many Uses

The WINDOWSX.TXT text file explains and illustrates how to use messagecrackers in many different application programming situations,including the following:

  • Passing messages to DefWindowProc, CallWindowProc, and so forth.
  • Private and registered window messages.
  • Windows with instance data.
  • Dialog box procedures.
  • Window subclassing.
  • Another way to create dialog box procedures that allows a dialog box procedure to return an LRESULT data type. This method allows an application to bypass the traditional limitation that dialog box procedures must return a BOOL data type.
no32bit 3.10

ID d'article : 83456 - Dernière mise à jour : 11/06/1999 16:44:00 - Révision : 1.0

Microsoft Windows Software Development Kit 3.1

  • kb16bitonly KB83456