寫個小工具,需要用到鍵盤快捷鍵。但是我對于mac os 開發(fā),目前來講還是個小白。網(wǎng)上一番搜索,得到一些了解,到這里記錄一下,便于后來者翻閱。
在mac os中,事件大概有以下幾種方式可以捕獲進行操作:
1.注冊全局事件
2.事件監(jiān)控回調(diào)函數(shù)
3.基于NSResponder的回調(diào)。
1.注冊全局事件
不廢話了,直接上代碼。
1.使用的是Carbon庫,所以需要項目導(dǎo)入Carbon庫。

2.在某個地方調(diào)用注冊代碼
#import <Carbon/Carbon.h>
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
[SomeClass addGlobalHotKey:kVK_ANSI_1];//注冊數(shù)字按鈕1
[SomeClass addGlobalHotKey:kVK_ANSI_2];//注冊數(shù)字按鈕2
[SomeClass addGlobalHotKey:kVK_ANSI_3];//注冊數(shù)字按鈕3
}
/**
* 添加全局的快捷鍵
**/
+(void)addGlobalHotKey:(NSInteger)keyCode{
EventHotKeyRef gMyHotKeyRef;
EventHotKeyID gMyHotKeyID;
EventTypeSpec eventType;
eventType.eventClass = kEventClassKeyboard;
eventType.eventKind = kEventHotKeyPressed;
InstallApplicationEventHandler(&GlobalHotKeyHandler,1,&eventType,NULL,NULL);
gMyHotKeyID.signature = 'abcdef';
gMyHotKeyID.id = keyCode;
RegisterEventHotKey(keyCode, 0, gMyHotKeyID,GetApplicationEventTarget(), 0, &gMyHotKeyRef);
// RegisterEventHotKey(keyCode, cmdKey+optionKey, gMyHotKeyID,GetApplicationEventTarget(), 0, &gMyHotKeyRef);
}
上面里面需要注意的:keyCode 是Carbon/HIToolbox/Events.h 文件里面定義好的鍵盤值,可以自己去看一下。
enum {
kVK_ANSI_A = 0x00,
kVK_ANSI_S = 0x01,
kVK_ANSI_D = 0x02,
kVK_ANSI_F = 0x03,
kVK_ANSI_H = 0x04,
kVK_ANSI_G = 0x05,
kVK_ANSI_Z = 0x06,
kVK_ANSI_X = 0x07,
kVK_ANSI_C = 0x08,
kVK_ANSI_V = 0x09,
kVK_ANSI_B = 0x0B,
kVK_ANSI_Q = 0x0C,
kVK_ANSI_W = 0x0D,
kVK_ANSI_E = 0x0E,
kVK_ANSI_R = 0x0F,
kVK_ANSI_Y = 0x10,
kVK_ANSI_T = 0x11,
kVK_ANSI_1 = 0x12,
kVK_ANSI_2 = 0x13,
kVK_ANSI_3 = 0x14,
kVK_ANSI_4 = 0x15,
kVK_ANSI_6 = 0x16,
kVK_ANSI_5 = 0x17,
kVK_ANSI_Equal = 0x18,
kVK_ANSI_9 = 0x19,
kVK_ANSI_7 = 0x1A,
kVK_ANSI_Minus = 0x1B,
kVK_ANSI_8 = 0x1C,
kVK_ANSI_0 = 0x1D,
kVK_ANSI_RightBracket = 0x1E,
kVK_ANSI_O = 0x1F,
kVK_ANSI_U = 0x20,
kVK_ANSI_LeftBracket = 0x21,
kVK_ANSI_I = 0x22,
kVK_ANSI_P = 0x23,
kVK_ANSI_L = 0x25,
kVK_ANSI_J = 0x26,
kVK_ANSI_Quote = 0x27,
kVK_ANSI_K = 0x28,
kVK_ANSI_Semicolon = 0x29,
kVK_ANSI_Backslash = 0x2A,
kVK_ANSI_Comma = 0x2B,
kVK_ANSI_Slash = 0x2C,
kVK_ANSI_N = 0x2D,
kVK_ANSI_M = 0x2E,
kVK_ANSI_Period = 0x2F,
kVK_ANSI_Grave = 0x32,
kVK_ANSI_KeypadDecimal = 0x41,
kVK_ANSI_KeypadMultiply = 0x43,
kVK_ANSI_KeypadPlus = 0x45,
kVK_ANSI_KeypadClear = 0x47,
kVK_ANSI_KeypadDivide = 0x4B,
kVK_ANSI_KeypadEnter = 0x4C,
kVK_ANSI_KeypadMinus = 0x4E,
kVK_ANSI_KeypadEquals = 0x51,
kVK_ANSI_Keypad0 = 0x52,
kVK_ANSI_Keypad1 = 0x53,
kVK_ANSI_Keypad2 = 0x54,
kVK_ANSI_Keypad3 = 0x55,
kVK_ANSI_Keypad4 = 0x56,
kVK_ANSI_Keypad5 = 0x57,
kVK_ANSI_Keypad6 = 0x58,
kVK_ANSI_Keypad7 = 0x59,
kVK_ANSI_Keypad8 = 0x5B,
kVK_ANSI_Keypad9 = 0x5C
};
如果是組合鍵需要在RegisterEventHotKey的第二個參數(shù)加cmdKey+optionKey 這樣子。表示 cmdKey+optionKey+keyCode 鍵盤上3個按鈕同時按下。
RegisterEventHotKey(keyCode, cmdKey+optionKey, gMyHotKeyID,GetApplicationEventTarget(), 0, &gMyHotKeyRef);
另外參數(shù)重需要傳遞一個回調(diào)函數(shù)過去,也就是InstallApplicationEventHandler這個方法的第一個參數(shù)&GlobalHotKeyHandler,所以我們要在文件前面申明這個回調(diào)函數(shù)。
OSStatus GlobalHotKeyHandler(EventHandlerCallRef nextHandler,EventRef theEvent,
void *userData)
{
EventHotKeyID hkCom;
GetEventParameter(theEvent,kEventParamDirectObject,typeEventHotKeyID,NULL,
sizeof(hkCom),NULL,&hkCom);
int l = hkCom.id;
switch (l) {
case kVK_ANSI_1: //do something
NSLog(@"kVK_ANSI_1按下");
break;
case kVK_ANSI_2:
NSLog(@"kVK_ANSI_2按下");
break;
case kVK_ANSI_3:
NSLog(@"kVK_ANSI_3按下");
break;
}
return noErr;
}
在對應(yīng)的case里,可以發(fā)送全局通知,呼起業(yè)務(wù)邏輯。
2.事件監(jiān)控回調(diào)函數(shù)
事件監(jiān)控就是2個簡單的函數(shù):
+(void)addMonitorForEvent{
[NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskFlagsChanged handler:^NSEvent * _Nullable(NSEvent * event) {
NSUInteger flags = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
if (flags == NSEventModifierFlagCommand) {
// handle it
NSLog(@"NSCommandKeyMask");
}
NSLog(@"addLocalMonitorForEventsMatchingMask %@",event);
return event;
}];
[NSEvent addGlobalMonitorForEventsMatchingMask:NSEventMaskFlagsChanged handler:^(NSEvent *event){
NSUInteger flags = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
if (flags == NSEventModifierFlagCommand) {
// handle it
}
NSLog(@"addGlobalMonitorForEventsMatchingMask %@",event);
}];
}
如果app是激活狀態(tài)按下cmd按鈕,則會調(diào)用local方法。如果是在非激活狀態(tài)按下,則會調(diào)用global方法。
這個addMonitorForEvent 也是可以在app加載的時候就直接初始化。
3.基于NSResponder的回調(diào)。
這個應(yīng)該是最常用的快捷鍵了,就是重寫view的NSResponder對應(yīng)的事件函數(shù),達到捕獲按鍵事件處理的效果。
在自己的視圖(NSView)上面直接寫2個函數(shù),如下:
//需要捕獲command + 1234567890事件
- (void)keyDown:(NSEvent *)theEvent{
NSString *key = [theEvent charactersIgnoringModifiers];
if([self.numKeyStrArray containsObject:key]){
if([theEvent modifierFlags] & NSEventModifierFlagCommand){//command+num
[self pressNum:key];
}
}
[super keyDown:theEvent];
}
-(void)keyUp:(NSEvent *)theEvent {
}
-(void)pressNum:(NSString *)numStr{
NSLog(@" 按下 commnd + %@",numStr);
}
- (BOOL)acceptsFirstResponder{
return YES;
}
有補充的歡迎留言。