2008年8月18日 星期一

使用全域熱鍵(Global hotkey)在VB .NET

這篇文章是介紹如何使用VB 2005來編寫可以讀取全域熱鍵(foobar翻成整體熱鍵)的程式,如果你是要找怎麼利用整體熱鍵,那很抱歉你可能迷路了XXD。
在開始寫程式之前,先來稍微介紹一下整體熱鍵的運作方式。
如左圖所示,一般來說,鍵盤上面的訊號是先送給OS處理後,經過管理程序再送給目前活動中(in active)的程序;所以當程式並不是在活動中,那麼自然就不會接收到目前鍵盤的訊號。
而全域熱鍵的用處就在於即使我的程式已經是在背景中,假如鍵盤有相對應的鍵被按下,我的程式也能夠做出想要的回應。而在XP系統下,提供了一個動態函式庫來讓我得以達成以上的需求:user32.dll。我可以藉由user32.dll向管理程序去通知說,我也要接收某些特定的鍵盤訊號,不論我是不是在活動中。註冊完畢後,當鍵盤有訊號進來,管理程序就會看目前進來的訊號是不是有人註冊過,如果有,這個值除了會丟給目前活動中的程序,也會丟給我註冊過的程序。
打個比方好了,就像是像在很常見的網路促銷活動,在一般的情況下如果要知道某商家有沒有特價或是促銷,只能透過商家固定的廣告來得到該資訊,或是要直接到賣場去才能看到。這就是一般的模式下情況,只有固定的一些程序(像是活動中的程序)才能獲得目前鍵盤的資訊。而假如我加入商家的會員,或是到他們的網站上去註冊,那麼就只要打開email(或是實體信箱),就可以知道商家最近有沒有什麼新的特價方案,就只要等著商家就會把訊息傳過來。我的程序也是一樣,一但完成了註冊的動作,負責管理鍵盤訊號的程序就會在有我所觀察的把訊發生之後,一並通知我。
所以在程式的一開始,我必須做這兩行的宣告:
Private Declare Function RegisterHotKey Lib "user32" (ByVal hwnd As IntPtr, ByVal id As Integer, ByVal fsModifiers As Integer, ByVal vk As Integer) As Integer
Private Declare Sub UnregisterHotKey Lib "user32" (ByVal hwnd As IntPtr, ByVal id As Integer)
告訴程式說,在接下來的程式碼中我需要這兩個從user32函式庫中的函式。
接下來的步驟比較繁複一點,須要參看程式碼,不過部落格中的空白都會被清空,內縮的格式會跑掉變得很難看,所以程式碼就貼在google文件中,連結在這
從form load開始看起,可以看到其中只有一行程式碼,裡面寫的是RegisterGlobalHotKey這個函式,目的是完成整個註冊全域熱鍵的動作,如果懶的去改直接就整個抓去用。比較要注意的是,取得hotkeyID的atomName,原程式碼中是利用threadID去做,不過用這麼麻煩的東西是可以用拉~。而其中 GlobalAddAtom函式就是取得一個類是hash code的東西,他會在系統的atom table寫入原字串以及獲得的atom(類似hash後的key值),在此程式中是利用此函式來得到用來註冊的hotkeyID值。
從form load上面一點看,會看到許多常數的宣告,那些是代表alt, shift, ctrl之類的鍵,不用做任何改變就可以。然後既然有註冊hotkey,當然也要有反註冊的函式UnregisterHotKey,當我們程式要結束的時候通知一下,這個程式已經死掉拉~~不要再寄訊息過來了。所以就照著程式碼那樣把反註冊函式寫完整在UnregisterGlobalHotKey,然後補在form closed(或是closing都可)裡面,讓程式結束後可以把hotkey反註冊掉。
接下來就是最重要的地方拉,如果要讓全域鍵按下後程式有所反應,程式碼就要寫在WndProc裡面。這個函式主要是接收從其他程序丟過來的訊息,所以當丟過來的訊息使說有使用者按下了我所設定的全域鍵,那麼就要給他好好處理一下拉。如果有要在全域熱鍵按下後所執行的程式碼,那麼就要寫在If m.Msg = WM_HOTKEY的裡面。在這個範例中,只做了一個計數器,來計算全域熱鍵被按下幾次,並且在全域熱鍵按下後,將自己設定為活動中的狀態。
這篇就寫到這樣吧,如果要加入全域熱鍵,直接把整篇程式碼給加進去其實也就差不多了XXD,只要把一些地方給改變一下,像是全域熱鍵的設定、按下熱鍵後的處理等比較重要的地方改一下,就可以用了。
在網路上還有找到另外一種做法,一樣是利用user32這個函式庫,又興趣的人可以參考一下^^。
參考網址:
http://www.codeguru.com/vb/gen/vb_system/keyboard/article.php/c4829/
http://www.vbforums.com/showthread.php?t=506461

沒有留言: