------引自深入浅出MFC
以下做法是MFC消息映射表格的雏形
首先,定义一个MSGMAP_ENTRY结构和一个dim宏:
struct
MSGMAP_ENTRY{
ULONG nMessage;
LONG ( * pfn)(HWND, UINT, WPARAM, LPARAM);
};
#define dim(x) (sizeof(x) / sizeof(x[0]))
ULONG nMessage;
LONG ( * pfn)(HWND, UINT, WPARAM, LPARAM);
};
#define dim(x) (sizeof(x) / sizeof(x[0]))
MSGMAP_ENTRY的第二个元素pfn是个函数指针,此指针指向的函数处理nMessage消息。
接下来,组织两个数组_messageEntries[]和_commandEntries[],把程序中欲处理的消息以及消息处理例程的关联性建立起来:
//
消息与处理例程的对照表格
struct MSGMAP_ENTRY _messageEntries[] =
{
// 消息 消息处理程序
WM_CREATE, OnCreate,
WM_PAINT, OnPaint,
WM_SIZE, OnSize,
WM_COMMAND, OnCommand,
WM_SETFOCUS, OnSetFocus,
WM_CLOSE, OnClose,
WM_DESTROY, OnDestroy,
};
// Command-ID与处理例程之对照表格
struct MSGMAP_ENTRY _commandEntries[] =
{
// WM_COMMAND命令项 命令处理程序
IDM_ABOUT, OnAbout,
IDM_FILEOPEN OnFileOpen,
IDM_SAVEAS, OnSaveAs,
};
struct MSGMAP_ENTRY _messageEntries[] =
{
// 消息 消息处理程序
WM_CREATE, OnCreate,
WM_PAINT, OnPaint,
WM_SIZE, OnSize,
WM_COMMAND, OnCommand,
WM_SETFOCUS, OnSetFocus,
WM_CLOSE, OnClose,
WM_DESTROY, OnDestroy,
};
// Command-ID与处理例程之对照表格
struct MSGMAP_ENTRY _commandEntries[] =
{
// WM_COMMAND命令项 命令处理程序
IDM_ABOUT, OnAbout,
IDM_FILEOPEN OnFileOpen,
IDM_SAVEAS, OnSaveAs,
};
于是窗口函数可以这么设计:
//
----------------------------------------------------------------------------
// 窗口函数
// ----------------------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
int i;
// 消息对照表
for (i = 0 ; i < dim(_messageEntries); i ++ )
{
if (message == _messageEntries[i].nMessage)
return (( * _messageEntries[i].pfn)(hWnd, message, wParam,lParam));
}
return (DefWindowProc(hWnd, message, wParam, lParam));
}
// ----------------------------------------------------------------------------
// OnCommand--专门处理WM_COMMAND
// ----------------------------------------------------------------------------
LONG ON_COMMAND(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
int i;
// 命令项目对照表
for (i = 0 ; i < dim(_commandEntries); i ++ )
{
if (LOWORD(wParam) == _commandEntries[i].nMessage)
return (( * _commandEntries[i].pfn)(hWnd, message, wParam, lParam));
}
return (DefWindowProc(hWnd, message, wParam, lParam));
}
// ----------------------------------------------------------------------------
LONG OnCreate(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
...
}
// ----------------------------------------------------------------------------
LONG OnAbout(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
...
}
// ----------------------------------------------------------------------------
// 窗口函数
// ----------------------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
int i;
// 消息对照表
for (i = 0 ; i < dim(_messageEntries); i ++ )
{
if (message == _messageEntries[i].nMessage)
return (( * _messageEntries[i].pfn)(hWnd, message, wParam,lParam));
}
return (DefWindowProc(hWnd, message, wParam, lParam));
}
// ----------------------------------------------------------------------------
// OnCommand--专门处理WM_COMMAND
// ----------------------------------------------------------------------------
LONG ON_COMMAND(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
int i;
// 命令项目对照表
for (i = 0 ; i < dim(_commandEntries); i ++ )
{
if (LOWORD(wParam) == _commandEntries[i].nMessage)
return (( * _commandEntries[i].pfn)(hWnd, message, wParam, lParam));
}
return (DefWindowProc(hWnd, message, wParam, lParam));
}
// ----------------------------------------------------------------------------
LONG OnCreate(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
...
}
// ----------------------------------------------------------------------------
LONG OnAbout(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
...
}
// ----------------------------------------------------------------------------
这么一来,WndProc和OnCommand永远不必改变,每当有新的要处理的消息,只要在_messageEntries[]和_commandEntries[]两个数组中加上新元素,并针对新消息撰写新的处理例程即可。