如何检测到已按下Shift键?

时间:2012-02-13 21:08:23

标签: macos cocoa

我有一个NSView子类,我希望当用户按下⇧Shift键时它会做出反应。但是,仅按下修改键时,不会调用-[NSView keyDown:](我当前覆盖)。

如何在按下Shift键时收到通知?

7 个答案:

答案 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)

在苹果的文档中:

您必须override the keydown method

使用以下NSEvent modifier flags