我有一个应用程序,其中我正在尝试捕获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确实会产生预期效果。
答案 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
记录modifierFlags
和NSLog
的值?也许它不是你所期望的那样。如果日志语句没有显示在输出中,则此代码根本不运行,而您在其他地方遇到问题。
NSLog(@"Chars: %@, modifier flags: 0x%x", eventChars, [theEvent modifierFlags]);
其他一些值得注意的事情:
isEqualTo:
是AppleScript等于运算符。 应该工作,但效率不高,因为它会通过compare:
。正确的方法是isEqualToString:
或更通用的isEqual:
,其中任何一个都可以进行直接的相等比较。QWERTY字母区域中的传统移动键集是wsad,而不是wxad。这使用倒T形排列。您可能还需要支持箭头键,因为我们中的许多人都有键盘,其箭头采用倒T形排列。
此外,你应该让用户可以配置这些,你应该回复键码而不是字母,因为不同的布局(法语,德沃夏克等)会生成不同的字母。我的网站上有a table of key codes, adapted from Inside Macintosh。仅将字符用于显示目的。
fireBullet
From
Column:row:inDirection:
”?我不了解你,但是说这个方法在一个单元格中发射一个子弹告诉我(并且会告诉你,在你没有查看一年的代码之后)它会触发它子弹朝那个牢房;将“At”替换为“From”可以避免这一混乱时刻。答案 3 :(得分:1)
从您的代码中看起来似乎永远不会到达检查修饰符的代码。 任何不是“w,x,a,d”的东西都会被发送到超类(参见else分支)。
你可能想要移动“[super keyDown:theEvent]; return;”在keyDown方法的末尾。
答案 4 :(得分:0)
解决当前问题:
根据Boaz的说法,-charactersIgnoringModifiers不包括Shift键(读取documentation),将在Shift键关闭时返回大写字符。这就是Control键工作而Shift键没有工作的原因。在测试之前将字符串切换到lowercase:
eventChars = [[theEvent charactersIgnoringModifiers] lowercaseString];
之后,(正如Peter建议的那样)将所有isEqualTo:'更改为isEqualToString:(除了正确之外,它还记录为更快)。
<强>然而强>
如果您打算将这个应用程序发布给其他人,那么您应该使用密钥代码(正如Peter和Boaz建议的那样),因此它可以在尽可能多的不同键盘和设置上运行。
在首选项中创建一个视图,其中包含您拥有的每个命令的输入,并记录用户按下的键的键代码。将它们存储在NSUserDefaults中,然后检查它们而不是硬编码字符串。您可以为当前的“wasd”键创建默认设置。
请参阅Shortcut Recorder等项目,了解如何执行此操作(或搜索friend)。