2009-09-08 7 views
7

Ich habe ein NSMenu, das aus einem NSStatusItem mit popUpStatusItemMenu herausspringt. Diese NSMenuItems zeigen eine Reihe von verschiedenen Links, und jeder ist mit setAction verbunden: mit der openLink: -Methode eines Ziels. Dieses Arrangement funktioniert lange gut. Der Benutzer wählt einen Link aus dem Menü und die Methode openLink: behandelt sie dann.Benutzerdefiniertes NSView in NSMenuItem empfängt keine Mausereignisse

Leider habe ich vor kurzem beschlossen, mit der setView: -Methode von NSMenuItem zu experimentieren, um eine nettere/slicker-Schnittstelle bereitzustellen. Im Grunde habe ich gerade den Titel eingestellt, das NSMenuItem erstellt und dann setView: verwendet, um eine benutzerdefinierte Ansicht anzuzeigen. Das funktioniert einwandfrei, die Menüpunkte sehen gut aus und meine benutzerdefinierte Ansicht wird angezeigt.

Wenn der Benutzer jedoch ein Menüelement auswählt und die Maus freigibt, funktioniert die Aktion nicht mehr (d. H. OpenLink: wird nicht aufgerufen). Wenn ich einfach den Befehl setView: comment auskommentiere, dann funktionieren die Aktionen wieder (natürlich sind die Menüpunkte leer, aber die Aktion wird korrekt ausgeführt). Meine erste Frage ist daher, warum das Setzen einer Ansicht die Aktion von NSMenuItem bricht.

Kein Problem, dachte ich, ich werde es beheben, indem ich das mouseUp-Ereignis in meiner benutzerdefinierten Ansicht erkenne und meine Aktionsmethode von dort aus aufrufen. Ich habe diese Methode zu meiner benutzerdefinierten Ansicht hinzugefügt:

- (void)mouseUp:(NSEvent *)theEvent { 
    NSLog(@"in mouseUp"); 
    } 

Kein Würfel! Diese Methode wird nie aufgerufen.

Ich kann Tracking-Rects festlegen und mouseEntered: events jedoch erhalten. Ich habe ein paar Tests in meiner mouseEntered Routine wie folgt:

if ([[self window] ignoresMouseEvents]) { NSLog(@"ignoring mouse events"); } 
else { NSLog(@"not ignoring mouse events"); } 
if ([[self window] canBecomeKeyWindow]) { dNSLog((@"canBecomeKeyWindow")); } 
else { NSLog(@"not canBecomeKeyWindow"); } 
if ([[self window] isKeyWindow]) { dNSLog((@"isKeyWindow")); } 
else { NSLog(@"not isKeyWindow"); } 

Und bekam folgende Antworten:

not ignoring mouse events 
canBecomeKeyWindow 
not isKeyWindow 

Ist das das Problem? "nicht isKeyWindow"? Vermutlich ist das nicht gut, weil Apples Dokumente sagen: "Wenn der Benutzer auf eine Ansicht klickt, die nicht im Schlüsselfenster ist, wird das Fenster standardmäßig nach vorne gebracht und zum Schlüssel gemacht, aber das Mausereignis wird nicht ausgelöst." Aber es muss einen Weg geben, diese Ereignisse zu erkennen. WIE?

Hinzufügen:

[[self window] makeKeyWindow]; 

hat keine Wirkung, trotz der Tatsache, dass canBecomeKeyWindow JA ist.

+0

Es gibt weitere Informationen zu diesem Problem bei offenem Radar: http://openradar.appspot.com/7128269 Es gibt auch eine behauptete Abhilfe, aber ich kann nicht die Abhilfe Arbeit machen. Grundsätzlich verweigert das Fenster den Schlüssel, obwohl es canBecomeKey meldet. – Dennis

+0

Hallo, ich habe das gleiche Problem, haben Sie Fortschritte damit? Ich habe versucht, einige Möglichkeiten, es zu lösen, ich habe einen Workaround gefunden, aber es ist schrecklich hässlich, und nach dem Anzeigen der Menü Statusleiste Element ist nicht markiert, aber Menü ist gezeigt und voll funktionsfähig. Ich habe Menü für Statuselement auf Null eingestellt und manuell Menü Popup steuern. Wenn die Anwendung aktiv ist, rufe ich einfach die Popup-Methode des Menüs auf, wenn ich keine aktiviere, mache die Anwendung aktiv, und im Callback öffne ich das Menü. Hier ist ein Code. Wieder ist es schrecklich und hässlich. http://gist.github.com/224275 – iafonov

+0

Ich muss sagen, dass iafonovs Code ist GREAT! Obwohl vor einem Jahr !!! Obwohl der Code irrelevant erscheint. Vielen Dank! Es löst alle Probleme mit NSVIEW, NSTextEdit in NSMenuItem. Zunächst funktioniert das NSTextEdit (in NSMenuItem) nicht normal, kann keinen Tastendruck erhalten und die Maus ändert sich nicht, jetzt funktioniert alles wunderbar !!! No acceptsFirstResponder, No self window makeFirstResponder: xxx, Nur iafonov'code. Es ist die Art und Weise Pop-up-Menü, das zählt. http://gist.github.com/224275 – user377808

Antwort

9

Fügen Sie diese auf Ihre benutzerdefinierte Ansicht und Sie sollten in Ordnung sein:

- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent 
{ 
    return YES; 
} 
+1

Arbeitete, danke! – Vojto

4

ich diese Methode zu meiner benutzerdefinierten Ansicht hinzugefügt, und jetzt alles funktioniert wunderbar:

- (void)viewDidMoveToWindow { 
    [[self window] becomeKeyWindow]; 
} 

hoffe, das hilft!

12

diese Methode, um Ihre benutzerdefinierten NSView hinzufügen und es wird mit Maus-Ereignisse

- (void)mouseUp:(NSEvent*) event { 
    NSMenuItem* mitem = [self enclosingMenuItem]; 
    NSMenu* m = [mitem menu]; 
    [m cancelTracking]; 
    [m performActionForItemAtIndex: [m indexOfItem: mitem]]; 
} 

Aber ich habe Probleme mit keyhandling gut funktionieren, wenn Sie dieses Problem vielleicht gelöst können Sie auf meine Frage gehen und mir helfen ein bisschen.

+0

Das war die Lösung für mich! Vielen Dank! – kdbdallas

+0

Wow, ich habe einen halben Tag damit verbracht, das herauszufinden. Vielen Dank – Cory

-1

Kürzlich musste ich eine benutzerdefinierte Ansicht für ein NSStatusItem anzeigen, ein normales NSMenu anzeigen, wenn ich darauf klicke und Drag & Drop-Operationen auf dem Statussymbol unterstütze.

Ich löste mein Problem mit hauptsächlich drei verschiedenen Quellen, die in this Frage gefunden werden können.

Ich hoffe, es hilft anderen Menschen.

-1

Siehe den Beispielcode von Apple namens CustomMenus Dort finden Sie ein gutes Beispiel in der ImagePickerMenuItemView-Klasse.

Es ist nicht einfach oder trivial, eine Ansicht in einem Menü wie ein normales NSMenuItem zu behandeln. Es gibt einige echte Entscheidungen und Codierungen zu tun.