Quel genre d'événements clés attendez-vous si vous n'avez pas de fenêtre?
Si vous avez besoin d'intercepter des événements clés globalement, vous devrez utiliser une touche Event Quartz. Vous devez être très prudent avec ceux-ci car si vous lancez une exception dans un événement, le gestionnaire de prise peut geler le serveur de fenêtre, de sorte que la gestion des exceptions soit en place.
#import <ApplicationServices/ApplicationServices.h>
//assume CGEventTap eventTap is an ivar or other global
void createEventTap(void)
{
CFRunLoopSourceRef runLoopSource;
///we only want keydown events
CGEventMask eventMask = (1 << kCGEventKeyDown);
// Keyboard event taps need Universal Access enabled,
// check whether we're allowed to attach an event tap
if (!AXAPIEnabled()&&!AXIsProcessTrusted()) {
// error dialog here
NSAlert *alert = [[[NSAlert alloc] init] autorelease];
[alert addButtonWithTitle:@"OK"];
[alert setMessageText:@"Could not start event monitoring."];
[alert setInformativeText:@"Please enable \"access for assistive devices\" in the Universal Access pane of System Preferences."];
[alert runModal];
return;
}
//create the event tap
eventTap = CGEventTapCreate(kCGHIDEventTap, //this intercepts events at the lowest level, where they enter the window server
kCGHeadInsertEventTap,
kCGEventTapOptionDefault,
eventMask,
myCGEventCallback, //this is the callback that we receive when the event fires
nil);
// Create a run loop source.
runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);
// Add to the current run loop.
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);
// Enable the event tap.
CGEventTapEnable(eventTap, true);
}
//the CGEvent callback that does the heavy lifting
CGEventRef myCGEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef theEvent, void *refcon)
{
//handle the event here
//if you want to capture the event and prevent it propagating as normal, return NULL.
//if you want to let the event process as normal, return theEvent.
return theEvent;
}
J'intercepte les presses d'options et de cmd, similaires au menu des pommes pour changer la fonction des éléments de menu. Il semble que je devrais aller de cette façon. –
Si vous devez changer le titre du menu alors que le menu est déjà ouvert, alors vous aurez certainement besoin de le faire de cette façon. Cependant, vous pouvez simplement implémenter -menuNeedsUpdate: dans votre délégué de menu et ajuster les titres de menu basés sur les modificateurs actifs à ce point à la place. Cela ne vous donnera pas de modifications "en direct" du menu lorsque vous appuyez sur/relâcher des touches de modification, mais c'est beaucoup plus simple que d'utiliser un CGEventTap. –
Je ne suis pas si préoccupé par l'état du MSMenuItems que j'effectue la fonction correcte lorsque l'on clique dessus. Techniquement, je n'ai pas besoin de mises à jour, mais j'ai besoin de l'état correct du clavier lorsque l'utilisateur clique sur un élément du menu. Je préfère ne pas mettre l'utilisateur à travers l'étape supplémentaire en exigeant des «appareils fonctionnels». J'ai trouvé HidLib de Dave Dribin, qui après un certain temps je peux me mettre au travail, mais il semble que c'est trop. N'y a-t-il pas d'abstraction de Cocoa que vous pouvez utiliser pour simplement taper: [keyboard activeKeys]; On dirait que ça devrait être trivial. –