macOS 开发 NSView添加鼠标监控
一、鼠标点击事件响应流程简述:
1.鼠标硬件先接收到用户点击;
2.然后交给鼠标驱动来处理,这个驱动是在Mac OS X内核运行的;
3.处理完就通过I/O Kit传递给window sever的事件队列。
4.而window server则负责分派这些事件到对应进程的run-loop.
二、步骤
1.自定义VC1 继承自NSView ;
2.在VC1.m的drawRect方法中添加监控区域NSTrackingArea和监控样式
- 如果VC1不添加NSTrackingArea,即使实现了监控方法,也不会调用。
- 监控区域要使用dirtyRect,而非self.frame,否则位置会错误。
鸣谢KeyboardLife
左边打印监听的位置点击事件等的数据,右边有颜色的就是监听鼠标的区域。
ViewController.m中
#import "ViewController.h" #import "VC1.h" @interface ViewController () @end @implementation ViewController -(void)viewDidLoad { [super viewDidLoad]; VC1 * view = [[VC1 alloc] initWithFrame:NSMakeRect(100, 100, 300, 300)]; [view setWantsLayer:YES];//开启layer支持,不然设置背景色无用 view.layer.backgroundColor = [NSColor blueColor].CGColor; [self.view addSubview:view]; } - (void)setRepresentedObject:(id)representedObject { [super setRepresentedObject:representedObject]; // Update the view, if already loaded. } @end
新建的VC1继承NSView
VC1.h
#import <Cocoa/Cocoa.h> NS_ASSUME_NONNULL_BEGIN @interface VC1 : NSView @end NS_ASSUME_NONNULL_END
VC1.m
#import "VC1.h" @interface VC1 () @end @implementation VC1 //鼠标进入追踪区域 -(void)mouseEntered:(NSEvent *)event { NSLog(@"mouseEntered ========="); } //mouserEntered之后调用 -(void)cursorUpdate:(NSEvent *)event { NSLog(@"cursorUpdate =========="); //更改鼠标光标样式 [[NSCursor pointingHandCursor] set]; } //鼠标退出追踪区域 -(void)mouseExited:(NSEvent *)event { NSLog(@"mouseExited ========"); } //鼠标左键按下 -(void)mouseDown:(NSEvent *)event { //event.clickCount 不是累计数。双击时调用mouseDown两次,clickCount第一次=1,第二次 = 2. if ([event clickCount] > 1) { //双击相关处理 } NSLog(@"mouseDown ==== clickCount: %ld buttonNumber: %ld",event.clickCount,event.buttonNumber); self.layer.backgroundColor = [NSColor redColor].CGColor; //获取鼠标点击位置坐标:先获取event发生的window中的坐标,在转换成view视图坐标系坐标。 NSPoint eventLocation = [event locationInWindow]; NSPoint center = [self convertPoint:eventLocation fromView:nil]; NSLog(@"center: %@",NSStringFromPoint(center)); //判断是否按下了Command键 if ([event modifierFlags] & NSEventModifierFlagCommand) { [self setFrameRotation:[self frameRotation] + 90.0]; [self setNeedsDisplay:YES]; NSLog(@"按下了Command键 ---- "); } } //鼠标左键起来 -(void)mouseUp:(NSEvent *)event { NSLog(@"mouseUp ======"); self.layer.backgroundColor = [NSColor greenColor].CGColor; } //鼠标右键按下 - (void)rightMouseDown:(NSEvent *)event { NSLog(@"rightMouseDown ======="); } //鼠标右键起来 - (void)rightMouseUp:(NSEvent *)event { NSLog(@"rightMouseUp ======= "); } //鼠标移动 - (void)mouseMoved:(NSEvent *)event { NSLog(@"mouseMoved ========= "); } //鼠标按住左键进行拖拽 - (void)mouseDragged:(NSEvent *)event { NSLog(@"mouseDragged ======== "); } //鼠标按住右键进行拖拽 - (void)rightMouseDragged:(NSEvent *)event { NSLog(@"rightMouseDragged ======= "); } #pragma mark 监控区域要使用dirtyRect,而非self.frame,否则位置会错误。 - (void)drawRect:(NSRect)dirtyRect { [super drawRect:dirtyRect]; // Drawing code here. [self addTrackingArea:[[NSTrackingArea alloc] initWithRect:dirtyRect options:NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingCursorUpdate | NSTrackingActiveWhenFirstResponder | NSTrackingActiveInKeyWindow | NSTrackingActiveInActiveApp | NSTrackingActiveAlways | NSTrackingAssumeInside | NSTrackingInVisibleRect | NSTrackingEnabledDuringMouseDrag owner:self userInfo:nil]]; [self becomeFirstResponder]; } @end