離奇失蹤的WM_HOTKEY消息--淺析WIN32消息隊列

故事的開端有些平淡,眼紅於XXX小程序,認爲寫完該程序就有了和心儀的妹子多相處的機會,必須搞,必須酷,按鈕不能有,界面得隱藏,這就想到了全局快捷鍵。小程序

註冊調用RegisterHotKey(m_hWnd, 300, MOD_ALT, 'K');函數

定義消息處理函數 afx_msg long OnHotKey(WPARAM wparam, LPARAM lparam);測試

消息關聯處理程序ON_MESSAGE(WM_HOTKEY, OnHotKey) spa

定義消息處理函數 ,switch(wparam)調用對應的函數處理。線程

測試了一下,一切OK,開始搜索其餘API,埋頭苦整,一番惡戰終於搞定其餘功能,開始登記其餘快捷鍵並調用處理過程。OH SHIT!快捷鍵沒效果了?難道是登記的快捷鍵衝突了?檢查了RegisterHotKey的返回值,是正確的,那麼登記快捷鍵確定沒問題!該怎麼辦呢?去查WIN32消息處理機制來解決問題吧翻譯

MFC總共有三種類型的消息:窗口、命令、控件通知,嗯,找找窗口消息是怎麼處理的。隊列

登記全局快捷鍵的原理解釋是:某鍵被按下時,系統在全部的熱鍵列表中尋找匹配者,匹配成功將WM_HOTKEY消息發送給登記了該熱鍵的線程的消息處理隊列。撓了撓腦殼,我認定WM_HOTKEY已經發送給指定的消息隊列。進程

-----補充知識點,發送消息有兩種形式:發送消息,即時到達並立馬調用目標窗口的進程,目標窗口必須爲調用函數返回一個結果才能繼續;寄送消息,將消息加入目標進程的消息隊列,應用程序有空閒時就會搜索消息隊列,從消息隊列中刪除消息並將消息發送給指定窗口,通訊可能延遲。鼠標和鍵盤消息因爲其特殊性,採用寄送的方式處理,其餘全部消息都是發送的方式。消息隊列

  到這裏就有點悟了,敢情我定義的全局快捷鍵處理函數OnHotKey並不會直接被調用,大膽猜想一下:窗口進程從消息隊列中取出寄送來的WM_HOTKEY消息後首先交給了窗口,而窗口線程收到WM_HOTKEY消息並無按照個人意願調用OhHotKey。再找一下窗口處理消息的機制。it

 寄送消息在被消息泵彈出以前會一直保留在消息隊列中,直到應用程序調用GetMessage函數從消息隊列中將之取出,取出後會調用PreTranslateMessage和TranslateMessage兩個函數進行消息翻譯,翻譯後的消息經過DispatchMessage調用該消息預期的目標窗口進程。看到這裏,不禁得笑了,這但是大有玄機啊,GO ON!

 PreTranslateMessage有點眼熟,果真從代碼裏找到這個知其然、不知其因此然的預處理函數。埋頭繼續查:絕大多數本窗口的消息都要通過PreTranslateMessage處理,若是想在MFC以前處理某消息,能夠重載該函數,重點來了,只有通過消息隊列的消息纔會通過PreTranslateMessage處理,即時發送的消息或其餘不通過消息隊列的消息不會理睬該函數,聯繫前面的寄送消息方式,各位小看官都應該懂了,快捷鍵消息到了這裏被截下來沒有發送給預期的窗口處理函數。挖,還得挖,這個坑有點苗頭了。

PretranslateMessage的定義和返回值仔細的看:是否調用TranslateMessage和DispatchMessage消息向指定窗口發送消息由PreTranslateMessage的返回值決定,當返回值爲TRUE的時候,不回把消息發送給對應的窗口函數處理,這難道是真相?預處理消息的時候挖坑把WM_HOTKEY消息給埋起來了?修改代碼,攔截到指定的消息後返回FALSE果真解決了問題。

隨着真相的浮出水面,我又一次期待着想象中的其樂融融,加油,我會作一個頗具高手風範的tool。 

相關文章
相關標籤/搜索