我在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:"打印到控制台。另外,如果有人知道检测功能键的更好方法,请说出来。
为什么不检测按键?
答案 0 :(得分:1)
看起来您正在尝试捕获媒体键(播放/暂停,前进,后退)。这些实际上不是功能键,它们是"硬件"键。 (如果您按住 fn ,则它们是功能键。如果您进入系统偏好设置>键盘窗格>键盘选项卡并启用"使用所有F1,F2等键作为标准功能键",然后它们是功能键并按住 fn 将它们切换到硬件键。)
其他地方有关于捕获这些媒体密钥的答案,例如here和here。他们都建议使用SPMediaKeyTap代码。
如果你真的对功能键感兴趣,你需要知道一些事情:
RegisterEventHotKey()
来实现更有限的方式从后台响应关键事件而无需辅助访问。它是Carbon API但不被弃用,因为它仍然是实现热键功能的正确方法。对媒体密钥等硬件密钥仍然没有帮助。答案 1 :(得分:0)
由@Serneum撰写(Swift或Swift 2)here
@Joshua Nozzi here
也可在Objective-C中找到请注意,按F8时,即使应用程序使用媒体键,iTunes仍会启动。如果您要禁用iTunes启动,请阅读this帖子(使用第三方应用)或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
,NX_KEYTYPE_SOUND_UP
以及键盘上没有的其他内容,因此我无法确认。