write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie
討論新聞群組及檔案
全域快速鍵屬於比較有用的功能了,在Windows下使用RegisterHotkey可以很方便的設定,(指的是通過程式設定啊)Qt中沒有封裝此功能,所以稍微麻煩一點,可以參看我原來的文章《Qt/PyQt中使用系統全域的快速鍵》,換到了MacOS中後,又得重新學習了,真是悲哀。。。。。。。
搜遍互連網,才總算髮現有用的文章,《Program Global Hotkeys in Cocoa Easily》一文真是精華中的精華。不僅說明了怎麼在MacOS中設定全域快速鍵,而且超額的指點了怎麼讓使用者在程式中自訂。。。。強就一個字,作者絕對是介於牛A及牛C之間的人物。
唯一還有點遺憾的是,作者雖然是說用Cocoa,但是其實使用了carbon架構,而carbon架構使用的還是C語言的介面,並且有回呼函數的設定,導致介面使用上不能用純Objective C。。。。。。
本文僅記錄大致使用流程,作為備檔,詳細的介面意義及各類,結構的意義未作詳細說明(文檔中我都沒有查到較為詳細的說明)。
準備工作
如上所述,用了Carbon架構,所以首先得為工程添加架構得連結依賴,然後使用上包含Carbon/Carbon.h檔案。
註冊全域快速鍵回呼函數
回呼函數的原型如下:
OSStatus MyHotKeyHandler(EventHandlerCallRef nextHandler,EventRef theEvent,
void *userData) {
}
註冊的方式
EventTypeSpec eventType;
eventType.eventClass=kEventClassKeyboard;
eventType.eventKind=kEventHotKeyPressed;
InstallApplicationEventHandler(MyHotKeyHandler, 1, &eventType,NULL, NULL);
主要的函數是InstallApplicationEventHandler,表示註冊相應的回呼函數,作為C語言介面,回調的函數原型必須一致。
註冊快速鍵
EventHotKeyRef gMyHotKeyRef;
EventHotKeyID gMyHotKeyID;
gMyHotKeyID.signature='rt2h';
gMyHotKeyID.id=1;
RegisterEventHotKey(6, controlKey, gMyHotKeyID,
GetApplicationEventTarget(), 0, &gMyHotKeyRef);
gMyHotKeyID.signature='te2h';
gMyHotKeyID.id=2;
RegisterEventHotKey(7, controlKey, gMyHotKeyID,
GetApplicationEventTarget(), 0, &gMyHotKeyRef);
註冊快速鍵,RegisterEventHotKey是整個過程中最重要的介面,第一個參數的數字,代表了最終響應的索引值,這裡有點奇怪,不是像Windows中那樣使用表示虛擬索引值的宏,而是直接用按鍵代表的數字來表示,而且此數字甚為奇怪,我也很為納悶。比如上面的6,7分別表示Z鍵和X鍵。這些數字我只有在《Program Global Hotkeys in Cocoa Easily》一文中提到的AsyncKeys軟體中我才能正確的知道。此軟體運行時,如:
上面就是我按Z鍵時,顯示的樣子,其中我們需要設定的值為AsyncKey Number那一欄的值,即6.。。。。。。。。原因不明,沒有深入瞭解。
RegisterEventHotKey第二參數是修飾鍵的設定參數,分別可以為cmdKey, shiftKey, optionKey,controlKey,各自的意思我想就不用我講了,不過需要注意的是,同時設定時不是用一般的|符號來組合,而是用+。。。。。。這點還真是比較奇怪,難道Mac下的介面都是這樣設定的嗎?-_-!對了,不需要設定這樣的常量感到奇怪,Mac下的代碼風格有所不同,以前Windows下(其實我在其他平台也是這樣),常量習慣性的全大寫,這樣大家就能知道這是不能改變的宏或者常量,但是Mac下的介面不是這樣。。。。但是,知道它們都是系統常量就好了。
實現回呼函數
OSStatus MyHotKeyHandler(EventHandlerCallRef nextHandler,EventRef theEvent,
void *userData) {
EventHotKeyID hkCom;
GetEventParameter(theEvent,kEventParamDirectObject,typeEventHotKeyID,NULL,
sizeof(hkCom),NULL,&hkCom);
int l = hkCom.id;
switch (l) {
case 1: //do something
convertRtfToHtml();
break;
case 2: //do something
convertTextToHtml();
break;
}
return noErr;
}
這裡通過GetEventParameter來擷取需要的資訊,然後通過事件的ID來分辨是哪個快速鍵按下。整個過程基本就是這樣了。
小結
接觸Cocoa的時間較短,發現介面設定的一些慣例都不太一樣,雖然在GUI世界,訊息(或者說事件)驅動是肯定的,但是在Windows的Win32 API及MFC那個層面編寫代碼的時候(.net不瞭解,就不知道了),訊息的流向是知道的,可控制的,訊息響應的時候也常常在OnMessage函數中自己去設定,但是Cocoa中感覺封裝的層次更加高一些,我不知道訊息從那兒來,又到哪兒去,只能通過回調或者控制項的binding,action的連結,類的委託來設定我希望被調用的函數,具體啥時候調用,入口在哪,我都無法控制,這點,可能屬於從較為底層跑到較為高層有點不適應。作為C/C++程式員,可能難免帶上了一定的刨根問底的性格,甚至一定要回溯到系統載入進程的彙編代碼才肯善罷甘休,不然總是覺得沒有底,在不能徹底瞭解一個庫的原始碼前,甚至都不敢大量的使用,不然效率怎麼樣,記憶體怎麼控制的,健壯不健壯總是沒底,到了Objective C with Cocoa的世界後,還有點不適應。。。。。。。。。。
原創文章作者保留著作權 轉載請註明原作者 並給出連結
write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie