訊息分流器(HANDLE MSG)

2021-06-20 13:47:14 字數 4872 閱讀 2336

windows訊息分流器的實現

很好理解,windows作業系統使用訊息處理機制,那麼,我們所設計的程式如何才能分辨和處理系統中的各種訊息呢?這就是訊息分流器的作用.

簡單來說,訊息分流器就是一段**,在我的講述中,將分7重來循序漸進的介紹它.從最初的第1重到最成熟的第7重,它的樣子會有很大的變化.但,實現的功能都是一樣的,所不同的,僅僅是變得更加簡練罷了.

程式開始時候,會是main函式,然後會生成初始的視窗,同時會呼叫wndproc函式.這是乙個自定義的函式,名字也會有變化,但其功能是一樣的,就是執行訊息分流器.wndproc函式如下:

lresult callback wndproc (hwnd hwnd, uint msg,wparam wparam, lparam lparam)

這其中,hwnd是視窗的控制代碼,msg是系統傳送來的訊息的名字.wparam和lparam則是隨訊息一起傳送來的訊息引數.

wndproc函式使用了訊息分流器,下面把訊息分流器的內容解釋一下:

一重,當不同的訊息出現時,在其中寫入相應的程式語句即可。

lresult callback wndproc (hwnd hwnd, uint msg,wparam wparam, lparam lparam)

return defwindowproc(hwnd, msg, wparam, lparam);

}二重,運用三個訊息分流器進行處理。

lresult callback wndproc (hwnd hwnd, uint msg, wparam wparam, lparam lparam)

return defwindowproc(hwnd, msg, wparam, lparam);

}這裡的handle_wm_create,handle_wm_paint,handle_wm_destroy就是訊息分流器。

與訊息不同之處就是在前面增加了「handle_」字元,windows的訊息分流器就是這樣的模樣。

它的本質就是巨集定義。

其中的四個引數有三個都是從本函式的入口引數中直接得到的,即為hwnd, wparam, lparam。

只有第四的引數是表明呼叫的函式。

訊息分流器是在winowsx.h檔案中定義的。由此,可以看出第四個引數是呼叫的函式,其定義如下:

#define handle_wm_create(hwnd, wparam, lparam, fn) ((fn)((hwnd), (lpcreatestruct)(lparam)) ? 0l : (lresult)-1l)

#define handle_wm_paint(hwnd, wparam, lparam, fn) ((fn)(hwnd), 0l)

#define handle_wm_destroyclipboard(hwnd, wparam, lparam, fn) ((fn)(hwnd), 0l)

0l是表示int型別的變數,其數值為0。

int型別時,可在後面加l或者l(小寫和大寫形式)

表明無符號數時,可在後面加u或者u(小寫和大寫形式)

float型別時,可在後面加f或者f(小寫和大寫形式)

例如:128u 1024ul 1l 8lu 3.14159f 0.1f

lresult是乙個系統的資料型別,其定義如下:

typedef long_ptr lresult;

long_ptr也是乙個系統的資料型別,其定義如下:

#if defined(_win64)

typedef __int64 long_ptr;

#else

typedef long long_ptr;

#endif

由此可見,lresult的實質就是64的long型別的變數

那麼(lresult)-1l的實質並不是減法,而是((lresult)(-1l)),即強制型別轉換

三重,把訊息分流器的巨集定義代換回去,就成了下面的樣子

lresult callback wndproc (hwnd hwnd, uint msg, wparam wparam, lparam lparam)

return defwindowproc(hwnd, msg, wparam, lparam);

}在逗號表示式,c++會計算每個表示式,但完整的逗號表示式的結果是最右邊表示式的值。

所以,會return 0。

然後,就可以手動的編寫各個處理函式了:cls_oncreate,cls_onpaint,wm_destroy。

四重,lresult callback wndproc (hwnd hwnd, uint msg, wparam wparam, lparam lparam)

return defwindowproc(hwnd, msg, wparam, lparam);

}handle_msg也是乙個巨集,它在windowsx.h中定義,如下:

#define handle_msg(hwnd, message, fn) case (message): return handle_##message((hwnd), (wparam), (lparam), (fn))

這個巨集要做的就是根據不同的message(##用來連線前後的字串),把自己「變成」相應的handle_***xmessage形式的巨集,再通過相應的巨集來執行訊息處理**。

說白了,就是把message的訊息做為替換,##就是乙個替換的標誌。

如果沒有##,就成了handle_message了,這樣,巨集是不會被代換的。

如果就單獨乙個,則會代換,如hwnd和fn。

比如實際**中寫入:

handle_msg(hwnd, wm_create, cls_oncreate)

則經過轉換就變成:

case (wm_create): return handle_wm_create((hwnd), (wparam), (lparam), (cls_oncreate))

這與二重一模一樣。

以上四重,是訊息分離器的基本使用,但,這不完整,訊息分離器主要應用在對話方塊訊息處理中。

這裡,視窗子類化是我們經常使用的手段,這也可以通過訊息分流器實現,

第五重lresult callback dlg_proc (hwnd hwnd, uint msg, wparam wparam, lparam lparam)

return false;

}由於是視窗子類化,所以,最後,返回的是false,以表明,如果沒有約定響應的訊息,

則返回父親視窗false,如果有,則返回ture,這是與前四重不同的地方。

一般情況下,對話方塊過程函式應該在處理了訊息的情況下返回true,如果沒有處理,則返回false。

如果對話方塊過程返回了false,那麼對話方塊管理器為這條訊息準備預設的對話操作。

但是,這其中有錯誤,因為有的訊息,需要單獨處理。單獨處理的訊息列表見setdlgmsgresult巨集。

第六重這點小問題,這就需要用到setdlgmsgresult(hwnd, msg, result)巨集。

lresult callback dlg_proc (hwnd hwnd, uint msg, wparam wparam, lparam lparam)

return false;

}這裡,就用直接用到了第二重的訊息分流器,而拋棄了其他。

這個巨集定義如下:

#define setdlgmsgresult(hwnd, msg, result)((

(msg) == wm_ctlcolormsgbox ||

(msg) == wm_ctlcoloredit ||

(msg) == wm_ctlcolorlistbox ||

(msg) == wm_ctlcolorbtn ||

(msg) == wm_ctlcolordlg ||

(msg) == wm_ctlcolorscrollbar ||

(msg) == wm_ctlcolorstatic ||

(msg) == wm_compareitem ||

(msg) == wm_vkeytoitem ||

(msg) == wm_chartoitem ||

(msg) == wm_querydragicon ||

(msg) == wm_initdialog

) ?(bool)(result) :

(setwindowlongptr((hwnd), dwlp_msgresult, (lparam)(lresult)(result)), true)

)為了表述清楚,所以用了此格式,這是乙個三項表示式,首先對訊息型別進行考察。

如果對話方塊過程處理的訊息恰巧為返回特定值中的乙個,則如實返回result;

不要被前面的bool蒙蔽,bool在標頭檔案中的定義實際上是乙個int型,

一旦需要返回非true或false的其他值,照樣可以;

這樣,我們的cls_oninitdialog就能夠正確的返回它的bool值了,

而cls_oncommand在處理之後,也可以由後面的逗號表示式正確的返回乙個true表示訊息已處理。

第七重我們還可以把case也包含進來,就成了如下的樣子。

lresult callback dlg_proc (hwnd hwnd, uint msg, wparam wparam, lparam lparam)

return false;

}chhandle_dlgmsg是牛人定義的乙個巨集,它把case也包含進來了。

#define chhandle_dlgmsg(hwnd, message, fn) case (message): return (setdlgmsgresult(hwnd, umsg, handle_##message((hwnd), (wparam), (lparam), (fn))))

這樣,程式中的語句

switch (umsg)

就被翻譯成:

switch (umsg)

這樣,訊息分流器,就介紹完畢.

訊息分流器(HANDLE MSG)

windows訊息分流器的實現2007 12 17 23 58很好理解,windows作業系統使用訊息處理機制,那麼,我們所設計的程式如何才能分辨和處理系統中的各種訊息呢?這就是訊息分流器的作用.簡單來說,訊息分流器就是一段 在我的講述中,將分7重來循序漸進的介紹它.從最初的第1重到最成熟的第7重,...

訊息分流器 HANDLE MSG

訊息分流器 handle msg 2010年10月13日 windows訊息分流器的實現,很好理解,windows作業系統使用訊息處理機制,那麼,我們所設計的程式如何才能分辨和處理系統中的各種訊息呢?這就是訊息分流器的作用.簡單來說,訊息分流器就是一段 在我的講述中,將分7重來循序漸進的介紹它.從最...

分流器的作用

分流器是根據直流電流通過電阻時在電阻兩端產生電壓的原理製成。分流器廣泛用於擴大儀表測量電流範圍,有固定式定值分流器和精密合金電阻器,均可用於儀表,通訊系統 電子整機 自動化控制的電源等迴路作限流,均流取樣檢測。其原理見下圖,檢出的電壓供儀表,控制電路等使用。用於直流電流測量的分流器有插槽式和非插槽式...