【问题标题】:How to Capture / Post system-wide Keyboard / Mouse events under Mac OS X?如何在 Mac OS X 下捕获/发布系统范围的键盘/鼠标事件?
【发布时间】:2022-05-09 21:02:08
【问题描述】:

对于脚本实用程序,我需要能够记录应用程序获得焦点时发生的一系列键盘和鼠标事件。第二部分是能够稍后将这些事件发送到活动窗口。

我不需要担心菜单或跟踪哪个窗口接收输入的标识符。

我知道如何在 Windows 下执行此操作,但不知道 Mac OS X。

【问题讨论】:

    标签: cocoa macos


    【解决方案1】:

    我要告诉你的第一件事是,如果用户在可访问性控制面板中启用对辅助设备的支持,你不能这样做。这是 OSX 内置的某种安全机制。

    这是我在我的一个应用程序中使用的代码片段:

    //this method calls a carbon method to attach a global event handler
    - (void)attachEventHandlers
    {
        //create our event type spec for the keyup
        EventTypeSpec eventType;
        eventType.eventClass = kEventClassKeyboard;
        eventType.eventKind = kEventRawKeyUp;
    
        //create a callback for our event to fire in
        EventHandlerUPP handlerFunction = NewEventHandlerUPP(globalKeyPress);
    
        //install the event handler
        OSStatus err = InstallEventHandler(GetEventMonitorTarget(), handlerFunction, 1, &eventType, self, NULL);
    
        //error checking
        if( err )
        {
            //TODO: need an alert sheet here
            NSLog(@"Error registering keyboard handler...%d", err);
        }
    
        //create our event type spec for the mouse events
        EventTypeSpec eventTypeM;
        eventTypeM.eventClass = kEventClassMouse;
        eventTypeM.eventKind = kEventMouseUp;
    
        //create a callback for our event to fire in
        EventHandlerUPP handlerFunctionM = NewEventHandlerUPP(globalMousePress);
    
        //install the event handler
        OSStatus errM = InstallEventHandler(GetEventMonitorTarget(), handlerFunctionM, 1, &eventTypeM, self, NULL);
    
        //error checking
        if( errM )
        {
            //TODO: need an alert sheet here
            NSLog(@"Error registering mouse handler...%d", err);
        }
    }
    

    这是我正在使用的回调方法的示例:

    OSStatus globalKeyPress(EventHandlerCallRef nextHandler, EventRef theEvent, void *userData) 
    {
        NSEvent *anEvent = [NSEvent eventWithEventRef:theEvent];
        NSEventType type = [anEvent type];
        WarStrokerApplication *application = (WarStrokerApplication*)userData;
    
        //is it a key up event?
        if( type == NSKeyUp)
        {
            //which key is it?
            switch( [anEvent keyCode] )
            {
                case NUMERIC_KEYPAD_PLUS: 
                    //this is the character we are using for our toggle
                    //call the handler function
                    [application toggleKeyPressed];
                    break;
    
                    //Comment this line back in to figure out the keykode for a particular character                
                default:
                    NSLog(@"Keypressed: %d, **%@**", [anEvent keyCode], [anEvent characters]);
                    break;
            }
        }
    
        return CallNextEventHandler(nextHandler, theEvent);
    }
    

    【讨论】:

      【解决方案2】:

      后半部分,发布事件,使用ApplicationServices/ApplicationServices.h中提供的CGEvent方法

      这是一个将鼠标移动到指定绝对位置的示例函数:

      #include <ApplicationServices/ApplicationServices.h>
      
      int to(int x, int y)
      {
          CGPoint newloc;
          CGEventRef eventRef;
          newloc.x = x;
          newloc.y = y;
      
          eventRef = CGEventCreateMouseEvent(NULL, kCGEventMouseMoved, newloc,
                                              kCGMouseButtonCenter);
          //Apparently, a bug in xcode requires this next line
          CGEventSetType(eventRef, kCGEventMouseMoved);
          CGEventPost(kCGSessionEventTap, eventRef);
          CFRelease(eventRef);
      
          return 0;
      }
      

      【讨论】:

        【解决方案3】:

        点击鼠标事件见Link

        我没有在 10.5 Leopard 下检查过这个,但在 10.4 上它可以工作。

        【讨论】:

        • 也适用于键盘事件,但 (IIRC) 用户必须在系统偏好设置中启用对辅助设备的访问权限。
        • 附录:我之前的评论仅指键盘事件点击。鼠标事件点击始终可用(再次,IIRC)。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-12
        • 2011-12-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多