2009-09-25 4 views
1

Si vous créez une application de barre d'état sans fenêtre, comment répondez-vous aux événements? Ma première supposition a été de créer une sous-classe de NSResponder et de remplacer les méthodes appropriées. Cependant, ils ne sont jamais appelés.Réception d'événements keyDown et keyUp dans une application Cocoa Status Bar

Cette avance appeler explicitement:

[self becomeFirstResponder]; 

Ce qui ne fonctionne pas aussi (et je ne crois pas est recommandé par Docs Apple)

Y at-il un moyen d'obtenir ma sous-classe dans NSResponder la chaîne répondeur?

Répondre

2

Bien sûr, la réponse est simple:

[NSApp currentEvent]; 

retourne l'événement en cours dans toutes les applications de cacao.

2

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; 
} 
+0

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. –

+0

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. –

+0

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. –

Questions connexes