------引自深入浅出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[]两个数组中加上新元素,并针对新消息撰写新的处理例程即可。