问题
I'd like to capture key events from any window in the application and interpret them as Unicode. For example, if the user types Option-e-e (on a default-configured US English keyboard), I would like to recognize that as "é".
I tried capturing keypress events and calling -[NSEvent characters]. However, as it says in the documentation, "This method returns an empty string for dead keys, such as Option-e." If I type Option-e-e, then it gives me nothing for the Option-e and plain "e" for the second e.
Is there a way to combine a series of keycodes (from -[NSEvent keyCode]) into a Unicode character?
Or a way to receive an event for each Unicode character typed (like Java's key-typed event)?
回答1:
Here's a way to take a series of key press events and get the Unicode character(s) they'd type.
Basically, call UCKeyTranslate() for each key press event received. Use its deadKeyState argument to capture a dead key and pass it along to the subsequent call.
Example:
- Receive key press event for Option-e.
- Call
UCKeyTranslate()with the virtual key code (for e), the modifier key state (for Option), and a variable to store the dead key state.UCKeyTranslate()outputs an empty string and updates the dead key state.
- Receive key press event for e.
- Call
UCKeyTranlate()with the virtual key code (for e) and the variable that holds the dead key state.UCKeyTranslate()outputs "é".
Sample code (the function to call for each key press event):
/**
* Returns the Unicode characters that would be typed by a key press.
*
* @param event A key press event.
* @param deadKeyState To capture multi-keystroke characters (e.g. Option-E-E for "é"), pass a reference to the same
* variable on consecutive calls to this function. Before the first call, you should initialize the variable to 0.
* @return One or more Unicode characters.
*/
CFStringRef getCharactersForKeyPress(NSEvent *event, UInt32 *deadKeyState)
{
// http://stackoverflow.com/questions/12547007/convert-key-code-into-key-equivalent-string
// http://stackoverflow.com/questions/8263618/convert-virtual-key-code-to-unicode-string
TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
CFDataRef layoutData = TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout *)CFDataGetBytePtr(layoutData);
CGEventFlags flags = [event modifierFlags];
UInt32 modifierKeyState = (flags >> 16) & 0xFF;
const size_t unicodeStringLength = 4;
UniChar unicodeString[unicodeStringLength];
UniCharCount realLength;
UCKeyTranslate(keyboardLayout,
[event keyCode],
kUCKeyActionDown,
modifierKeyState,
LMGetKbdType(),
0,
deadKeyState,
unicodeStringLength,
&realLength,
unicodeString);
CFRelease(currentKeyboard);
return CFStringCreateWithCharacters(kCFAllocatorDefault, unicodeString, realLength);
}
回答2:
subclass the view/window you want to capture the "é" event in and add this instance variable
BOOL optionE_Pressed;
then, override keyDown: with this
-(void) keyDown:(NSEvent *)theEvent {
NSString *chars = theEvent.charactersIgnoringModifiers;
unichar aChar = [chars characterAtIndex: 0];
if (aChar==101 && [theEvent modifierFlags]&NSAlternateKeyMask) {
optionE_Pressed=YES;
}
else if (aChar==101 && optionE_Pressed) {
NSLog(@"spanish é pressed");
}
else {
optionE_Pressed=NO;
}
[super keyDown:theEvent];
}
The Boolean variable "optionE_Pressed" is activated when the user holds down the option and e keys. If the next key that is pressed is e, meaning that they have effectively created a spanish é, then it will log "spanish é pressed." Otherwise, the Boolien is switched back to NO. The "super" call at the end allows the user to still be able to type all events as normal
来源:https://stackoverflow.com/questions/22566665/how-to-capture-unicode-from-key-events-without-an-nstextview