macos 如何在 Mac OS X 下捕获/发布系统范围的键盘/鼠标事件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/399616/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 05:59:50  来源:igfitidea点击:

How to Capture / Post system-wide Keyboard / Mouse events under Mac OS X?

cocoamacos

提问by Andrew Grant

For a scripting utility I need to be able to record a series of keyboard and mouse events that occur when an application has focus. The second part is being able to later send those events to the active window.

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

I do not need to worry about menus or tracking the identifier of which window receives input.

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

I know how to do this under Windows but have no idea about Mac OS X.

我知道如何在 Windows 下执行此操作,但对 Mac OS X 一无所知。

回答by Lounges

The first thing i will tell you is that you CAN'Tdo this without the user enabling support for assitive devices in the accessability control panel. It's some kind of security built into OSX.

的第一件事,我会告诉你的是,你CAN NOT未经用户允许在前往的交通控制面板assitive设备的支持,做到这一点。这是 OSX 中内置的某种安全性。

Here is a code snippit I am using in one of my applications to do this:

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

//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);
    }
}

Here is an example of the callback method i am using:

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

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);
}

回答by Ben

For the latter part, posting events, use the CGEvent methods provided in ApplicationServices/ApplicationServices.h

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

Here's an example function to move the mouse to a specified absolute location:

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

#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;
}

回答by diciu

For tapping mouse events, see http://osxbook.com/book/bonus/chapter2/altermouse/

对于点击鼠标事件,请参阅http://osxbook.com/book/bonus/chapter2/altermouse/

I haven't checked this under 10.5 Leopard but on 10.4 it works.

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