使用Swift模拟按键

ixa*_*any 10 cocoa keystroke keypress swift

我正在寻找一种模拟OSX中击键的方法.我使用Objective-C 找到了另一个解决方案(模拟系统范围热键的按键),但我需要使用Swift.我怎样才能适应CGEventCreateKeyboardEvent?

Nis*_*sba 12

使用Swift 3

let src = CGEventSource(stateID: CGEventSourceStateID.hidSystemState)

let cmdd = CGEvent(keyboardEventSource: src, virtualKey: 0x38, keyDown: true)
let cmdu = CGEvent(keyboardEventSource: src, virtualKey: 0x38, keyDown: false)
let spcd = CGEvent(keyboardEventSource: src, virtualKey: 0x31, keyDown: true)
let spcu = CGEvent(keyboardEventSource: src, virtualKey: 0x31, keyDown: false)

spcd?.flags = CGEventFlags.maskCommand;

let loc = CGEventTapLocation.cghidEventTap

cmdd?.post(tap: loc)
spcd?.post(tap: loc)
spcu?.post(tap: loc)
cmdu?.post(tap: loc)
Run Code Online (Sandbox Code Playgroud)

  • 就我而言(Swift 5),我必须使用:`let src = CGEventSource(stateID: .privateState)` (2认同)

Air*_*ity 9

该链接答案的代码很容易转换为Swift代码,但是在此过程中需要注意的一些问题:

CGEventSourceCreate取a CGEventSourceStateID,这是a的typealiase UInt32,但是常量如kCGEventSourceStateHIDSystemState定义为Int,所以你必须抛出它们,即CGEventSourceStateID(kCGEventSourceStateHIDSystemState).同样地CGEventFlags.

CGEventSourceCreateCGEventCreateKeyboardEvent返回Unmanaged<CGEventSource>(或Unmanaged<CGEvent>).自动生成的用于Core Graphics的Swift API不知道您是否需要释放返回的对象,因此您需要检查这些调用的API文档,然后使用takeRetainedValue()takeUnretainedValue()相应地返回值,将它们转换为您想要使用的基础类型.

最后,它们会隐式返回未包装的选项,因此您需要决定是否要检查nils,或者只是在运行时爆发时会感到兴奋.

鉴于所有这一切都很简单,在那个答案中将Objective-C转换为将Cmd-Space压缩为Swift,我只是尝试将其粘贴到临时应用程序中并且工作正常:

(虽然我没有检查API文档是否保留是正确的做法)

let src = CGEventSourceCreate(CGEventSourceStateID(kCGEventSourceStateHIDSystemState)).takeRetainedValue()

let cmdd = CGEventCreateKeyboardEvent(src, 0x38, true).takeRetainedValue()
let cmdu = CGEventCreateKeyboardEvent(src, 0x38, false).takeRetainedValue()
let spcd = CGEventCreateKeyboardEvent(src, 0x31, true).takeRetainedValue()
let spcu = CGEventCreateKeyboardEvent(src, 0x31, false).takeRetainedValue()

CGEventSetFlags(spcd, CGEventFlags(kCGEventFlagMaskCommand));
CGEventSetFlags(spcd, CGEventFlags(kCGEventFlagMaskCommand));

let loc = CGEventTapLocation(kCGHIDEventTap)

CGEventPost(loc, cmdd)
CGEventPost(loc, spcd)
CGEventPost(loc, spcu)
CGEventPost(loc, cmdu)
Run Code Online (Sandbox Code Playgroud)


bal*_*630 6

斯威夫特 3

对我来说,十六进制键值如: 0x124 不起作用,但简单的 UInt 124 成功了!

可以在这里找到一组不错的键码!此复制粘贴代码片段模拟向右箭头按键。更改您想要模拟的任何键号:

    // Simulate Right Arrow keypress
    let rightArrowKeyCode: UInt16 = 124

    let keyDownEvent = CGEvent(keyboardEventSource: nil, virtualKey: rightArrowKeyCode, keyDown: true)
    keyDownEvent?.flags = CGEventFlags.maskCommand
    keyDownEvent?.post(tap: CGEventTapLocation.cghidEventTap)

    let keyUpEvent = CGEvent(keyboardEventSource: nil, virtualKey: rightArrowKeyCode, keyDown: false)
    keyUpEvent?.flags = CGEventFlags.maskCommand
    keyUpEvent?.post(tap: CGEventTapLocation.cghidEventTap)
Run Code Online (Sandbox Code Playgroud)

更新: 对于 macOS Mojave 及更高版本,您应该允许您的应用在系统偏好设置 > 安全和隐私 > 辅助功能中控制您的计算机

  • 令人惊奇的是,我们如何与发布此类信息的其他开发人员建立联系。苹果公司应该解雇撒旦,让其不再管理文档部门,并雇用一些有能力的人。他们的文档很糟糕。 (2认同)

oco*_*odo 5

我为 Swift 4 项目制作了这个,不要忘记应用沙盒不允许应用发送这样的按键,所以需要关闭它。这意味着您的应用程序将被 AppStore 禁止。

import Foundation

class FakeKey {
    static func send(_ keyCode: CGKeyCode, useCommandFlag: Bool) {
        let sourceRef = CGEventSource(stateID: .combinedSessionState)

        if sourceRef == nil {
            NSLog("FakeKey: No event source")
            return
        }

        let keyDownEvent = CGEvent(keyboardEventSource: sourceRef,
                                   virtualKey: keyCode,
                                   keyDown: true)
        if useCommandFlag {
            keyDownEvent?.flags = .maskCommand
        }

        let keyUpEvent = CGEvent(keyboardEventSource: sourceRef,
                                 virtualKey: keyCode,
                                 keyDown: false)

        keyDownEvent?.post(tap: .cghidEventTap)
        keyUpEvent?.post(tap: .cghidEventTap)
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 该问题似乎与“可访问性”API 有关。您需要授予它权限才能使用它。在我的情况下,它“悄悄地”失败了 b/c 我拒绝了一次权限提示。 (7认同)