使用Swift模拟按键

时间:2014-12-15 12:40:02

标签: cocoa swift keypress keystroke

我正在寻找一种在OSX中模拟击键的方法。我找到了另一个使用Objective-C的解决方案(Simulate keypress for system wide hotkeys),但我需要使用Swift。我如何调整CGEventCreateKeyboardEvent?

5 个答案:

答案 0 :(得分:11)

使用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)

答案 1 :(得分:9)

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

CGEventSourceCreate需要CGEventSourceStateID,这是UInt32的类型值,但kCGEventSourceStateHIDSystemState等常量定义为Int,所以你'我必须施放它们,即CGEventSourceStateID(kCGEventSourceStateHIDSystemState)。与CGEventFlags一样。

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

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

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

(虽然我没有检查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)

答案 2 :(得分:2)

我为Swift 4项目做了这个,不要忘记App沙盒不允许应用程序发送这样的击键,因此需要关闭它。这意味着您的应用程序将被禁止进入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)
    }
}

答案 3 :(得分:1)

Swift 3

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

一组很好的密钥代码可以是found here! 此复制粘贴代码段模拟右箭头按键。更改您想要模拟的任何键号:

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

<强>更新 它在macOS Mojave下无效。

答案 4 :(得分:0)

刺激快捷键/热键的答案组合。 Swift 5.1

let source = CGEventSource(stateID: CGEventSourceStateID.hidSystemState)

let cmdKey: UInt16 = 0x38
let numberThreeKey: UInt16 = 0x14

let cmdDown = CGEvent(keyboardEventSource: source, virtualKey: cmdKey, keyDown: true)
let cmdUp = CGEvent(keyboardEventSource: source, virtualKey: cmdKey, keyDown: false)
let keyThreeDown = CGEvent(keyboardEventSource: source, virtualKey: numberThreeKey, keyDown: true)
let keyThreeUp = CGEvent(keyboardEventSource: source, virtualKey: numberThreeKey, keyDown: false)


fileprivate func testShortcut() {

let loc = CGEventTapLocation.cghidEventTap

cmdDown?.flags = CGEventFlags.maskCommand
cmdUp?.flags = CGEventFlags.maskCommand
keyThreeDown?.flags = CGEventFlags.maskCommand
keyThreeUp?.flags = CGEVentFlags.maskCommand

cmdDown?.post(tap: loc)
keyThreeDown?.post(tap: loc)
cmdUp?.post(tap: loc)
keyThreeUp?.post(tap: loc)

}

手动书写可能包含错误。