2010-01-23 18 views
2

J'essaie d'utiliser des taps d'événement pour créer un programme OS X qui va écouter le yiddish tapé en translittération et afficher le résultat en caractères hébreux. J'ai fait un programme très court pour tester une des choses que je dois faire: http://pastie.org/791398Comment utiliser CGEventKeyboardSetUnicodeString avec plusieurs caractères?

Comme il est, le programme remplace avec succès tous les typé « q » avec « w »:

if(inputString[0] == 'q') { inputString[0] = 'w'; } 

Mais comment poster une chaîne de plus d'un caractère? Par exemple, si quelqu'un tape 'sh', vous devrez probablement poster un backspace (pour supprimer le caractère qui a été posté pour 's' seulement) et ensuite afficher le caractère qui correspond à 'sh'. Cependant, ce code entraîne seulement un retour arrière affiché:

else if(inputString[0] == 'm') { inputString[0] = '\b'; inputString[1] = 'n'; } 

Je m'excuse si ce sont des questions de base; J'ai lu toute la documentation que j'ai pu trouver, mais je n'aurais peut-être pas tout compris. Il est également possible que je m'y mette complètement dans le mauvais sens.

Répondre

2

Idéalement, vous devriez utiliser une méthode de saisie au lieu d'un programme avec des taps d'événement, probablement en utilisant Input Method Kit si vous n'avez pas besoin de prendre en charge le pré-10.5. L'utilisation des taps d'événement à cette fin est intrinsèquement une mauvaise idée car l'utilisateur peut changer où il tapait avec la souris ainsi que le clavier. Donc, si l'utilisateur tapait un "s" dans un champ de texte suivi d'un "h" dans un autre, vous ne seriez pas capable de faire la différence.

Cela dit, voici une réponse directe à votre question.

La chaîne est comptée en longueur, donc vous ne pouvez pas simplement fournir la longueur entrante (1); le deuxième personnage sera ignoré. Cependant, la plupart des applications n'aiment pas avoir plus d'un caractère par événement, donc ils vont simplement ignorer les caractères restants. (Terminal est une exception notable.)

Ainsi, vous pouvez simplement poster un deuxième événement avec le deuxième caractère.

else if(inputString[0] == 'm') { 
    inputString[0] = 'n'; 
    CGEventKeyboardSetUnicodeString(event, 1, inputString); 
    CGEventPost(kCGSessionEventTap, event); 
    inputString[0] = '\b'; 
} 

Dans le cas général (simulation> 2 pressions sur les touches), vous devez créer un événement pour chaque personnage que vous souhaitez insérer. This mailing list post inclut un exemple simple.

+0

Merci! C'est vraiment utile à savoir - et vous avez raison d'avoir fait une méthode de saisie avec IMKit. (En fait, il est plus facile d'utiliser un framework de méthode de saisie comme MacUIM: http://code.google.com/p/macuim/) –

0

Voici comment j'envoie une chaîne au premier répondeur (application de premier plan)

// 1 - Get the string length in bytes.   
NSUInteger l = [string lengthOfBytesUsingEncoding:NSUTF16StringEncoding]; 

// 2 - Get bytes for unicode characters 
UniChar *uc = malloc(l); 
[string getBytes:uc maxLength:l usedLength:NULL encoding:NSUTF16StringEncoding options:0 range:NSMakeRange(0, l) remainingRange:NULL]; 

// 3 - create an empty tap event, and set unicode string 
CGEventRef tap = CGEventCreateKeyboardEvent(NULL,0, YES); 
CGEventKeyboardSetUnicodeString(tap, string.length, uc); 

// 4 - Send event and tear down 
CGEventPost(kCGSessionEventTap, tap); 
CFRelease(tap); 
free(uc);