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

 

posted on 2022-12-12 09:43  高彰  阅读(469)  评论(0编辑  收藏  举报

导航