Question

Je travaille sur une application en tapant-tuteur pour Mac OS X qui doit avoir des frappes qui lui sont transmises, même si la demande est mise au point.

Est-il possible d'avoir le système des séquences de touches avant l'application, peut-être par NSDistributedNotificationCenter? Je me suis googlé stupide, et n'ont pas été en mesure de trouver une réponse ...

EDIT:. Exemple de code ci-dessous

Merci @NSGod pour moi pointant dans la bonne direction - j'ai fini par l'ajout d'un liste des masques pour les types d'événements pris en charge peuvent être trouvés ici

Maintenant, nous arrivons à la partie la plus délicate: gestionnaire, qui attend un bloc:

handler:^(NSEvent *event){

Il m'a fallu quelques erreurs de compilation pour obtenir ce droit, mais (merci Apple) ils étaient des messages d'erreur très constructifs. La première chose à noter est le carat ^. Qui signale le début du bloc. Après cela, dans les parenthèses,

NSEvent *event

Ce qui déclare la variable que vous utiliserez dans le bloc pour capturer l'événement. Vous pouvez l'appeler

NSEvent *someCustomNameForAnEvent

Peu importe, vous aurez juste utiliser ce nom dans le bloc. Ensuite, c'est à peu près tout ce qu'il ya à faire. Assurez-vous de fermer votre accolade, et le support pour terminer l'appel de méthode:

}];

Et vous avez terminé! C'est vraiment une sorte de «one-liner. Peu importe où vous exécutez cet appel dans votre application - je le fais dans la méthode de applicationDidFinishLaunching de AppDelegate. Ensuite, dans le bloc, vous pouvez appeler d'autres méthodes à partir de votre application.

Était-ce utile?

La solution

Si vous êtes d'accord avec une exigence minimale de Mac OS X 10.6+, et peut suffire à « lecture seule » l'accès au flux d'événements, vous pouvez installer un moniteur événement mondial à Cocoa: .

Si vous avez besoin pour soutenir OS X 10.5 et versions antérieures, et accès en lecture seule est correct, et ne me dérange pas de travailler avec le Carbon Event Manager, vous pouvez en principe faire l'utilisation de carbone équivalent GetEventMonitorTarget(). (Vous serez aux abois pour trouver toute la documentation (officielle) sur cette méthode bien). Cette API a d'abord été disponible sous Mac OS X 10.3, je crois.

Si vous avez besoin d'un accès en lecture-écriture au flux d'événements, alors vous aurez besoin de regarder une API de niveau inférieur légèrement qui fait partie de ApplicationServices> CoreGraphics: CGEventTapCreate() et les amis. Ce fut d'abord disponible en 10.4.

Notez que les 3 méthodes, il faudra que l'utilisateur dispose « Activer l'accès pour les périphériques d'aide » activé dans les Préférences Système> Universal panneau de préférences d'accès (au moins pour les événements clés).

Autres conseils

Je poste le code qui a fonctionné pour mon cas.

J'ajoute le gestionnaire d'événement mondial après l'application des lancements. Mon raccourci fait ctrl + alt + cmd + T ouvrir mon application.

- (void) applicationWillFinishLaunching:(NSNotification *)aNotification
{
    // Register global key handler, passing a block as a callback function
    [NSEvent addGlobalMonitorForEventsMatchingMask:NSKeyDownMask
                                           handler:^(NSEvent *event){

        // Activate app when pressing cmd+ctrl+alt+T
        if([event modifierFlags] == 1835305 && [[event charactersIgnoringModifiers] compare:@"t"] == 0) {

              [NSApp activateIgnoringOtherApps:YES];
        }
    }];

}

La question que je trouve ce que toute clé enregistrée à l'échelle mondiale par une autre application ne sera pas cought ... ou tout au moins dans mon cas, peut-être que je fais quelque chose de mal.

Si vos besoins de programme pour afficher toutes les touches, comme « Commande-Maj-3 », par exemple, il ne verra pas passer cela pour l'afficher ... car il est repris par le système d'exploitation.

Ou bien quelqu'un qui figure sur? J'aimerais savoir ...

Comme NSGod déjà signalé, vous pouvez également utiliser CoreGraphics.

Dans votre classe (par exemple dans -init):

CFRunLoopRef runloop = (CFRunLoopRef)CFRunLoopGetCurrent();

CGEventMask interestedEvents = NSKeyDown;
CFMachPortRef eventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, 
                                        0, interestedEvents, myCGEventCallback, self);
// by passing self as last argument, you can later send events to this class instance

CFRunLoopSourceRef source = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, 
                                                           eventTap, 0);
CFRunLoopAddSource((CFRunLoopRef)runloop, source, kCFRunLoopCommonModes);
CFRunLoopRun();

En dehors de la classe, mais dans le même fichier .m:

CGEventRef myCGEventCallback(CGEventTapProxy proxy, 
                             CGEventType type, 
                             CGEventRef event, 
                             void *refcon)
{

    if(type == NX_KEYDOWN)
    {
       // we convert our event into plain unicode
       UniChar myUnichar[2];
       UniCharCount actualLength;
       UniCharCount outputLength = 1;
       CGEventKeyboardGetUnicodeString(event, outputLength, &actualLength, myUnichar);

       // do something with the key

       NSLog(@"Character: %c", *myUnichar);
       NSLog(@"Int Value: %i", *myUnichar);

       // you can now also call your class instance with refcon
       [(id)refcon sendUniChar:*myUnichar];
   }

   // send event to next application
   return event;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top