SendMessage函數完全使用手冊(ZT)
首先 我們瞭解一下Windows的消息機制。Windows是一個消息驅動式系
統,Windows消息提供應用程序與應用程序之間,應用程序與Windows系統之間進
行通信的手段。
舉個例子,打開記事本程序,該程序有一個 “文件“菜單。 那麼,在運行該程序
的時候,如果用戶單擊“文件菜單“裏的“新建“命令, 這個動作將被Windows所捕
捉,Windows經過分析得知這個動作應該由我們打開的記事本程序所來處理,然後
Windows就發送個消息 譬如我們編程的時候有時用到的 WM_COMMAND的消息給記
事本,然後記事本就把這個消息處理掉。 這個過程就是消息處理。
接下來,我們把SendMessage的完整形式講一下
SendMessage
Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal
hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As
Long
別名
SendMessageA
說明
調用一個窗口的窗口函數,將一條消息發給那個窗口。除非消息處理完畢,否
則該函數不會返回
SendMessage所包含4個參數
hwnd 32位的窗口句柄窗口可以是任何類型的屏幕對象,因爲Win32能夠維
護大多數可視對象的句柄
wMsg 用於區別其他消息的常量值,這些常量可以是Windows單元中預定
義的常量,也可以是自定義的常量
wParam 通常是一個與消息有關的常量值,也可能是窗口或控件的句柄
lParam 通常是一個指向內存中數據的指針。由於WParm、lParam和Pointer
都是32位的,因此,它們之間可以相互轉換
wMsg函數
WM_CREATE 創建一個窗口
WM_DESTROY 當一個窗口被破壞時發送
WM_MOVE 移動一個窗口
WM_SIZE 改變一個窗口的大小
WM_ACTIVATE 一個窗口被激活或失去激活狀態
WM_SETFOCUS 一個窗口獲得焦點
WM_KILLFOCUS 一個窗口失去焦點
WM_ENABLE 一個窗口改變成Enable狀態
WM_SETREDRAW 設置窗口是否能重畫
WM_SETTEXT 應用程序發送此消息來設置一個窗口的文本
WM_GETTEXT 應用程序發送此消息來複制對應窗口的文本到緩衝區
WM_GETTEXTLENGTH 得到與一個窗口有關的文本的長度(不包含空字符)
WM_PAINT 要求一個窗口重畫自己
WM_CLOSE 當一個窗口或應用程序要關閉時發送一個信號
WM_QUERYENDSESSION 當用戶選擇結束對話框或程序自己調用ExitWindows函數
WM_QUIT 用來結束程序運行
WM_QUERYOPEN 當用戶窗口恢復以前的大小位置時,把此消息發送給某個圖標
WM_ERASEBKGND 當窗口背景必須被擦除時(例在窗口改變大小時)
WM_SYSCOLORCHANGE 當系統顏色改變時,發送此消息給所有頂級窗口
WM_ENDSESSION 當系統進程發出WM_QUERYENDSESSION消息後,此消息發送給應用程序,通知它對話是否結束
WM_SHOWWINDOW 當隱藏或顯示窗口是發送此消息給這個窗口WM_ACTIVATEAPP
發此消息給應用程序哪個窗口是激活的,哪個是非激活的
WM_FONTCHANGE 當系統的字體資源庫變化時發送此消息給所有頂級窗口
WM_TIMECHANGE 當系統的時間變化時發送此消息給所有頂級窗口
WM_CANCELMODE 發送此消息來取消某種正在進行的摸態(操作)
WM_SETCURSOR 如果鼠標引起光標在某個窗口中移動且鼠標輸入沒有被捕獲時,就發消息給某個窗口
WM_MOUSEACTIVATE 當光標在某個非激活的窗口中而用戶正按着鼠標的某個鍵發送此消息給當前窗口
WM_CHILDACTIVATE 發送此消息給MDI子窗口當用戶點擊此窗口的標題欄,或當窗口被激活,移動,改變大小
WM_QUEUESYNC 此消息由基於計算機的訓練程序發送,通過WH_JOURNALPALYBACK的hook程序分離出用戶輸入消息
WM_GETMINMAXINFO 此消息發送給窗口當它將要改變大小或位置
WM_PAINTICON 發送給最小化窗口當它圖標將要被重畫
WM_ICONERASEBKGND 此消息發送給某個最小化窗口,僅當它在畫圖標前它的背景必須被重畫
WM_NEXTDLGCTL 發送此消息給一個對話框程序去更改焦點位置
WM_SPOOLERSTATUS 每當打印管理列隊增加或減少一條作業時發出此消息
WM_DRAWITEM 當button,combobox,listbox,menu的可視外觀改變時發送
WM_MEASUREITEM 當button, combo box, list box, list,view control, or menu item 被創建時
WM_VKEYTOITEM 此消息有一個LBS_WANTKEYBOARDINPUT風格的發出給它的所有者來響應WM_KEYDOWN消息
WM_CHARTOITEM 此消息由一個LBS_WANTKEYBOARDINPUT風格的列表框發送給他的所有者來響應WM_CHAR消息
WM_SETFONT 當繪製文本時程序發送此消息得到控件要用的顏色
WM_GETFONT 應用程序發送此消息得到當前控件繪製文本的字體
WM_SETHOTKEY 應用程序發送此消息讓一個窗口與一個熱鍵相關連
WM_GETHOTKEY 應用程序發送此消息來判斷熱鍵與某個窗口是否有關聯
WM_QUERYDRAGICON 此消息發送給最小化窗口,當此窗口將要被拖放而它的類中沒有定義圖標,
應用程序能返回一個圖標或光標的句柄,當用戶拖放圖標時系統顯示這個圖標或光標
WM_COMPAREITEM 發送此消息來判定combobox或listbox新增加的項的相對位置
WM_COMPACTING 顯示內存已經很少了
WM_WINDOWPOSCHANGING 發送此消息給那個窗口的大小和位置將要被改變時,來調用setwindowpos函數或其它窗口管理函數
WM_WINDOWPOSCHANGED 發送此消息給那個窗口的大小和位置已經被改變時,來調用setwindowpos函數或其它窗口管理函數
WM_POWER 當系統將要進入暫停狀態時發送此消息
WM_COPYDATA 當一個應用程序傳遞數據給另一個應用程序時發送此消息
WM_CANCELJOURNA 當某個用戶取消程序日誌激活狀態,提交此消息給程序
WM_NOTIFY 當某個控件的某個事件已經發生或這個控件需要得到一些信息時,發送此消息給它的父窗口
WM_INPUTLANGCHANGEREQUEST 當用戶選擇某種輸入語言,或輸入語言的熱鍵改變
WM_INPUTLANGCHANGE 當平臺現場已經被改變後發送此消息給受影響的最頂級窗口
WM_TCARD 當程序已經初始化windows幫助例程時發送此消息給應用程序
WM_HELP 此消息顯示用戶按下了F1,如果某個菜單是激活的,就發送此消息個此窗口關聯的菜單,
否則就發送給有焦點的窗口,如果當前都沒有焦點,就把此消息發送給當前激活的窗口
WM_USERCHANGED 當用戶已經登入或退出後發送此消息給所有的窗口,當用戶登入或退出時系統更新用戶的具體設置信息,
在用戶更新設置時系統馬上發送此消息
WM_NOTIFYformAT 公用控件,自定義控件和他們的父窗口通過此消息來判斷控件是使用ANSI還是UNICODE結構
WM_CONTEXTMENU 當用戶某個窗口中點擊了一下右鍵就發送此消息給這個窗口
WM_styleCHANGING 當調用SETWINDOWLONG函數將要改變一個或多個 窗口的風格時發送此消息給那個窗口
WM_styleCHANGED 當調用SETWINDOWLONG函數一個或多個 窗口的風格後發送此消息給那個窗口
WM_DISPLAYCHANGE 當顯示器的分辨率改變後發送此消息給所有的窗口
WM_GETICON 此消息發送給某個窗口來返回與某個窗口有關連的大圖標或小圖標的句柄
WM_SETICON 程序發送此消息讓一個新的大圖標或小圖標與某個窗口關聯
WM_NCCREATE 當某個窗口第一次被創建時,此消息在WM_CREATE消息發送前發送
WM_NCDESTROY 此消息通知某個窗口,非客戶區正在銷燬
WM_NCCALCSIZE 當某個窗口的客戶區域必須被覈算時發送此消息
WM_NCHITTEST 移動鼠標,按住或釋放鼠標時發生
WM_NCPAINT 程序發送此消息給某個窗口當它(窗口)的框架必須被繪製時
WM_NCACTIVATE 此消息發送給某個窗口僅當它的非客戶區需要被改變來顯示是激活還是非激活狀態
WM_GETDLGCODE 發送此消息給某個與對話框程序關聯的控件,widdows控制方位鍵和TAB鍵使輸入進入此控件通過應
WM_NCMOUSEMOVE 當光標在一個窗口的非客戶區內移動時發送此消息給這個窗口 非客戶區爲:窗體的標題欄及窗 的邊框體
WM_NCLBUTTONDOWN 當光標在一個窗口的非客戶區同時按下鼠標左鍵時提交此消息
WM_NCLBUTTONUP 當用戶釋放鼠標左鍵同時光標某個窗口在非客戶區十發送此消息
WM_NCLBUTTONDBLCLK 當用戶雙擊鼠標左鍵同時光標某個窗口在非客戶區十發送此消息
WM_NCRBUTTONDOWN 當用戶按下鼠標右鍵同時光標又在窗口的非客戶區時發送此消息
WM_NCRBUTTONUP 當用戶釋放鼠標右鍵同時光標又在窗口的非客戶區時發送此消息
WM_NCRBUTTONDBLCLK 當用戶雙擊鼠標右鍵同時光標某個窗口在非客戶區十發送此消息
WM_NCMBUTTONDOWN 當用戶按下鼠標中鍵同時光標又在窗口的非客戶區時發送此消息
WM_NCMBUTTONUP 當用戶釋放鼠標中鍵同時光標又在窗口的非客戶區時發送此消息
WM_NCMBUTTONDBLCLK 當用戶雙擊鼠標中鍵同時光標又在窗口的非客戶區時發送此消息
WM_KEYFIRST WM_KEYDOWN 按下一個鍵
WM_KEYUP 釋放一個鍵
WM_CHAR 按下某鍵,並已發出WM_KEYDOWN, WM_KEYUP消息
WM_DEADCHAR 當用translatemessage函數翻譯
WM_KEYUP 消息時發送此消息給擁有焦點的窗口
WM_SYSKEYDOWN 當用戶按住ALT鍵同時按下其它,鍵時提交此消息給擁有焦點的窗口
WM_SYSKEYUP 當用戶釋放一個鍵同時ALT 鍵還按着時提交此消息給擁有焦點的窗口
WM_SYSCHAR 當WM_SYSKEYDOWN消息被TRANSLATEMESSAGE函數翻譯後提交此消息給擁有焦點的窗口
WM_SYSDEADCHAR 當WM_SYSKEYDOWN消息被TRANSLATEMESSAGE函數翻譯後發送此消息給擁有焦點的窗口
WM_INITDIALOG 在一個對話框程序被顯示前發送此消息給它,通常用此消息初始化控件和執行其它任務
WM_COMMAND 當用戶選擇一條菜單命令項或當某個控件發送一條消息給它的父窗口,一個快捷鍵被翻譯
WM_SYSCOMMAND 當用戶選擇窗口菜單的一條命令或當用戶選擇最大化或最小化時那個窗口會收到此消息
WM_TIMER 發生了定時器事件
WM_HSCROLL 當一個窗口標準水平滾動條產生一個滾動事件時發送此消息給那個窗口,也發送給擁有它的控件
WM_VSCROLL 當一個窗口標準垂直滾動條產生一個滾動事件時發送此消息給那個窗口也,發送給擁有它的控件
WM_INITMENU 當一個菜單將要被激活時發送此消息,它發生在用戶菜單條中的某項或按下某個菜單鍵,
它允許程序在顯示前更改菜單
WM_INITMENUPOPUP 當一個下拉菜單或子菜單將要被激活時發送此消息,它允許程序在它顯示前更改菜單,而不要改變全部
WM_MENUSELECT 當用戶選擇一條菜單項時發送此消息給菜單的所有者(一般是窗口)
WM_MENUCHAR 當菜單已被激活用戶按下了某個鍵(不同於加速鍵),發送此消息給菜單的所有者
WM_ENTERIDLE 當一個模態對話框或菜單進入空載狀態時發送此消息給它的所有者,
一個模態對話框或菜單進入空載狀態就是在處理完一條或幾條先前的消息後沒有消息它的列隊中等待
WM_CTLCOLORMSGBOX 在windows繪製消息框前發送此消息給消息框的所有者窗口,通過響應這條消息,
所有者窗口可以通過使用給定的相關顯示設備的句柄來設置消息框的文本和背景顏色
WM_CTLCOLOREDIT 當一個編輯型控件將要被繪製時發送此消息給它的父窗口 通過響應這條消息,
所有者窗口可以通過使用給定的相關顯示設備的句柄來設置編輯框的文本和背景顏色
WM_CTLCOLORLISTBOX 當一個列表框控件將要被繪製前發送此消息給它的父窗口 通過響應這條消息,
所有者窗口可以通過使用給定的相關顯示設備的句柄來設置列表框的文本和背景顏色
WM_CTLCOLORBTN 當一個按鈕控件將要被繪製時發送此消息給它的父窗口 通過響應這條消息,
所有者窗口可以通過使用給定的相關顯示設備的句柄來設置按紐的文本和背景顏色
WM_CTLCOLORDLG 當一個對話框控件將要被繪製前發送此消息給它的父窗口 通過響應這條消息,
所有者窗口可以通過使用給定的相關顯示設備的句柄來設置對話框的文本背景顏色
WM_CTLCOLORSCROLLBAR 當一個滾動條控件將要被繪製時發送此消息給它的父窗口 通過響應這條消息,
所有者窗口可以通過使用給定的相關顯示設備的句柄來設置滾動條的背景顏色
WM_CTLCOLORSTATIC 當一個靜態控件將要被繪製時發送此消息給它的父窗口 通過響應這條消息,
所有者窗口可以 通過使用給定的相關顯示設備的句柄來設置靜態控件的文本和背景顏色
WM_MOUSEFIRST WM_MOUSEMOVE 移動鼠標
WM_LBUTTONDOWN 按下鼠標左鍵
WM_LBUTTONUP 釋放鼠標左鍵
WM_LBUTTONDBLCLK 雙擊鼠標左鍵
WM_RBUTTONDOWN 按下鼠標右鍵
WM_RBUTTONUP 釋放鼠標右鍵
WM_RBUTTONDBLCLK 雙擊鼠標右鍵
WM_MBUTTONDOWN 按下鼠標中鍵
WM_MBUTTONUP 釋放鼠標中鍵
WM_MBUTTONDBLCLK 雙擊鼠標中鍵
WM_MOUSEWHEEL 當鼠標輪子轉動時發送此消息個當前有焦點的控件
WM_PARENTNOTIFY 當MDI子窗口被創建或被銷燬,或用戶按了一下鼠標鍵而光標在子窗口上時發送此消息給它的父窗口
WM_ENTERMENULOOP 發送此消息通知應用程序的主窗口that已經進入了菜單循環模式
WM_EXITMENULOOP 發送此消息通知應用程序的主窗口that已退出了菜單循環模式
WM_SIZING 當用戶正在調整窗口大小時發送此消息給窗口 通過此消息應用程序可以監視窗口大小和位置也可以修改他們
WM_CAPTURECHANGED 發送此消息 給窗口當它失去捕獲的鼠標時
WM_MOVING 當用戶在移動窗口時發送此消息,通過此消息應用程序可以監視窗口大小和位置也可以修改他們
WM_POWERBROADCAST 此消息發送給應用程序來通知它有關電源管理事件
當客戶窗口收到此消息後,它發出WM_MDIACTIVE消息給MDI子窗口(未激活)激活它 它允許用剪貼板觀察窗口來顯示剪貼板的新內容 |
什麼是消息?
消息系統對於一個win32程序來說十分重要,它是一個程序運行的動力源泉。一個消息,是系統定義的一個32位的值,他唯一的定義了一個事件,向Windows發出一個通知,告訴應用程序某個事情發生了。例如,單擊鼠標、改變窗口尺寸、按下鍵盤上的一個鍵都會使Windows發送一個消息給應用程序。
消息本身是作爲一個記錄傳遞給應用程序的,這個記錄中包含了消息的類型以及其他信息。例如,對於單擊鼠標所產生的消息來說,這個記錄中包含了單擊鼠標時的座標。這個記錄類型叫做MSG,MSG含有來自windows應用程序消息隊列的消息信息,它在Windows中聲明如下:
typedef struct tagMsg
{
HWND hwnd; 接受該消息的窗口句柄
UINT message; 消息常量標識符,也就是我們通常所說的消息號
WPARAM wParam; 32位消息的特定附加信息,確切含義依賴於消息值
LPARAM lParam; 32位消息的特定附加信息,確切含義依賴於消息值
DWORD time; 消息創建時的時間
POINT pt; 消息創建時的鼠標/光標在屏幕座標系中的位置
}MSG;
消息可以由系統或者應用程序產生。系統在發生輸入事件時產生消息。舉個例子, 當用戶敲鍵, 移動鼠標或者單擊控件。系統也產生消息以響應由應用程序帶來的變化, 比如應用程序改變系統字體改變窗體大小。應用程序可以產生消息使窗體執行任務,或者與其他應用程序中的窗口通訊。
消息中有什麼?
我們給出了上面的註釋,是不是會對消息結構有了一個比較清楚的認識?如果還沒有,那麼我們再試着給出下面的解釋:
hwnd 32位的窗口句柄。窗口可以是任何類型的屏幕對象,因爲Win32能夠維護大多數可視對象的句柄(窗口、對話框、按鈕、編輯框等)。
message用於區別其他消息的常量值,這些常量可以是Windows單元中預定義的常量,也可以是自定義的常量。消息標識符以常量命名的方式指出消息的含義。當窗口過程接收到消息之後,他就會使用消息標識符來決定如何處理消息。例如、WM_PAINT告訴窗口過程窗體客戶區被改變了需要重繪。符號常量指定系統消息屬於的類別,其前綴指明瞭處理解釋消息的窗體的類型。
wParam 通常是一個與消息有關的常量值,也可能是窗口或控件的句柄。
lParam 通常是一個指向內存中數據的指針。由於WParam、lParam和Pointer都是32位的,因此,它們之間可以相互轉換。
消息標識符的值
系統保留消息標識符的值在0x0000在0x03ff(WM_USER-1)範圍。這些值被系統定義消息使用。 應用程序不能使用這些值給自己的消息。應用程序消息從WM_USER(0X0400)到0X7FFF,或0XC000到0XFFFF;WM_USER到0X7FFF範圍的消息由應用程序自己使用;0XC000到0XFFFF範圍的消息用來和其他應用程序通信,我們順便說一下具有標誌性的消息值:
WM_NULL---0x0000 空消息。
0x0001----0x0087 主要是窗口消息。
0x00A0----0x00A9 非客戶區消息
0x0100----0x0108 鍵盤消息
0x0111----0x0126 菜單消息
0x0132----0x0138 顏色控制消息
0x0200----0x020A 鼠標消息
0x0211----0x0213 菜單循環消息
0x0220----0x0230 多文檔消息
0x03E0----0x03E8 DDE消息
0x0400 WM_USER
0x8000 WM_APP
0x0400----0x7FFF 應用程序自定義私有消息
消息有的分類?
其實,windows中的消息雖然很多,但是種類並不繁雜,大體上有3種:窗口消息、命令消息和控件通知消息。
窗口消息大概是系統中最爲常見的消息,它是指由操作系統和控制其他窗口的窗口所使用的消息。例如CreateWindow、DestroyWindow和MoveWindow等都會激發窗口消息,還有我們在上面談到的單擊鼠標所產生的消息也是一種窗口消息。
命令消息,這是一種特殊的窗口消息,他用來處理從一個窗口發送到另一個窗口的用戶請求,例如按下一個按鈕,他就會向主窗口發送一個命令消息。
控件通知消息,是指這樣一種消息,一個窗口內的子控件發生了一些事情,需要通知父窗口。通知消息只適用於標準的窗口控件如按鈕、列表框、組合框、編輯框,以及Windows公共控件如樹狀視圖、列表視圖等。例如,單擊或雙擊一個控件、在控件中選擇部分文本、操作控件的滾動條都會產生通知消息。 她類似於命令消息,當用戶與控件窗口交互時,那麼控件通知消息就會從控件窗口發送到它的主窗口。但是這種消息的存在並不是爲了處理用戶命令,而是爲了讓主窗口能夠改變控件,例如加載、顯示數據。例如按下一個按鈕,他向父窗口發送的消息也可以看作是一個控件通知消息;單擊鼠標所產生的消息可以由主窗口直接處理,然後交給控件窗口處理。
其中窗口消息及控件通知消息主要由窗口類即直接或間接由CWND類派生類處理。相對窗口消息及控件通知消息而言,命令消息的處理對象範圍就廣得多,它不僅可以由窗口類處理,還可以由文檔類,文檔模板類及應用類所處理。
由於控件通知消息很重要的,人們用的也比較多,但是具體的含義往往令初學者暈頭轉向,所以我決定把常見的幾個列出來供大家參考:
按扭控件
BN_CLICKED 用戶單擊了按鈕
BN_DISABLE 按鈕被禁止
BN_DOUBLECLICKED 用戶雙擊了按鈕
BN_HILITE 用/戶加亮了按鈕
BN_PAINT 按鈕應當重畫
BN_UNHILITE 加亮應當去掉
組合框控件
CBN_CLOSEUP 組合框的列表框被關閉
CBN_DBLCLK 用戶雙擊了一個字符串
CBN_DROPDOWN 組合框的列表框被拉出
CBN_EDITCHANGE 用戶修改了編輯框中的文本
CBN_EDITUPDATE 編輯框內的文本即將更新
CBN_ERRSPACE 組合框內存不足
CBN_KILLFOCUS 組合框失去輸入焦點
CBN_SELCHANGE 在組合框中選擇了一項
CBN_SELENDCANCEL 用戶的選擇應當被取消
CBN_SELENDOK 用戶的選擇是合法的
CBN_SETFOCUS 組合框獲得輸入焦點
編輯框控件
EN_CHANGE 編輯框中的文本己更新
EN_ERRSPACE 編輯框內存不足
EN_HSCROLL 用戶點擊了水平滾動條
EN_KILLFOCUS 編輯框正在失去輸入焦點
EN_MAXTEXT 插入的內容被截斷
EN_SETFOCUS 編輯框獲得輸入焦點
EN_UPDATE 編輯框中的文本將要更新
EN_VSCROLL 用戶點擊了垂直滾動條消息含義
列表框控件
LBN_DBLCLK 用戶雙擊了一項
LBN_ERRSPACE 列表框內存不夠
LBN_KILLFOCUS 列表框正在失去輸入焦點
LBN_SELCANCEL 選擇被取消
LBN_SELCHANGE 選擇了另一項
LBN_SETFOCUS 列表框獲得輸入焦點
隊列消息和非隊列消息
從消息的發送途徑來看,消息可以分成2種:隊列消息和非隊列消息。消息隊列由可以分成系統消息隊列和線程消息隊列。系統消息隊列由Windows維護,線程消息隊列則由每個GUI線程自己進行維護,爲避免給non-GUI現成創建消息隊列,所有線程產生時並沒有消息隊列,僅當線程第一次調用GDI函數數系統給線程創建一個消息隊列。隊列消息送到系統消息隊列,然後到線程消息隊列;非隊列消息直接送給目的窗口過程。
對於隊列消息,最常見的是鼠標和鍵盤觸發的消息,例如WM_MOUSERMOVE,WM_CHAR等消息,還有一些其它的消息,例如:WM_PAINT、WM_TIMER和WM_QUIT。當鼠標、鍵盤事件被觸發後,相應的鼠標或鍵盤驅動程序就會把這些事件轉換成相應的消息,然後輸送到系統消息隊列,由Windows系統去進行處理。Windows系統則在適當的時機,從系統消息隊列中取出一個消息,根據前面我們所說的MSG消息結構確定消息是要被送往那個窗口,然後把取出的消息送往創建窗口的線程的相應隊列,下面的事情就該由線程消息隊列操心了,Windows開始忙自己的事情去了。線程看到自己的消息隊列中有消息,就從隊列中取出來,通過操作系統發送到合適的窗口過程去處理。 //有關Windows中消息的走向的說明
一般來講,系統總是將消息Post在消息隊列的末尾。這樣保證窗口以先進先出的順序接受消息。然而,WM_PAINT是一個例外,同一個窗口的多個 WM_PAINT被合併成一個 WM_PAINT 消息, 合併所有的無效區域到一個無效區域。合併WM_PAIN的目的是爲了減少刷新窗口的次數。
非隊列消息將會繞過系統隊列和消息隊列,直接將消息發送到窗口過程,。系統發送非隊列消息通知窗口,系統發送消息通知窗口。 例如,當用戶激活一個窗口系統發送WM_ACTIVATE, WM_SETFOCUS, and WM_SETCURSOR。這些消息通知窗口它被激活了。非隊列消息也可以由當應用程序調用系統函數產生。例如,當程序調用SetWindowPos系統發送WM_WINDOWPOSCHANGED消息。一些函數也發送非隊列消息,例如下面我們要談到的函數。
消息的發送
瞭解了上面的這些基礎理論之後,我們就可以進行一下簡單的消息發送與接收。
把一個消息發送到窗口有3種方式:發送、寄送和廣播。
發送消息的函數有SendMessage、SendMessageCallback、SendNotifyMessage、SendMessageTimeout;寄送消息的函數主要有PostMessage、PostThreadMessage、PostQuitMessage;廣播消息的函數我知道的只有BroadcastSystemMessage、BroadcastSystemMessageEx。
SendMessage的原型如下:LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam),這個函數主要是向一個或多個窗口發送一條消息,一直等到消息被處理之後纔會返回。不過需要注意的是,如果接收消息的窗口是同一個應用程序的一部分,那麼這個窗口的窗口函數就被作爲一個子程序馬上被調用;如果接收消息的窗口是被另外的線程所創建的,那麼窗口系統就切換到相應的線程並且調用相應的窗口函數,這條消息不會被放進目標應用程序隊列中。函數的返回值是由接收消息的窗口的窗口函數返回,返回的值取決於被髮送的消息。
PostMessage的原型如下:BOOL PostMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam),該函數把一條消息放置到創建hWnd窗口的線程的消息隊列中,該函數不等消息被處理就馬上將控制返回。需要注意的是,如果hWnd參數爲HWND_BROADCAST,那麼,消息將被寄送給系統中的所有的重疊窗口和彈出窗口,但是子窗口不會收到該消息;如果hWnd參數爲NULL,則該函數類似於將dwThreadID參數設置成當前線程的標誌來調用PostThreadMEssage函數。
從上面的這2個具有代表性的函數,我們可以看出消息的發送方式和寄送方式的區別所在:被髮送的消息是否會被立即處理,函數是否立即返回。被髮送的消息會被立即處理,處理完畢後函數纔會返回;被寄送的消息不會被立即處理,他被放到一個先進先出的隊列中,一直等到應用程序空線的時候纔會被處理,不過函數放置消息後立即返回。
實際上,發送消息到一個窗口處理過程和直接調用窗口處理過程之間並沒有太大的區別,他們直接的唯一區別就在於你可以要求操作系統截獲所有被髮送的消息,但是不能夠截獲對窗口處理過程的直接調用。
以寄送方式發送的消息通常是與用戶輸入事件相對應的,因爲這些事件不是十分緊迫,可以進行緩慢的緩衝處理,例如鼠標、鍵盤消息會被寄送,而按鈕等消息則會被髮送。
廣播消息用得比較少,BroadcastSystemMessage函數原型如下:
long BroadcastSystemMessage(DWORD dwFlags,LPDWORD lpdwRecipients,UINT uiMessage,WPARAM wParam,LPARAM lParam);
該函數可以向指定的接收者發送一條消息,這些接收者可以是應用程序、可安裝的驅動程序、網絡驅動程序、系統級別的設備驅動消息和他們的任意組合。需要注意的是,如果dwFlags參數是BSF_QUERY並且至少一個接收者返回了BROADCAST_QUERY_DENY,則返回值爲0,如果沒有指定BSF_QUERY,則函數將消息發送給所有接收者,並且忽略其返回值。