Gibt es eine äquivalente Technik in Kakao für den synchronen TrackpopupMenu in Windows?

StackOverflow https://stackoverflow.com/questions/227935

  •  03-07-2019
  •  | 
  •  

Frage

Als Antwort auf ein Ereignis von Rightmouse möchte ich eine Funktion aufrufen, die ein Kontextmenü anzeigt, es ausführt und auf den ausgewählten Menüelement antwortet. In Windows kann ich TrackpopupMenu mit dem Flag TPM_ReturnCMD verwenden.

Was ist der einfachste Weg, dies in Kakao umzusetzen? Es scheint, dass NSMenu: PopupContextMenu ein Ereignis für das angegebene NSView veröffentlichen. Muss ich eine Dummy -Ansicht erstellen und auf das Ereignis warten, bevor ich zurückkommt? Wenn ja, wie "warte" oder spüle Ereignisse, da ich nicht zu meinem Haupt zurückkomme?

War es hilfreich?

Lösung 2

Es scheint, dass PopupContextMenu bereits synchron ist. Da ich keinen Weg gesehen habe, NSMenu zu verwenden, ohne dass es eine Benachrichtigung an eine NSView senden konnte, habe ich ein Schema entwickelt, das eine vorübergehende NSView instanziiert. Ziel ist es, ein Popup -Menü anzuzeigen und das ausgewählte Element im Kontext eines einzelnen Funktionsaufrufs zurückzugeben. Im Folgenden finden Sie Codeausschnitte meiner vorgeschlagenen Lösung:

// Dummy View class used to receive Menu Events

@interface DVFBaseView : NSView
{
    NSMenuItem* nsMenuItem;
}
- (void) OnMenuSelection:(id)sender;
- (NSMenuItem*)MenuItem;
@end

@implementation DVFBaseView
- (NSMenuItem*)MenuItem
{
    return nsMenuItem;
}

- (void)OnMenuSelection:(id)sender
{
    nsMenuItem = sender;
}

@end

// Calling Code (in response to rightMouseDown event in my main NSView

void HandleRButtonDown (NSPoint pt)
{
    NSRect    graphicsRect;  // contains an origin, width, height
    graphicsRect = NSMakeRect(200, 200, 50, 100);

    //-----------------------------
    // Create Menu and Dummy View
    //-----------------------------

    nsMenu = [[[NSMenu alloc] initWithTitle:@"Contextual Menu"] autorelease];
    nsView = [[[DVFBaseView alloc] initWithFrame:graphicsRect] autorelease];

    NSMenuItem* item = [nsMenu addItemWithTitle:@"Menu Item# 1" action:@selector(OnMenuSelection:) keyEquivalent:@""];

    [item setTag:ID_FIRST];

    item = [nsMenu addItemWithTitle:@"Menu Item #2" action:@selector(OnMenuSelection:) keyEquivalent:@""];

    [item setTag:ID_SECOND];
    //---------------------------------------------------------------------------------------------
// Providing a valid windowNumber is key in getting the Menu to display in the proper location
//---------------------------------------------------------------------------------------------

    int windowNumber = [(NSWindow*)myWindow windowNumber];
    NSRect frame = [(NSWindow*)myWindow frame];
    NSPoint wp = {pt.x, frame.size.height - pt.y};  // Origin in lower left

    NSEvent* event = [NSEvent otherEventWithType:NSApplicationDefined
                     location:wp
                     modifierFlags:NSApplicationDefined 
                     timestamp: (NSTimeInterval) 0
                     windowNumber: windowNumber
                     context: [NSGraphicsContext currentContext]
                     subtype:0
                     data1: 0
                     data2: 0]; 

    [NSMenu popUpContextMenu:nsMenu withEvent:event forView:nsView];      
    NSMenuItem* MenuItem = [nsView MenuItem];

    switch ([MenuItem tag])
    {
    case ID_FIRST: HandleFirstCommand(); break;
    case ID_SECOND: HandleSecondCommand(); break;
    }
 }

Andere Tipps

Die „richtige“ Möglichkeit, dies in Kakao zu tun, besteht darin, dass das Ziel und die Aktion Ihres Menüelements die erforderliche Methode ausführen. Wenn Sie dies jedoch in Ihrem ersten Anruf tun müssen, können Sie verwenden [NSView nextEventMatchingMask:] Um kontinuierlich neue Ereignisse zu holen, die Sie interessieren, sie umgehen und schleifen. Hier ist ein Beispiel, das nur bis zur Veröffentlichung der rechten Maustaste wartet. Sie möchten wahrscheinlich ein komplexeres Maskenargument verwenden und kontinuierlich anrufen [NSView nextEventMatchingMask:] bis du bekommst, was du willst.

NSEvent *localEvent = [[self window] nextEventMatchingMask: NSRightMouseUpMask];

Ich denke, Sie werden den „richtigen“ Weg finden, viel einfacher zu werden.

Es gibt kein direktes Äquivalent, außer in Kohlenstoff, was veraltet ist.

Folgen Sie zum Erkennen des Rechtsklicks diese Anweisungen. Sie stellen sicher, dass Sie mit der rechten Maustaste und rechts nach rechts klicken und das Menü angezeigt werden, wenn Sie es sollten, und es nicht anzeigen, wenn Sie dies nicht sollten.

Für die folgenden Ereignisse könnten Sie es versuchen [[NSRunLoop currentRunLoop] runMode:NSEventTrackingRunLoopMode untilDate:[NSDate distantFuture]]. Sie müssen dies wiederholt anrufen, bis der Benutzer eines der Menüelemente ausgewählt hat.

Verwendung nextEventMatchingMask:NSRightMouseUpMask funktioniert nicht in allen oder sogar den meisten Fällen. Wenn der Benutzer rechts-Klicks Bei Ihrer Steuerung fällt die rechte Maustaste sofort nach, ohne einen Menüpunkt auszuwählen, und die Auswahl der Menüelemente wird wahrscheinlich (wenn auch nicht unbedingt) über die linke Maustaste erfolgen. Besser die Auslaufschleife wiederholt ausführen, bis der Benutzer entweder etwas auswählt oder das Menü entlässt.

Ich weiß nicht, wie ich sagen soll, dass der Benutzer das Menü entlassen hat, ohne etwas auszuwählen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top