【问题标题】:Swift 2: Detect Function Key PressesSwift 2:检测功能键按下
【发布时间】:2016-01-04 16:31:42
【问题描述】:

我正在 Xcode 7(用于 OS X 10.11)中使用 Swift 2 编写程序,我希望它(这是 ViewController 类)能够检测用户何时按下功能键,尤其是当应用程序处于在后台。我覆盖了acceptsFirstResponder:

override var acceptsFirstResponder: Bool { return true }

我已经实现了keyUp: 和keyDown::

override func keyDown(theEvent: NSEvent) {
    print("keyDown:\n")
    let ch: NSString = theEvent.charactersIgnoringModifiers!
    if ch.length == 1 {
        let char: Int = Int(ch.characterAtIndex(0))
        if char == NSF7FunctionKey {
            prevSong(NSNull())
        }else if char == NSF8FunctionKey {
            playPause(NSNull())
        }else if char == NSF9FunctionKey {
            nextSong(NSNull())
        }else{
            self.nextResponder?.keyDown(theEvent)
        }
    }else{
        self.nextResponder?.keyDown(theEvent)
    }
}

override func keyUp(theEvent: NSEvent) {
    print("keyUp:\n")
    self.nextResponder?.keyUp(theEvent)
}

我原本拥有 keyUp: 中的所有代码,但我从未将“keyDown:”打印到控制台。另外,如果有人知道检测功能键的更好方法,请说出来。

为什么检测不到按键?

【问题讨论】:

  • 你为什么要从你的 keyDown 方法中调用 keyUp 方法?
  • 代码仍在 keyUp 方法中时的错字
  • 嗯....所以您发布的代码实际上并不是您正在运行的代码?
  • 两者结果相同:按 F7 或 F9 时无效;按 F8 会调出 iTunes。

标签: macos swift2


【解决方案1】:

您似乎正在尝试捕获媒体键(播放/暂停、前进、后退)。这些实际上不是功能键,它们是“硬件”键。 (如果您按住 fn,则它们是功能键。如果您进入系统偏好设置 > 键盘窗格 > 键盘选项卡并启用“使用所有 F1、F2 等键作为标准功能键”,那么它们是功能键,按住 fn 会将它们切换为硬件键。)

其他地方有关于捕获这些媒体密钥的答案,例如here 和here。他们都推荐使用SPMediaKeyTap 代码。

如果您真的对功能键感兴趣,您需要了解一些事项:

  • 应用程序在后台时通常不会接收键盘事件。键盘事件只会发送到活动应用。
  • 您可以使用全局事件监控器或 Quartz 事件点击从后台监控关键事件,但前提是您的应用已被用户批准访问辅助设备。这是为了防止键盘记录程序和其他恶意软件。
  • 您可以使用RegisterEventHotKey() 来实现一种更有限的方式,在没有辅助访问的情况下从后台响应关键事件。它是一个 Carbon API,但并未被弃用,因为它仍然是实现热键功能的正确方法。对于媒体键等硬件键仍然没有帮助。

【讨论】:

  • 感谢您的帮助,但是关于它们被称为 媒体键 的事情确实一针见血。我发现this 的帖子还谈到了在不使用 3rd 方代码的情况下在 Swift 中捕获媒体密钥。
【解决方案2】:

作者:@Serneum(Swift 或 Swift 2)here

@Joshua Nozzi here 也可以在 Objective-C 中使用

请注意,即使您的应用程序使用媒体键,当按下 F8 时,iTunes 仍会启动。如果您想禁用 iTunes 启动,请阅读 this 帖子(使用 3rd 方应用程序)或 this 帖子(使用终端)(相同的问题,不同的答案)。


您可以通过继承 NSApplication(在 AppKit 框架中为那些不知道的人)和覆盖 sendEvent:NSEvent 来捕获媒体密钥。

Swift 代码(取自 Serneum 的回答):

import Cocoa

class Application: NSApplication {
    override func sendEvent(theEvent: NSEvent) {
        if theEvent.type == .SystemDefined && theEvent.subtype.rawValue == 8 {
            let keyCode = ((theEvent.data1 & 0xFFFF0000) >> 16)
            let keyFlags = (theEvent.data1 & 0x0000FFFF)
            // Get the key state. 0xA is KeyDown, OxB is KeyUp
            let keyState = (((keyFlags & 0xFF00) >> 8)) == 0xA
            let keyRepeat = (keyFlags & 0x1)
            mediaKeyEvent(Int32(keyCode), state: keyState, keyRepeat: Bool(keyRepeat))
        }
        super.sendEvent(theEvent)
        //note that without the above line the app doesn't respond to clicks or any keyboard events
    }

    func mediaKeyEvent(key: Int32, state: Bool, keyRepeat: Bool) {
        // Only send events on KeyDown. Without this check, these events will happen twice
        if (state) {
            switch(key) {
            case NX_KEYTYPE_PLAY:
                //F8 pressed
                break
            case NX_KEYTYPE_FAST:
                //F9 pressed
                break
            case NX_KEYTYPE_REWIND:
                //F7 pressed
                break
            default:
                break
            }
        }
    }
}

其他“硬件密钥”包括NX_KEYTYPE_BRIGHTNESS_DOWN、NX_KEYTYPE_BRIGHTNESS_UP、NX_KEYTYPE_CAPS_LOCK、NX_KEYTYPE_EJECT、NX_KEYTYPE_ILLUMINATION_UP、NX_KEYTYPE_ILLUMINATION_DOWN、NX_KEYTYPE_LAUNCH_PANEL、NX_KEYTYPE_MUTE、NX_KEYTYPE_SOUND_DOWN、@987654其他一些不在我的键盘上,所以我无法确认。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-23
    • 2018-10-24
    • 1970-01-01
    相关资源
    最近更新 更多