2015-10-07 135 views
0

我正在Xcode 7中编写Swift 2中的程序(对于OS X 10.11),我希望它(这是ViewController类)能够检测用户何时按下一个函数关键,特别是当应用程序在后台。我推翻acceptsFirstResponderSwift 2:检测功能按键

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:”打印到控制台。在附注中,如果有人知道更好的方法来检测功能键,请这么说。

为什么不检测按键?

+0

你为什么要在'keyDown'方法中调用'keyUp'方法? – Droppy

+0

从代码仍然在'keyUp'方法中的错字 – Arc676

+0

嗯......所以你发布的代码实际上并不是你正在运行的东西? – Droppy

回答

0

撰稿@Serneum(SWIFT雨燕或2)here

在Objective-C也可以通过@Joshua Nozzi here

注意,按F8时iTunes仍会启动,即使您的应用程序使用媒体密钥。如果您想禁用iTunes启动,请阅读this(使用第三方应用)或this(使用终端)(相同问题,不同答案)。


您可以通过继承NSApplication(是AppKit框架对于那些不知道)和压倒一切的sendEvent:NSEvent捕捉媒体键。

斯威夫特码(从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_DOWNNX_KEYTYPE_BRIGHTNESS_UPNX_KEYTYPE_CAPS_LOCKNX_KEYTYPE_EJECTNX_KEYTYPE_ILLUMINATION_UPNX_KEYTYPE_ILLUMINATION_DOWNNX_KEYTYPE_LAUNCH_PANELNX_KEYTYPE_MUTENX_KEYTYPE_SOUND_DOWNNX_KEYTYPE_SOUND_UP,还有一些其他的不在我的键盘上,所以我无法确认它们。

+0

处理iTunes启动事件。 https://github.com/nevyn/SPMediaKeyTap – AJit

1

它看起来像你试图捕获媒体键(播放/暂停,转发,返回)。这些实际上不是功能键,它们是“硬件”键。 (如果你按住fn,那么它们就是功能键,如果进入系统首选项>键盘窗格>键盘选项卡并启用“使用所有F1,F2等键作为标准功能键”,则它们是功能键和按住FN他们切换到硬件键。)

有回答有关捕获那些媒体键,如herehere别处。他们都推荐使用SPMediaKeyTap代码。

如果你在功能键真的有兴趣,你需要一些事项:

  • 应用程序通常不接收键盘事件时,他们的背景。键盘事件只能进入活动的应用程序。
  • 您可以使用全局事件监视器或Quartz事件点击来监视来自后台的关键事件,但前提是您的应用程序已获得用户批准以访问辅助设备。这是为了防止键盘记录器和其他恶意软件。
  • 您可以使用RegisterEventHotKey()来实现更有限的方式来响应来自后台的关键事件而无需辅助访问。它是一个Carbon API,但不被弃用,因为它仍然是实现热键功能的正确方法。对于媒体键等硬件键仍然没有帮助。
+0

感谢您的帮助,但关于他们被称为** _媒体键_ **的事情真的触到了它的指甲。我发现[this](http://stackoverflow.com/questions/32499676/capture-osx-media-control-buttons-in-swift)这篇文章也提到了在不使用第三方代码的情况下在Swift中捕获媒体密钥。 – Arc676