Share via


Making Your Application STRICT Compliant

OverviewHow Do I

Some source code that in the past compiled successfully might produce error messages when you enable STRICT type checking. The following sections describe the minimal requirements for making your code compile when STRICT is enabled. Additional steps are recommended, especially if you want to produce portable code. These are covered in Using STRICT Type Checking.

General Requirements

The principal requirement is that you must declare correct handle types and function pointers instead of relying on more general types such as unsigned int and FARPROC. You cannot use one handle type where another is expected. This also means that you may have to change function declarations and use more type casts.

For best results, the generic HANDLE type should be used only when necessary. Consult New Types and Macros for a list of new specific handle types.

Using Function Pointers

Always declare function pointers with the proper function type (such as DLGPROC or WNDPROC) rather than FARPROC. You’ll need to cast function pointers to and from the proper function type when using MakeProcInstance, FreeProcInstance, and other functions that take or return a FARPROC, as shown in the following code:

BOOL CALLBACK DlgProc(HWND hwnd, UINT msg, WPARAM wParam,
                       LPARAM lParam);
DLGPROC lpfnDlg;

lpfnDlg = (DLGPROC)MakeProcInstance((FARPROC)DlgProc, hinst);
...
FreeProcInstance((FARPROC)lpfnDlg);

Declaring Functions Within Your Application

Make sure all application functions are declared. Placing all function declarations in an include file is recommended because you can easily scan your declarations and look for parameter and return types that should be changed.

If you use the /Zg compiler option to create header files for your functions, remember that you’ll get different results depending on whether you have enabled STRICT type checking. With STRICT disabled, all handle types generate the same base type (unsigned short in Windows 3.x). With STRICT enabled, they generate base types such as HWND __near * or HDC __near *. To avoid conflict, you need to re-create the header file each time you enable or disable STRICT, or edit the header file to use the types HWND, HDC, HANDLE, and so on, instead of the base types.

Any API function declarations that you copied from WINDOWS.H into your source code may have changed, and your local declaration may be out of date. Remove your local declaration.

Functions That Require Casts

Some API functions have generic return types or parameters. For example, a function like SendMessage returns data that may be any number of types, depending on the context. When you see any of these functions in your source code, make sure that you use the correct type cast and that it is as specific as possible.

The following table summarizes these functions.

API function Comment
LocalLock Cast result to the proper kind of data pointer.
GlobalLock Cast result to the proper kind of data pointer.
GetWindowWord Cast result to appropriate data type.
GetWindowLong Cast result to appropriate data type.
SetWindowWord Cast argument as it is passed to function.
SetWindowLong Cast argument as it is passed to function.
SendMessage Cast result to appropriate data type; cast to UINT before casting to a handle type.
DefWindowProc See comment for SendMessage.
SendDlgItemMessage See comment for SendMessage.

When you call SendMessage, DefWindowProc, or SendDlgItemMessage, you should first cast the result to type UINT. You need to take similar steps for any API function that returns LRESULT or LONG, where the result contains a handle. This is necessary for writing portable code because the size of a handle is either 16 bits or 32 bits, depending on the version of Windows. The (UINT) cast ensures proper conversion. The following code shows an example in which SendMessage returns a handle to a brush:

HBRUSH hbr;

hbr = (HBRUSH)(UINT)SendMessage(hwnd, WM_CTLCOLOR, ..., ...);

The CreateWindow Function

The CreateWindow and CreateWindowExhmenu parameter is sometimes used to pass an integer control ID. In this case, you must cast the ID to an HMENU type:

HWND hwnd;
int id;

hwnd = CreateWindow("Button", "Ok", BS_PUSHBUTTON,
        x, y, cx, cy, hwndParent,
        (HMENU)id,      // Cast required here
        hinst,
        NULL);