通常的窗口过程是通过一个switch语句来实现的,这个事情很烦,有没有更简便的方法呢?有,那就是消息分流器,利用消息分流器,我们可以把switch语句分成更小的函数,每一个消息都对应一个小函数,这样做的好处就是对消息更容易管理。
之所以被称为消息分流器,就是因为它可以对任何消息进行分流。下面我们做一个函数就很清楚了:
- void MsgCracker(HWND hWnd,int id,HWND hWndCtl,UINT codeNotify)
- {
- switch(id)
- {
- case ID_A:
- if(codeNotify==EN_CHANGE)...
- break;
- case ID_B:
- if(codeNotify==BN_CLICKED)...
- break;
- ....
- }
- }
- LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- switch(message)
- {
- HANDLE_MSG(hWnd,WM_COMMAND,MsgCracker);
- HANDLE_MSG(hWnd,WM_DESTROY,MsgCracker);
- default:
- return DefWindowProc(hWnd, message, wParam, lParam);
- }
- return 0;
- }
在WindowsX.h中定义了如下的HANDLE_MSG宏:
#define HANDLE_MSG(hwnd,msg,fn) \
switch(msg): return HANDLE_##msg((hwnd),(wParam),(lParam),(fn));
实际上,HANDLE_WM_XXXX都是宏,例如:HANDLE_MSG(hWnd,WM_COMMAND,MsgCracker);
将被转换成如下定义:
#define HANDLE_WM_COMMAND(hwnd,wParam,lParam,fn)\
((fn)((hwnd),(int)(LOWORD(wParam)),(HWND)(lParam),(UINT)HIWORD(wParam)),0L);
好了,事情到了这一步,应该一切都明朗了。
不过,我们发现在windowsx.h里面还有一个宏:FORWARD_WM_XXXX,我们还是那WM_COMMAND为例,进行分析:
#define FORWARD_WM_COMMAND(hwnd, id, hwndCtl, codeNotify, fn) \
(void)(fn)((hwnd), WM_COMMAND, MAKEWPARAM((UINT)(id),(UINT)(codeNotify)), (LPARAM)(HWND)(hwndCtl))
所以实际上,FORWARD_WM_XXXX将消息参数进行了重新构造,生成了wParam && lParam,然后调用了我们定义的函数。
- LRESULT CALLBACK Dlg_Proc (HWND hwnd, UINT msg,WPARAM wParam, LPARAM lParam)
- {
- switch(msg)
- {
- chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Cls_OnInitDialog); // 使用大牛的chHANDLE_DLGMSG宏
- chHANDLE_DLGMSG(hwnd, WM_COMMAND, Cls_OnCommand);
- }
- return false;
- }
- LRESULT CALLBACK Dlg_Proc(HWND hwnd, UNIT umsg, WPARAM wparam, LPARAM lparam)
- {
- switch(msg)
- {
- case WM_COMMAND: // 每个case都被一个message cracker代替,这里使用大牛同志的
- // do something; // chHANDLE_DLGMSG宏;这个宏负责对消息筛选,处理并返回相应的值
- return true;
- case WM_INITDIALOG:
- // do something;
- return xxxx;
- }
- return false; // 如果消息不在我们的DlgProc过程中被处理,则告诉调用这个DlgProc的消息,
- } //告诉系统的对话框管理器,这个消息我们不处理,交给你了