消息分流器




通常的窗口過程是通過一個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,然後調用了我們定義的函數。


在《Windows核心編程》一書中,大牛Jeffrey自己定義了一個宏,使SetDlgMsgResult宏的使用更加方便:
#define chHANDLE_DLGMSG(hwnd, message, fn)
case (message): return (SetDlgMsgResult(hwnd, uMsg,
HANDLE_##message((hwnd), (wParam), (lParam), (fn))))
可見這個宏只是簡單的對SetDlgMsgRseult宏進行了封裝。
這樣,我們最終的代碼可以寫成:
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的消息,
} //告訴系統的對話框管理器,這個消息我們不處理,交給你了




發佈了22 篇原創文章 · 獲贊 5 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章