Windows 消息機(jī)制API
xiaoxi guanli jizhi
Windows平臺(tái)上的應(yīng)用程序是事件驅(qū)動(dòng)的 ,它們不會(huì)顯式地調(diào)用底層函數(shù)以獲得用戶輸入或其它信息,而是等待系統(tǒng)將這些信息提供給它們。同類定義的窗口向系統(tǒng)聲明一個(gè)唯一的 窗口過程函數(shù) (Window Procedures)。當(dāng)有關(guān)某一窗口句柄的事件發(fā)生時(shí)(比如:鼠標(biāo)單擊這個(gè)窗口,或鍵盤向這個(gè)窗口輸入一個(gè)字符),系統(tǒng)調(diào)用這個(gè)函數(shù),把某個(gè)特定的消息作為參數(shù)。
要向特定的窗口過程發(fā)送消息,Windows提供了以下函數(shù):
由于lpPrevWndFunc為同一類窗口共有,發(fā)送的消息在被某一窗口處理前事實(shí)上可能已被多個(gè)窗口接收。本文不會(huì)用到這一函數(shù),關(guān)于此函數(shù)的完整定義請(qǐng)參閱:
這一函數(shù)在中定義,它向唯一的窗口句柄發(fā)送消息,并只在發(fā)送的消息被處理后返回。與之相似的是PostMessageW,它在發(fā)送消息后立即返回,即只將消息添加到目的窗口句柄的消息隊(duì)列里,并不等待其處理。
HWND hwnd:接收消息的窗口句柄
(特別地(HWND)0xffff為廣播)
UINT Msg:發(fā)送的消息類型
WPARAM wParam:發(fā)送的消息
LPARAM lParam:發(fā)送消息的附加參數(shù)
實(shí)現(xiàn)刷屏
mian dui dui xiang
獲得Windows提供的API函數(shù)后,下面用C++實(shí)現(xiàn)。
首先將刷屏過程封裝到一個(gè)類中
--------Bomb.h--------
構(gòu)造類時(shí)向構(gòu)造函數(shù)提供刷屏消息的重復(fù)次數(shù)和刷屏消息 (UTF-16格式)
ShowMessage()用于調(diào)試,把當(dāng)前類保存的消息輸出到控制臺(tái)上
StartBombing(int)用于開始刷屏,參數(shù)定義開始刷屏前的延時(shí)。用戶可在這段延時(shí)內(nèi)把鍵盤焦點(diǎn)設(shè)置到目標(biāo)窗口上去,使目標(biāo)窗口句柄或得消息后把消息內(nèi)容加入到文本輸入框中去。此函數(shù)有一個(gè)無(wú)延遲參數(shù)的重載。
消息內(nèi)容存儲(chǔ)在私有段中一個(gè)類型為WPARAM的數(shù)組中(該類型在上文中有介紹),附加消息是一個(gè)值為NULL的LPARAM類型——實(shí)現(xiàn)本例中的功能不需要向SendMessageW()提供附加消息。
--------Bomb.cpp--------
出于某些考量,我們?cè)诖瞬惶峁┲饕瘮?shù)的定義。在StartBombing()中,程序按用戶設(shè)定的刷屏消息重復(fù)次數(shù)循環(huán)times次,并按消息長(zhǎng)度循環(huán)MessageLength,每次將消息字符串中的第j個(gè)字符以WH_CHAR模式向所有窗口廣播。獲得鍵盤輸入焦點(diǎn)的窗口會(huì)將其加入到文本框中。
在發(fā)送完一條消息后,通過keybd_event函數(shù)模擬一次【回車鍵按下】事件,使目標(biāo)窗口(比如:wechat)發(fā)送消息或換行。
--------Main.cpp--------
這是應(yīng)用程序入口點(diǎn)。注意它設(shè)置了wcout/wcin的本地化,使其將儲(chǔ)存在WPARAM類型(其本質(zhì)是unsigned int)中的UTF-16數(shù)據(jù)轉(zhuǎn)化為中文字符輸出/輸入。
可見,按以上代碼編譯的應(yīng)用程序已經(jīng)可以完成質(zhì)問馬人王的任務(wù)。然而, 這速度也太慢了?? 這個(gè)速度比打字快不了多少,如果這樣的話就沒必要用刷屏軟件了。哪里出了問題呢?
問題在于,如本文開頭介紹:SendMessageW()強(qiáng)制在目標(biāo)窗口過程將消息處理完畢后才返回,這使得整個(gè)過程變得相當(dāng)緩慢。
解決方法是顯而易見的:用PostMessageW()取代原函數(shù)。但是這樣做會(huì)帶來(lái)新的問題:Post函數(shù)只是簡(jiǎn)單地把消息加入到目標(biāo)的消息隊(duì)列去,之后立即返回。而原程序在Post/Send函數(shù)返回后會(huì)調(diào)用keybd_event()模擬一個(gè)鍵盤事件。然而,窗口過程處理消息的速度現(xiàn)在看來(lái)并不盡如人意,這往往會(huì)導(dǎo)致大量字符消息堆積在消息隊(duì)列中,最終導(dǎo)致鍵盤事件和消息發(fā)送間不協(xié)調(diào)(比如:微信PC端輸入框中堆積了很多信息而不發(fā)送,因?yàn)榛剀囨I按下事件沒有按正常順序處理)
所以,要兼顧消息的穩(wěn)定性和發(fā)送速度,就要把keybd_event替換成另一個(gè)PostMessageW(),使【回車鍵按下】這一事件也像其它字符事件那樣加入到消息隊(duì)列中去,這樣就能保證字符消息和回車間的先后順序不變。
-
存儲(chǔ)器
+關(guān)注
關(guān)注
38文章
7484瀏覽量
163765 -
WINDOWS
+關(guān)注
關(guān)注
3文章
3541瀏覽量
88626 -
C++語(yǔ)言
+關(guān)注
關(guān)注
0文章
147瀏覽量
6989
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論