在MAC开发中,我们时常会有一些要监听鼠标或者键盘全局事件的需求,比如说如图一:当我鼠标点击程序其他位置的时候,我需要把在线状态这个小窗口给关掉,但是又不能影响事件的传递。此时我们就需要通过全局事件的锚点来实现(其他编程语言中也叫钩子事件):
还是先上代码:
```
self.mEventMonitor= [NSEvent addLocalMonitorForEventsMatchingMask:
NSLeftMouseDownMask|NSLeftMouseDraggedMask|NSLeftMouseUpMask
handler:^NSEvent*_Nullable(NSEvent* event) {
//获取触发事件坐标
NSPoint p = [event locationInWindow];
//判断坐标是否处于保护区内
NSPoint newP = [weakself.mBox_state convertPoint:p fromView:nil];
if(!CGRectContainsPoint(weakself.mBox_state.bounds, newP)) {
weakself.mBox_state.hidden = YES;
weakself.mBox_state=nil;
}
//把注册的锚点事件移除掉
[NSEvent removeMonitor:weakself.mEventMonitor];
weakself.mEventMonitor=nil;
//返回事件,让事件继续传递
returnevent;
}];
```
代码很简单,原理更简单,就是在系统在传递事件的过程中,插入了一个回调,而这个回调是一个Block,而我们需要做的就是通过addLocalMonitorForEventsMatchingMask函数给回调Block赋上值。触发Block回调的条件就是 addLocalMonitorForEventsMatchingMask 函数的第一个参数,是一个位枚举,上面代码给了三个触发条件,分别是NSLeftMouseDownMask、NSLeftMouseDraggedMask、NSLeftMouseUpMask。
上面代码之所以做一次判断事件坐标是否在保护区内,是不想在点击状态窗口的时候把窗口给关掉,因为我还要做改变在线状态的点击事件呢,你把窗口给我关掉了,控件给释放了,我还怎么继续?
下面,来看下苹果都给了哪些可以触发回调Block的条件:
```
typedefNS_OPTIONS(unsignedlonglong, NSEventMask) {/* masks for the types of events */
NSEventMaskLeftMouseDown=1<
NSEventMaskLeftMouseUp=1<
NSEventMaskRightMouseDown=1<
NSEventMaskRightMouseUp=1<
NSEventMaskMouseMoved=1<
NSEventMaskLeftMouseDragged=1<
NSEventMaskRightMouseDragged=1<
NSEventMaskMouseEntered=1<
NSEventMaskMouseExited=1<
NSEventMaskKeyDown=1<
NSEventMaskKeyUp=1<
NSEventMaskFlagsChanged=1<
NSEventMaskAppKitDefined=1<
NSEventMaskSystemDefined=1<
NSEventMaskApplicationDefined=1<
NSEventMaskPeriodic=1<
NSEventMaskCursorUpdate=1<
NSEventMaskScrollWheel=1<
NSEventMaskTabletPoint=1<
NSEventMaskTabletProximity=1<
NSEventMaskOtherMouseDown=1<
NSEventMaskOtherMouseUp=1<
NSEventMaskOtherMouseDragged=1<
/* The following event masks are available on some hardware on 10.5.2 and later */
NSEventMaskGestureNS_ENUM_AVAILABLE_MAC(10_5)=1<
NSEventMaskMagnifyNS_ENUM_AVAILABLE_MAC(10_5)=1<
NSEventMaskSwipeNS_ENUM_AVAILABLE_MAC(10_5)=1U <
NSEventMaskRotateNS_ENUM_AVAILABLE_MAC(10_5)=1<
NSEventMaskBeginGestureNS_ENUM_AVAILABLE_MAC(10_5)=1<
NSEventMaskEndGestureNS_ENUM_AVAILABLE_MAC(10_5)=1<
#if __LP64__
/* Note: You can only use these event masks on 64 bit. In other words, you cannot setup a local, nor global, event monitor for these event types on 32 bit. Also, you cannot search the event queue for them (nextEventMatchingMask:...) on 32 bit.
*/
NSEventMaskSmartMagnifyNS_ENUM_AVAILABLE_MAC(10_8) =1ULL <
NSEventMaskPressureNS_ENUM_AVAILABLE_MAC(10_10_3) =1ULL <
NSEventMaskDirectTouchNS_ENUM_AVAILABLE_MAC(10_12_1) =1ULL <
#endif
NSEventMaskAny=NSUIntegerMax,
};
```
啧啧,还真不少,算了,就不翻译了,只是为了大家看着方便才贴出来这儿的......