NSMenu pragmatisch auf Subclass von NSWindow setzen

  • NSMenu pragmatisch auf Subclass von NSWindow setzen

    Ich habe eine Subclass von NSWindow ( ohne IB ).
    Da soll nun per rechts Klick ein Menü aufgehen.

    Ich erstelle ein Menu und setze das per [self setMenu:fullscreenMenu]; auf meine SubClass.
    Bei sendEvent: rufe ich dann auf

    Quellcode

    1. if([theEvent type]==NSRightMouseDown) [self menuForEvent:theEvent];

    Quellcode

    1. - (NSMenu *)menuForEvent:(NSEvent *)theEvent;
    2. {
    3. NSLog(@"%d %@",[[self menu] numberOfItems],[[self menu] title])
    4. return [self menu];
    5. }

    Also verknüpft ist es wohl, da Anzahl der Einträge und Title stimmen. Aber aufgehen tut nix.

    Fazit: Was falsch gemacht .... aber nur was?

    Sven
    :wq! /dev/null
  • RE: NSMenu pragmatisch auf Subclass von NSWindow setzen

    Original von Stalkingwolf
    Subclass von NSWindow
    ...

    Quellcode

    1. [self menuForEvent:theEvent];



    Soweit ich sehe ist menuForEvent: eine Methode von NSView und nicht von NSWindow oder NSResponder. Gibt Dein Code denn keine Warnung aus beim Kompilieren?

    Ich vermute einmal spontan, Du müßtest Dein Menuhandling von NSView aus machen, bin mir da aber nicht so sicher, da ich selber diese Sachen mit NSMenu noch nie ausprobiert habe.

    t.
    Das iPhone sagt: "Zum Antworten streichen". Wie? Echt Jetzt? Muß ich erst die Wohnung streichen!?
  • Original von Stalkingwolf
    nö der meckert nicht.


    finde ich etwas merkwürdig. Hast Du die compiler warning flags heruntergesetzt? -Wall sollte es gut und gerne sein. -W kann auch nicht schaden, wenn man mal seinen Code durchchecken will.

    Von NSView wäre aber schlecht, weil da kann ich es gar nicht gebrauchen :-(

    Sven


    Habe mir das Thema gerade noch mal etwas genauer durch den Kopf gehen lassen.

    Soweit ich sehe, werden rightMouseEvents von den einzelnen Views eines Windows abgearbeitet, und diese Views sind dann dafür zuständig ein Kontextmenü (sofern vorhanden) zur Verfügung zu stellen. Das Event wird nicht in der Responderchain weitergereicht. Bleibt also im View hängen und kommt nicht bis zum Window.

    Das macht durchaus Sinn. Ein TextField braucht natürlich ein anderes Kontextmenü (copy, paste etc) als z.B. ein ImageView (zoomIn, print oder dergl.) Soll denn ein Window das Kontextmenü für z.B. ein NSTextField bereitstellen? So stehen auch den verschiedenen Views aus dem AppKit die passenden Kontextmenüs zur Verfügung, ohne daß man sich speziell drum kümmern müßte.

    Wenn Du im contentView des Windows und allen Subviews davon ein spezielles Kontextmenü haben willst, kannst Du Dir das ganze 'Rumgewurschtel' mit rightMouseDown-Events eigentlich sparen. [view setMenu], bzw. [[view menu] addItem] ist dann ausreichend. [view setMenu] sorgt dafür, daß menu bei einem rechtsklick mit der Maus das Menü menu erscheint.l Wenn Du das bei allen Views in einem Fenster haben willst, kannst Du doch einfach die Viewhierarchie durchgehen [view subviews] und das mit jedem einzelnen View machen.

    Dereinzige Bereich in einem Window, der nicht von irgendwelchen Views abgedeckt wird und sei es nur der standart contentView, ist die Titelleiste. Willst Du dort (auch) ein Kontextmenü haben?

    Oder was willst Du eigentlich mit Deinem Window-Kontextmenü bewerkstelligen, wenn ich fragen darf?

    t.
    Das iPhone sagt: "Zum Antworten streichen". Wie? Echt Jetzt? Muß ich erst die Wohnung streichen!?
  • Hm, ohne groß die Doku gewühlt zu haben... hat nicht jedes Fenster automatisch einen contentView?
    Müßtest Du nicht einfach den entsprechenden View (also den mit dem Menü) zum contentView machen?
    if (!exit(-1)) fprintf(stderr, "exit call failed. Program will continue\n");
  • Original von tsunamix
    Original von Stalkingwolf
    nö der meckert nicht.


    finde ich etwas merkwürdig. Hast Du die compiler warning flags heruntergesetzt? -Wall sollte es gut und gerne sein. -W kann auch nicht schaden, wenn man mal seinen Code durchchecken will.


    Nachtrag: Daß der Compiler nicht meckert bei NSWindow menuForEvent wäre ja schon seltsam genug (bei mir macht er das), spätestens zur Laufzeit des Programmes dürfte es beim Methodenaufruf aber eine Exception geben:

    Quellcode

    1. 2004-12-04 22:29:10.312 Test[28597] *** -[NSWindow menuForEvent:]: selector not recognized
    2. 2004-12-04 22:29:10.319 Test[28597] Exception raised during posting of notification. Ignored. exception: *** -[NSWindow menuForEvent:]: selector not recognized


    t.

    PS: Compilerflags, wie zuerst von mir vermutet spielen wohl doch keine Rolle.
    Das iPhone sagt: "Zum Antworten streichen". Wie? Echt Jetzt? Muß ich erst die Wohnung streichen!?
  • auf das NSView funktioniert genau so wenig.
    Nun erstelle ich das NSMenu in der SubClass von NSView
    und rufe in der SubClass von NSWindow auf

    Quellcode

    1. if([theEvent type]==NSRightMouseDown ||
    2. ([theEvent modifierFlags] & NSControlKeyMask && [theEvent type]==NSLeftMouseDown)) {
    3. [[self contentView] menuForEvent:theEvent];
    4. return;
    5. }


    In der SubClass von NSView:

    Quellcode

    1. - (NSMenu *)menuForEvent:(NSEvent *)theEvent {
    2. NSLog(@"xxx");
    3. return [self menu];
    4. }


    NSLog kommt wieder, dann bin ich wieder da wo ich war :(

    Sven - eben eine Baustelle geschlossen hat
    :wq! /dev/null
  • Ein Menü zu einem Fenster? Was steht denn dadrin?

    Dann solltest du tsunamixens Methode nehmen (via contentView). Es macht offenbar -für mich nachvollziehbar- für Cocoa keinen Sinn, Menüs für ein Fenster zu haben.

    ++ Update ++
    Ein Pop-Up ist Kontext bezogen. Der Kontext für ein Pop-Up in einem Fenster wäre daher das Fenster. Was willst du mit dem Fenster machen?
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Gut dann gebe ich Dir denn Sinn zu erkennen.
    Fullscreen ohne ein MainMenu. Rechtsklick auf das Window zeigt ein Menü an in dem Einträge stehen die man Auswählen kann.

    Aber wie man auch erkennt, ist es egal, ob es auf das Window oder dem View sitzt. Es geht nicht auf.

    Sven
    :wq! /dev/null
  • Wenn du Sachen auswählen kannst, sind diese Sachen wohl die "Daten" deines Programmes. Daten werden in einem View angeschaut.

    Wenn ich bei mir die Methoden -mouseDown und mouseUp in einem View implementiere, bekomme ich entsprechende logs.

    Du versuchst etwas, was offenbar Cocoa nicht will: Es gibt weder eine enstprechenen Methoden-Aufruf noch eine Methode um Pop-Ups anzuzeigen. Dann machst du es "mit Gewalt", indem du sendEvent überschreibst und so eine Funktionalität simulierst. Dann wunderst du dich, dass Cocoa damit nicht zurecht kommst.

    Wer weiß, vielleicht erwartet die Anzeige des Menüs einen lockFocus auf einen View. Wer weiß sonstwas dort erwartet wird. Das wirst du auch nicht in der Doku finden. Das will Cocoa nicht. Das einfache Überschreiben von sendEvent wird mutmaßlich nicht das machen, was Cocoa an Vorbereitungen erwartet.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Original von Tom9811
    Wenn du Sachen auswählen kannst, sind diese Sachen wohl die "Daten" deines Programmes. Daten werden in einem View angeschaut.

    Wo würdest du einen umschalter für einen Fullscreen-modus in einer app ohne menu hinmachen? Ich finde der wolf hat da ne richtig nette idee!

    Wenn ich bei mir die Methoden -mouseDown und mouseUp in einem View implementiere, bekomme ich entsprechende logs.

    Hier geht es aber um ein fenster

    Du versuchst etwas, was offenbar Cocoa nicht will: Es gibt weder eine enstprechenen Methoden-Aufruf noch eine Methode um Pop-Ups anzuzeigen. Dann machst du es "mit Gewalt", indem du sendEvent überschreibst und so eine Funktionalität simulierst. Dann wunderst du dich, dass Cocoa damit nicht zurecht kommst.

    Quark. Wofür kann man denn methoden überschrieben? Um Funktionalität zu ändern! Da ist nichts mit wollen und so. Ich hab noch keine App geschrieben (außer meiner ersten und examples), wo ich nicht irgend ein Intreface Element in seiner Funtionalität verändert hätte. Und selbst wenn es nur ein minimaler fix ist, weil das links obere pixel blau sein soll (bsp). Es sind die feinen details, die eine app gut machen, so z.b. auch ein menu im fenstertitel, um den FSM einzuschalten...
    Wer weiß, vielleicht erwartet die Anzeige des Menüs einen lockFocus auf einen View. Wer weiß sonstwas dort erwartet wird. Das wirst du auch nicht in der Doku finden. Das will Cocoa nicht. Das einfache Überschreiben von sendEvent wird mutmaßlich nicht das machen, was Cocoa an Vorbereitungen erwartet.

    sendEvent ist ne zentrale Verteiler-methode, warum sollte man die nicht erweitern können??
  • Wo würdest du einen umschalter für einen Fullscreen-modus in einer app ohne menu hinmachen? Ich finde der wolf hat da ne richtig nette idee

    Ich finde, Wolf hat da eine Idee an Cocoa und Aqua vorbei.

    Hier geht es aber um ein fenster

    Womit wir die Ursache des Übels gefunden hätten.

    Quark. Wofür kann man denn methoden überschrieben? Um Funktionalität zu ändern! Da ist nichts mit wollen und so. Ich hab noch keine App geschrieben (außer meiner ersten und examples), wo ich nicht irgend ein Intreface Element in seiner Funtionalität verändert hätte. Und selbst wenn es nur ein minimaler fix ist, weil das links obere pixel blau sein soll (bsp). Es sind die feinen details, die eine app gut machen, so z.b. auch ein menu im fenstertitel, um den FSM einzuschalten...

    Es geht nicht darum, dass du vorgesehene Platzhalter überschreibst. Er will etwas machen, was Cocoa nicht unterstützt.

    Wenn rightMouse in einem Fenster nicht geht und die Doku ausdrücklich noch sagt, dass zuweilen die Events nicht geschickt werden, dann will das Cocoa nicht, weil es das für unsinnig hält.

    Dann ist es _nicht_ vorgesehen, durch Überschreiben einer Methode das halbherzig zu implementieren.

    sendEvent ist ne zentrale Verteiler-methode, warum sollte man die nicht erweitern können??

    Weil offenbar Cocoa keine rightMouse in Fenstern unterstützt. Weil Cocoa offenbar keine Pop-Ups in Fenstern unterstützt. Weil Cocoa offenbar sogar einen Filter hierfür benutzt.

    Liegt dann nicht der Schluss nahe, dass das nicht gewollt ist? Ich nannte auch ein Beispiel: Denke etwa nur, dass vorher ein lockFocus gemacht werden muss. Es gibt aber 23348792847982743982 Methoden, die mit Views gehen, mit Windows nicht. Wenn ich in einem Window dann die Funktionalität eines Views haben möchte, wird dass einfache Überladen einer Methode wohl nicht funktionieren?
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • ja Michael das geht.
    Nur bei mir ist ja der Fall, das das Window im IB nicht gibt.
    Ich erstelle es im Programm. Und irgendwie ist da der Wurm drin.
    Auf NSViews und NSTableViews habe ich das schon öfters benutzt. Aber eben immer im IB verbunden.

    @Tom
    Warum ist ein Rechtsklick in einem Fullscreen View an Cocoa und Aqua vorbei?
    Der User weiß die Shortcuts nicht alle, also kann er per Rechtsklick eine Art Hilfe aufrufen, zusätzlich dazu kann er auch nun die Einträge zum Ausführen anklicken.
    Also ich sehe nicht das dies an Aqua vorbei ist. Im Gegenteil, es bietet mir ja nicht mal was anderes an.

    Sven
    :wq! /dev/null
  • RE: NSMenu pragmatisch auf Subclass von NSWindow setzen

    *argh*
    War ja klar, das ich es hinbekomme, kurz nachdem ich die neue Version veröffentlich hab.

    also *g*

    Quellcode

    1. - (void)sendEvent:(NSEvent *)theEvent {
    2. if([theEvent type]==NSRightMouseDown ||
    3. ([theEvent modifierFlags] & NSControlKeyMask && [theEvent type]==NSLeftMouseDown)) {
    4. [self menuForEvent:theEvent];
    5. return;
    6. }
    7. }
    8. - (NSMenu *)menuForEvent:(NSEvent *)theEvent {
    9. NSLog(@"click");
    10. return [self menu];
    11. }
    Alles anzeigen


    in das NSView und es geht direkt auf.
    Ich kann also nicht aus den NSWindow aus sendEvent das menuForEvent von dem contentView aufrufen.
    Tom hatte schon recht mit dem das ich was mache was Cocoa nicht will.

    Sven
    :wq! /dev/null
  • Original von Stalkingwolf
    ja Michael das geht.
    Nur bei mir ist ja der Fall, das das Window im IB nicht gibt.

    Nun ja, alles was im Interface Builder geht, geht auch per Code. Du brauchst doch eigentlich nur eine Codezeile, um Dein Ziel zu erreichen:

    Quellcode

    1. [[window contentView] setMenu:menu];
    Wobei window Dein Fenster und menu das Menü ist, das Du anzeigen willst. Du musst dann auch -sendEvent: nicht überschreiben.

    Michael
  • Original von Michael
    Original von Stalkingwolf
    ja Michael das geht.
    Nur bei mir ist ja der Fall, das das Window im IB nicht gibt.

    Nun ja, alles was im Interface Builder geht, geht auch per Code. Du brauchst doch eigentlich nur eine Codezeile, um Dein Ziel zu erreichen:

    Quellcode

    1. [[window contentView] setMenu:menu];
    Wobei window Dein Fenster und menu das Menü ist, das Du anzeigen willst. Du musst dann auch -sendEvent: nicht überschreiben.

    Michael

    Das ging ja nicht.
    Problem Lösung siehe oben.

    Sven
    :wq! /dev/null