我有一个NSView
子类,我希望当用户按下⇧Shift键时它会做出反应。但是,仅按下修改键时,不会调用-[NSView keyDown:]
(我当前覆盖)。
如何在按下Shift键时收到通知?
答案 0 :(得分:34)
来自Cocoa事件处理指南:
flagsChanged:方法可用于检测按下修改键而无需同时按下任何其他键。例如,如果用户单独按下Option键,则响应者对象可以在flagsChanged的实现中检测到:。
可以找到更多详细信息here。
NSResponder 的文档还说明了以下内容:
flagsChanged:
通知接收者用户已按下或释放修改键(Shift,Control等)。
- (void)flagsChanged:(NSEvent *)theEvent
答案 1 :(得分:14)
这是一个例子,稍微修改了Matt Gemmell的ModKeyTest示例应用程序。 使用一个按钮创建一个基本的Cocoa应用程序,并将按钮连接到这样的IBAction。 然后尝试所需的键组合。 文档有点模糊,但Matt的例子很清楚,并提供了从文档中进一步利用这一点所需的一切。
- (IBAction)myAction:(id)sender {
NSUInteger flags = [[NSApp currentEvent] modifierFlags];
if ((flags & NSCommandKeyMask) && (flags & NSAlternateKeyMask) && (flags & NSControlKeyMask)) {
NSBeginInformationalAlertSheet(@"Modifier keys Command Option Control detected", nil, nil, nil, [NSApp mainWindow], self, nil, nil, nil,
@"You sneaky thing!");
}
if ((flags & NSCommandKeyMask) && (flags & NSShiftKeyMask)) {
NSBeginInformationalAlertSheet(@"Modifier keys Command Shift detected", nil, nil, nil, [NSApp mainWindow], self, nil, nil, nil,
@"You sneaky thing!");
}
if ((flags & NSAlphaShiftKeyMask)) {
NSBeginInformationalAlertSheet(@"Modifier keys Caps Lock detected", nil, nil, nil, [NSApp mainWindow], self, nil, nil, nil,
@"You sneaky thing!");
}
if ((flags & NSFunctionKeyMask)) {
NSBeginInformationalAlertSheet(@"Modifier keys fn detected", nil, nil, nil, [NSApp mainWindow], self, nil, nil, nil,
@"You sneaky thing!");
}
答案 2 :(得分:8)
这是代码处理关键事件,在Xcode 8.2.1和macOS 10.12.2上测试了swift 3.0.1
override func keyDown(with event: NSEvent) {
var handled = false
if event.keyCode == 53 { // ESC, same as `CMD + .`
handled = true
print("ESC")
}
if event.modifierFlags.contains(.command) { // .shift, .option, .control ...
if let chars = event.charactersIgnoringModifiers {
handled = true // likely we are interested with that key
switch chars {
case "r":
print("CMD + r")
case ",":
print("CMD + ,")
case "/":
print("CMD + /")
default:
handled = false
}
}
}
if !handled {
super.keyDown(with: event) // let system handle it(may contains sound)
}
}
答案 3 :(得分:0)
如果按键事件不是一个事件,您该怎么办?例如,您想在程序启动时测试Shift键的状态吗?在程序启动之前按下Shift键,直到测试其状态后才能释放。
在Windows中,您可以通过致电GetKeyState(VK_SHIFT)
轻松获得此信息。什么是macOS等价物?
答案 4 :(得分:0)
您要查看,如果用户按下特殊键,则无论是否同时按下任何普通键。在Swift 5中,您可以在AppDelegate中使用替代功能。
新的Swift项目中的占位符应如下所示:
override func flagsChanged (with theEvent: NSEvent)
{
// ...
}
现在,您可以使用以下代码填充此空函数:
override func flagsChanged (with theEvent: NSEvent)
{
let mods: Int = (Int(theEvent.modifierFlags.rawValue)) >> 16
let t_KeyCapsLockPressed = (bitand(mods, 1) != 0)
let t_KeyShiftPressed = (bitand(mods, 2) != 0)
let t_KeyControlPressed = (bitand(mods, 4) != 0)
let t_KeyOptionPressed = (bitand(mods, 8) != 0)
let t_KeyCommandPressed = (bitand(mods, 16) != 0)
// let t_KeyNumericPadPressed = (bitand(mods, 32) != 0) // Not used here
// let t_KeyHelpPressed = (bitand(mods, 64) != 0) // Not used here
let t_KeyFnPressed = (bitand(mods, 128) != 0)
print("flagsChanged: t_KeyShiftPressed = \(Int(t_KeyShiftPressed))")
print("flagsChanged: t_KeyControlPressed = \(Int(t_KeyControlPressed))")
print("flagsChanged: t_KeyOptionPressed = \(Int(t_KeyOptionPressed))")
print("flagsChanged: t_KeyCommandPressed = \(Int(t_KeyCommandPressed))")
// and so on...
}
每次按下或释放特殊键时都会调用该func。这样您就可以做任何您想做的事。如果将变量声明为全局变量,则可以从任何地方实时访问它们:
// In the header of your program:
var t_KeyCapsLockPressed: Bool = false
var t_KeyShiftPressed: Bool = false
var t_KeyControlPressed: Bool = false
var t_KeyOptionPressed: Bool = false
var t_KeyCommandPressed: Bool = false
var t_KeyFnPressed: Bool = false
var t_KeyFlagsHaveChanged: Bool = false
// In the AppDelegate:
override func flagsChanged (with theEvent: NSEvent)
{
let mods: Int = (Int(theEvent.modifierFlags.rawValue)) >> 16
t_KeyCapsLockPressed = (bitand(mods, 1) != 0)
t_KeyShiftPressed = (bitand(mods, 2) != 0)
t_KeyControlPressed = (bitand(mods, 4) != 0)
t_KeyOptionPressed = (bitand(mods, 8) != 0)
t_KeyCommandPressed = (bitand(mods, 16) != 0)
t_KeyFnPressed = (bitand(mods, 128) != 0)
t_KeyFlagsHaveChanged = true
}
// In your Main program:
func keyCheck ()
{
if t_KeyFlagsHaveChanged
{
print("flagsChanged: t_KeyShiftPressed = \(Int(t_KeyShiftPressed))")
print("flagsChanged: t_KeyControlPressed = \(Int(t_KeyControlPressed))")
print("flagsChanged: t_KeyOptionPressed = \(Int(t_KeyOptionPressed))")
print("flagsChanged: t_KeyCommandPressed = \(Int(t_KeyCommandPressed))")
// and so on...
t_KeyFlagsHaveChanged = false
}
}
答案 5 :(得分:-2)
检查按下:
-(void)keyDown:(NSEvent *)theEvent
{
if ([theEvent modifierFlags] & NSShiftKeyMask)
{
NSLog("Shift key was pressed");
}
}
检查发布:
-(void)keyUp:(NSEvent *)theEvent
{
if(!([theEvent modifierFlags] & NSShiftKeyMask))
{
NSLog("Shift key was released");
}
}
应该注意,只有在按下SHIFT然后按下其他键时才会调用NSLog函数。
希望这有帮助!
答案 6 :(得分:-3)