使用 CoreGraphics 方法发送自动重复键 (Mac OS X Snow Leopard)

发布于 2024-11-02 04:28:32 字数 948 浏览 1 评论 0原文

我已经成功地发送击键,以便自动化我使用的用于绘图的特定软件包。该软件依赖于很多键盘快捷键,因此我编写了一些可以调用其中一些键盘快捷键的东西,以简化我的工作流程。正如我所说,这已经取得了很好的效果。

我的库是一个 Cocoa 库,它作为插件加载到软件包中。这是我用来发送击键的代码片段。

CGEventSourceRef eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
CGEventRef eventDown = CGEventCreateKeyboardEvent(eventSource, (CGKeyCode)1, true);
CGEventRef eventUp = CGEventCreateKeyboardEvent(eventSource, (CGKeyCode)1, false);

//setting the process number somewhere else
CGEventPostToPSN(&number, eventDown);
CGEventPostToPSN(&number, eventUp);

对于绘图包中的某些程序,如果继续按住 Shift 键,则会激活特殊工具。我一直无法模拟这个。我以为我可以发送 Shift 键并说我希望它自动重复,但这似乎不起作用。我一直在使用以下代码来设置自动重复:

//This is done before sending the key
CGEventSetIntegerValueField(eventDown, kCGKeyboardEventAutorepeat, 1);

在我的测试中,我无法使任何键自动重复。它只需发送一次密钥即可。

有人使用上述方法成功地自动重复按键吗?我在互联网上搜索了答案,但我发现的只是 2008 年一些未解答的问题......非常感谢任何帮助。

谢谢,

莫贝

I have been successful sending keystrokes in order to automate a particular software package for drawing that I use. This software relies a lot of keyboard shortcuts so I wrote something that could call some of these keyboard shortcuts in order to streamline my workflow. As I said, this has worked out good.

My library is a Cocoa library that is loaded as a plugin to the software package. Here is a snippet of code that I have been using for sending my keystrokes.

CGEventSourceRef eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
CGEventRef eventDown = CGEventCreateKeyboardEvent(eventSource, (CGKeyCode)1, true);
CGEventRef eventUp = CGEventCreateKeyboardEvent(eventSource, (CGKeyCode)1, false);

//setting the process number somewhere else
CGEventPostToPSN(&number, eventDown);
CGEventPostToPSN(&number, eventUp);

For some procedures in the drawing package if you continue to hold the Shift key then you activate a special tool. I have been unable to simulate this. I thought I could send the Shift key and say that I wanted it to auto-repeat but that doesn't seem to work. I have been using the following code to set the auto-repeat:

//This is done before sending the key
CGEventSetIntegerValueField(eventDown, kCGKeyboardEventAutorepeat, 1);

In my testing I have been unable to make any key auto-repeat. It just send the key once and that is it.

Is there anyone that have been successful autorepeating a key using the above method? I have searched the Internet for answers but all I have found are some unanswered questions from 2008... Any help is greatly appreciated.

Thanks,

mobbe

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

绅刃 2024-11-09 04:28:32

OP最终想出的解决问题的代码(从其他答案下的评论转移到这里):

CGEventRef flagsChanged = CGEventCreate(eventSource); 
CGEventSetType(flagsChanged, kCGEventFlagsChanged); 
CGEventSetIntegerValueField(flagsChanged, kCGKeyboardEventKeycode, 56);     
CGEventSetFlags(flagsChanged, 131330); 
CGEventPostToPSN(&number, flagsChanged); 
CFRelease(flagsChanged); CFRelease(eventSource);

131330是一个常量,表示Shift键;它与 NSShiftKeyMaskkCGEventFlagMaskShift 相关,即 131072 (0x00020000)。 131330 - 256 - 2 == 131072

The code that OP finally came up with to solve the problem (transferred here from a comment under other answer):

CGEventRef flagsChanged = CGEventCreate(eventSource); 
CGEventSetType(flagsChanged, kCGEventFlagsChanged); 
CGEventSetIntegerValueField(flagsChanged, kCGKeyboardEventKeycode, 56);     
CGEventSetFlags(flagsChanged, 131330); 
CGEventPostToPSN(&number, flagsChanged); 
CFRelease(flagsChanged); CFRelease(eventSource);

131330 is a constant indicating the Shift key; it is related to NSShiftKeyMask and kCGEventFlagMaskShift, which are 131072 (0x00020000). 131330 - 256 - 2 == 131072.

余厌 2024-11-09 04:28:32

更新:根据 Events.h,Shift 键的代码不是 56:(

...
kVK_Shift                     = 0x38,
...

编辑:当然,那些关注的人(我没有)意识到 HEX 38 == DEC 56 .)

我还意识到如何获得修饰键按下:flagsChanged:。因此,使用这个键码,我可以在 flagsChanged: 中捕捉 Shift 键按下的情况,并且重复工作正常;我还可以毫无困难地在 keyDown:keyUp: 中获得“普通”键的重复按键事件。

听起来您可能无权访问/想要更改事件处理代码(添加 flagsChanged:),所以如果该键代码不适合您,我会很困惑并且可以只说“祝你好运!”


我相信您设置的字段用于指示系统不应重复该事件,而是指示该事件是先前事件的自动重复事件。您仍然需要自己生成每个事件。像(编辑使用计时器而不是循环):

CGEventSourceRef eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
CGEventRef eventDown = CGEventCreateKeyboardEvent(eventSource, (CGKeyCode)1, true);
// Post the initial keydown
CGEventPostToPSN(&pidNumber, eventDown);

// Keep track of how many Shift keydown events have been sent
shiftKeyRepeatCount = 1;
[NSTimer scheduledTimerWithTimeInterval:0.3    // I don't know exactly what the interval should be, of course
                                 target:self
                               selector:@selector(repeatShiftKeyDown:)
                               userInfo:nil
                                repeats:YES];

CFRelease(eventDown);

- (void)repeatShiftKeyDown:(NSTimer *)tim {
    if( shiftKeyRepeatCount >= kRepeatCountForSpecialTool ){
        [tim invalidate];
        [self sendShiftKeyUp];
        return;
    }
    shiftKeyRepeatCount++;
    GEventSourceRef eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
    CGEventRef eventDown = CGEventCreateKeyboardEvent(eventSource, (CGKeyCode)1, true);
    // Set the auto-repeat field
    CGEventSetIntegerValueField(eventDown, kCGKeyboardEventAutorepeat, 1);
    CGEventPostToPSN(&pidNumber, eventDown);
    CFRelease(eventDown);
}

我不确定您是否可以使用更改的字段重用第一个事件,或者您需要生成一个新事件以在重复时使用。

UPDATE: the Shift key's code isn't 56, according to Events.h:

...
kVK_Shift                     = 0x38,
...

(EDIT: of course those of you who are paying attention (I wasn't) realize that HEX 38 == DEC 56.)

I also realized how to get modifier key presses: flagsChanged:. So using this keycode, I can catch Shift key presses in flagsChanged:, and the repeat works fine; I also get repeated key events for "normal" keys in keyDown: and keyUp: without difficulty.

It sounds like you may not have access to/want to change the event-handling code (to add flagsChanged:) though, so if that keycode doesn't work for you, I'm stumped and can only say "Good luck!"


I believe that the field you're setting is used to indicate not that the event should be repeated by the system, but that an event is an auto-repeat of a previous event. You still have to generate each event yourself. Something like (EDITED to use a timer instead of a loop):

CGEventSourceRef eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
CGEventRef eventDown = CGEventCreateKeyboardEvent(eventSource, (CGKeyCode)1, true);
// Post the initial keydown
CGEventPostToPSN(&pidNumber, eventDown);

// Keep track of how many Shift keydown events have been sent
shiftKeyRepeatCount = 1;
[NSTimer scheduledTimerWithTimeInterval:0.3    // I don't know exactly what the interval should be, of course
                                 target:self
                               selector:@selector(repeatShiftKeyDown:)
                               userInfo:nil
                                repeats:YES];

CFRelease(eventDown);

- (void)repeatShiftKeyDown:(NSTimer *)tim {
    if( shiftKeyRepeatCount >= kRepeatCountForSpecialTool ){
        [tim invalidate];
        [self sendShiftKeyUp];
        return;
    }
    shiftKeyRepeatCount++;
    GEventSourceRef eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
    CGEventRef eventDown = CGEventCreateKeyboardEvent(eventSource, (CGKeyCode)1, true);
    // Set the auto-repeat field
    CGEventSetIntegerValueField(eventDown, kCGKeyboardEventAutorepeat, 1);
    CGEventPostToPSN(&pidNumber, eventDown);
    CFRelease(eventDown);
}

I'm not certain whether you can reuse the first event with a changed field or you'll need to generate a new event to use when repeating.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文