Cocoa不会捕获Shift Shift修饰符?

时间:2009-01-01 10:31:23

标签: cocoa macos

我有一个应用程序,其中我正在尝试捕获shift键修改器以执行操作,但是当我运行程序并按下而没有Shift键修改器的普通键时,我会发出一声嘟嘟声,修改器和键是没有发送到我的keyDown事件。相关代码是:

NSString* eventChars = [theEvent charactersIgnoringModifiers];

if ([eventChars isEqualTo:@"w"]) {
    newPlayerRow++;
    direction = eUp;
} else if ([eventChars isEqualTo:@"x"]) {
    newPlayerRow--;
    direction = eDown;
} else if ([eventChars isEqualTo:@"a"]) {
    newPlayerCol--;
    direction = eLeft;
} else if ([eventChars isEqualTo:@"d"]) {
    newPlayerCol++;
    direction = eRight;
} else {
    [super keyDown:theEvent];
    return;
}

// handle the player firing a bullet
if (([theEvent modifierFlags] & (NSShiftKeyMask | NSAlphaShiftKeyMask)) != 0) {
    NSLog(@"Shift key");
    [self fireBulletAtColumn:newPlayerCol row:newPlayerRow inDirection:direction];
    [self setNeedsDisplay:YES];
} else {
    ...
}

我不确定是什么导致了这种情况,但我希望能够捕获按键切换按键。提前感谢您对此问题的任何帮助。

编辑:如果这有任何不同,我也在使用MacBook键盘。

编辑:这绝对是一个以移位为中心的问题,因为将NSShiftKeyMask | NSAlphaShiftKeyMask更改为NSControlKeyMask确实会产生预期效果。

5 个答案:

答案 0 :(得分:5)

首先,-charactersIgnoringModifiers不会忽略shift键,因此你仍然会得到从它返回的移位字符(即UPPERCASE和!%#$%^& *)。你的函数可能会发生什么:你按shift-w,你的-isEqualTo:返回false,因为你正在比较一个小写的'w'和一个大写的'W',所以你在得到移位检测代码之前返回底部。最简单的解决方案就是检查两者。

但是,如果您希望阿拉伯语键盘手能够轻松使用您的应用,那么您真的不应该硬编码甚至可能不会出现在用户键盘上的字符。 -keyCode返回的值是指键在键盘上的位置,而不是表示的字符。对于初学者来说,在Events.h中以'kVK_ANSI_'和'kVK_'开头的常量(你可能需要链接到Carbon.framework和#include< Carbon / Carbon.h>来使用这些常量)可以与以下内容进行比较 - keyCode返回,它们引用QWERTY使用USian期望的关键位置。所以你可以(非常)确定,无论键盘布局如何,'wasd'(kVK_ANSI_W,kVK_ANSI_A等)的密钥代码都会引用用户键盘左上角的那个三角形。

答案 1 :(得分:4)

如果您只是希望收到没有字符键的修改键按下的通知,您应该覆盖NSResponder方法flagsChanged。

- (void)flagsChanged:(NSEvent *)theEvent

答案 2 :(得分:3)

您是否尝试使用eventChars记录modifierFlagsNSLog的值?也许它不是你所期望的那样。如果日志语句没有显示在输出中,则此代码根本不运行,而您在其他地方遇到问题。

NSLog(@"Chars: %@, modifier flags: 0x%x", eventChars, [theEvent modifierFlags]);

其他一些值得注意的事情:

  1. isEqualTo:是AppleScript等于运算符。 应该工作,但效率不高,因为它会通过compare:。正确的方法是isEqualToString:或更通用的isEqual:,其中任何一个都可以进行直接的相等比较。
  2. QWERTY字母区域中的传统移动键集是wsad,而不是wxad。这使用倒T形排列。您可能还需要支持箭头键,因为我们中的许多人都有键盘,其箭头采用倒T形排列。

    此外,你应该让用户可以配置这些,你应该回复键码而不是字母,因为不同的布局(法语,德沃夏克等)会生成不同的字母。我的网站上有a table of key codes, adapted from Inside Macintosh。仅将字符用于显示目的。

  3. 不应该是“fireBullet From Column:row:inDirection:”?我不了解你,但是说这个方法在一个单元格中发射一个子弹告诉我(并且会告诉你,在你没有查看一年的代码之后)它会触发它子弹那个牢房;将“At”替换为“From”可以避免这一混乱时刻。

答案 3 :(得分:1)

从您的代码中看起来似乎永远不会到达检查修饰符的代码。 任何不是“w,x,a,d”的东西都会被发送到超类(参见else分支)。

你可能想要移动“[super keyDown:theEvent]; return;”在keyDown方法的末尾。

答案 4 :(得分:0)

解决当前问题:

  1. 根据Boaz的说法,-charactersIgnoringModifiers不包括Shift键(读取documentation),在Shift键关闭时返回大写字符。这就是Control键工作而Shift键没有工作的原因。在测试之前将字符串切换到lowercase

    eventChars = [[theEvent charactersIgnoringModifiers] lowercaseString];
    
  2. 之后,(正如Peter建议的那样)将所有isEqualTo:'更改为isEqualToString:(除了正确之外,它还记录为更快)。

  3. <强>然而

    如果您打算将这个应用程序发布给其他人,那么您应该使用密钥代码(正如Peter和Boaz建议的那样),因此它可以在尽可能多的不同键盘和设置上运行。

    在首选项中创建一个视图,其中包含您拥有的每个命令的输入,并记录用户按下的键的键代码。将它们存储在NSUserDefaults中,然后检查它们而不是硬编码字符串。您可以为当前的“wasd”键创建默认设置。

    请参阅Shortcut Recorder等项目,了解如何执行此操作(或搜索friend)。