Changing Message Handlers

Window handles in the Win32 API are 32-bit values; consequently, the WPARAM type has been widened from 16 to 32 bits to accommodate this change. This widening often necessitates repacking the values carried by the wParam and lParam parameters.

A 16-bit application, written for Windows without using the framework, requires a considerable amount of code rewriting to port successfully to 32-bit. Each window procedure declaration must be modified, as well as the message-handling code within the procedure.

The MFC class library accommodates most of these changes internally. The framework hides the window procedure from you, unpacks wParam and lParam, and passes the properly unpacked values to you in message handlers. The only two instances that require your attention are functions that override the and message handlers, where the framework passes wParam or lParam directly from Windows to you.

The framework also unpacks the wParam and lParam values associated with a WM_COMMAND message to implement message-map entries. The framework properly unpacks the values as appropriate for Windows version 3.x or Win32 with no attention from you.

CWnd::OnCommand Changes

If your application overrides OnCommand, check the code carefully and modify it so that it unpacks wParam and lParam correctly. Your 16-bit override of OnCommand may compile successfully, but will not execute correctly.

When the framework receives a WM_COMMAND message, it calls the member function with the following arguments:

virtual BOOL OnCommand( WPARAMwParam**,LPARAMlParam);**

A command ID, a control handle, and a notification message can be packed in wParam and lParam, depending on the circumstances of the call.

You don’t need to change the way you extract the command ID; it is packed the same way in both environments. You can extract it this way:

UINT nID = LOWORD(wParam);

You extract the remaining two values in this way in the 16-bit framework:

HWND hWndCtrl = (HWND)LOWORD(lParam);       //Control handle
int nCode = HIWORD(lParam);                 //Notification code

You extract them this way in the 32-bit framework:

HWND hWndCtrl = (HWND)lParam;              //Control handle
int nCode = HIWORD(wParam);                //Notification code

In both the 16-bit and 32-bit versions, if the message is from an accelerator, the value retrieved in nCode is 1. If the message is from a menu, the value in nCode is 0.

CWnd::OnParentNotify Changes

As with OnCommand, carefully check any code in your application that overrides OnParentNotify and modify it so that it unpacks values from lParam correctly. Your 16-bit override of OnParentNotify will compile successfully, but will not execute correctly.

The framework calls the member function with the following arguments:

afx_msg void OnParentNotify( UINT message**,LPARAM** lParam**);**

The OnParentNotify member function is called for the parent of a child window in two cases: when the mouse is clicked over a child window, and when a child window is created or destroyed.

When the message parameter is equal to WM_CREATE or WM_DESTROY, the framework’s 16-bit packing of lParam puts the child window handle in the low-order word and the identifier of the child window in the high-order word. For the 32-bit framework, the child window handle has been widened and now takes up all of lParam; the child window identifier is unavailable.

If your Win32 code in OnParentNotify requires the child ID, retrieve it like this:

CWnd* pChild = FromHandle( (HWND)lParam );
int nID = pChild->GetDlgCtrlID();

In this example, FromHandle returns the CWnd object attached to the child window handle. The GetDlgCtrlID member function returns the child window ID. You could also retrieve the child ID by passing the child handle directly to the Windows GetDlgCtrlID function, but the code above also retrieves a pointer to the child CWnd object.

The pointer returned in pChild is temporary and should not be stored for use beyond the scope of OnParentNotify.