消息映射(Message Map)的雏形
在读完这一章的内容之后打算从以下几点来总结我的看法
- 为什么需要消息映射
- 如何实现消息映射
首先解决第一个问题 为什么需要消息映射呢?
- 为了使窗口过程函数更加模块化, 一般化;
如何来理解这句话呢? 分两部分
第一部分, 当还没有进行消息映射之前. 窗口函数对消息的处理, 先是通过一个switch语句选择出消息类型, 再通过一个switch语句来选择ID号. 之后在case下书写自己的代码的 这么一种方式.代码如下
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM, lParam)
{
int wmID, wmEvent;
switch(message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch(wmID)
{
case IDM_ABOUT:
DialogBox(_hInt, "AboutBox", hWnd, (DLGPROC)About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_DESTROY: //窗口已被销毁程序即将结束
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
从以上代码可以看出每增加一个消息, 或者ID号. 都需要更改窗口过程中的代码这样容易发生错误也不方便修改. 因此有没有办法可以把窗口过程函数的代码和消息处理的代码给分开写呢? 因此出现了消息映射.
接下来我们看 第二部分 , 进行消息映射
首先需要一个结构体和一个宏
struct MSGMAP_ENTRY
{
UINT nMessage; //消息
LONG (*pfn)(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); //消息处理函数
}
#define dim(x) sizeof(x)/sizeof(x[0]);
接下来在定义两个结构体数组
// 第一个结构体数组, 消息条目
struct MSGMAP_ENTRY _messageEntries[] = {
WM_CREATE, OnCreate,
WM_PAINT, OnPaint,
WM_COMMAND, OnCommand
};
// 第二个结构体数组, 命令条目
struct MSGMAP_ENTRY _commandEntries[] = {
IDM_ABOUT, OnAbout,
IDM_SAVEAS, OnSaveAs
}
我们再来看看有了这些前提条件之后窗口函数的代码是怎么写的
/*
* Summary :窗口过程函数
*/
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);
}
/*
* Summary :OnCommand专门处理WM_COMMAND消息的函数
*/
LONG OnCommand(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int i;
for(i = 0; i < dim(_commandEntries); i++)
{
if (LOWORD(wParam) == nMessage)
{
return ((*_commandEntries.pfn[i])(hWnd, message, wParam, lParam))
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
/*
* Summary :命令处理函数OnAbout
*/
LONG OnAbout(hWnd, message, wParam, lParam)
{}
通过以上操作, 我们就不必再更改窗口过程函数和命令处理函数了, 当有新的消息和命令出现, 我们只需修改两个数组的元素并添加对应的函数即可.以上也就是实现了简化版的消息映射解决第二个问题.