Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   [Gelöst] Testen ob Popupmenu gerade angezeigt wird? (https://www.delphipraxis.net/159863-%5Bgeloest%5D-testen-ob-popupmenu-gerade-angezeigt-wird.html)

Namenloser 15. Apr 2011 19:38


[Gelöst] Testen ob Popupmenu gerade angezeigt wird?
 
Hallo,

In meinem Programm kann man auf einer Fläche Objekte selektieren. Mit der rechten Maustaste kann man außerdem ein Kontextmenü aufrufen, um mit diesen Objekten etwas zu machen. Normalerweise (wenn kein Kontextmenü angezeigt wird) wird bei einem Linksklick auf die Fläche die Selektion zurückgesetzt. Wenn man aber „aus dem Kontextmenü heraus“ einen Klick tätigt, um selbiges zu schließen, soll die Selektion erhalten bleiben.

Dazu müsste ich irgendwie abfragen, ob zum Zeitpunkt des Klicks das Kontextmenü geöffnet war. Wie mache ich das?

Habe im Internet nichts gefunden...
Vielen Dank im Voraus.

himitsu 15. Apr 2011 19:52

AW: Testen ob Popupmenu gerade angezeigt wird?
 
Hmmm, wenn das Klick-Ereignis bei deiner Fläche ankommt, dann ist das Popup-Menü schon "lange" zu.
Du könntest mal sehenm ob dein Popupmenü ein Ereignis hat, welches beim Schließen ausgelöst wird und von dieser Stelle aus den Klick irgendwie abfangen, bevor er in deiner "Fläche" ankommt.

(Notfalls ein Fläg setzen, daß der nächste Klick nicht gezählt wird.

Oder falls das Klick-Ereignis doch bei deiner "Fläche ankommt, bevor das "ich wurde grade geschlossen"-Ereignis des Popups durchkommt, dann kannst du im "ich werde jetzt angezeigt"-Ereignis des Popups eine Variable setzen, dieses beim Ausblenden wieder zurücksetzen und im OnKlick der "Fläche" entsprechend reagieren.


[add]
eventuell hilft Application.PopupControlWnd

markus5766h 15. Apr 2011 19:56

AW: Testen ob Popupmenu gerade angezeigt wird?
 
Hallo,

falls Du bei Deinen Objekten das Ereignis 'MouseDown' oder 'OnClick' nutzen kannst :

eine Variable (Boolean) bei Popup.OnPopup auf True setzen und bei z.B. MouseDown Deiner
Objekte nach der Auswertung (Selektionsaufhebung . . .) wieder auf False setzen.

. . . wäre zuzmindest mein erster Ansatz

Namenloser 15. Apr 2011 19:59

AW: Testen ob Popupmenu gerade angezeigt wird?
 
@himitsu: Das ist das Problem: Es gibt anscheinend auch kein Ereignis beim Schließen.
@beide
Außerdem erscheint mir eine solche Lösung unsauber, weil es ja mehr als einen Weg gibt, ein Popupmenü zu schließen. Der Klick soll aber nur dann „ignoriert“ werden, wenn er selbst zum Schließen des Menüs führt.

himitsu 15. Apr 2011 20:01

AW: Testen ob Popupmenu gerade angezeigt wird?
 
Zitat:

Zitat von markus5766h (Beitrag 1095465)
. . . wäre zuzmindest mein erster Ansatz

Man schließe das Popup irgendwie anders (ESC drücken, Woanders hinklicken oder einen Eintrag auswählen) und klicke dann irgendwann später auf seine "Fläche" ... schwupps, der erste Klick wird erstmal ignoriert.

Namenloser 15. Apr 2011 20:07

AW: Testen ob Popupmenu gerade angezeigt wird?
 
Okay, ich habe jetzt diesen Thread hier gefunden: Prüfen, ob ein Popupmenü geöffnet ist
Bin aber noch nicht sicher, ob mir das weiterhilft...

stahli 15. Apr 2011 20:15

AW: Testen ob Popupmenu gerade angezeigt wird?
 
Schau mal, ob Dir hier etwas hilft...

markus5766h 15. Apr 2011 20:18

AW: Testen ob Popupmenu gerade angezeigt wird?
 
Zitat:

Zitat von NamenLozer (Beitrag 1095474)
Okay, ich habe jetzt diesen Thread hier gefunden: Prüfen, ob ein Popupmenü geöffnet ist
Bin aber noch nicht sicher, ob mir das weiterhilft...

funzt :!:

Namenloser 15. Apr 2011 20:21

AW: Testen ob Popupmenu gerade angezeigt wird?
 
Zitat:

Zitat von markus5766h (Beitrag 1095478)
Zitat:

Zitat von NamenLozer (Beitrag 1095474)
Okay, ich habe jetzt diesen Thread hier gefunden: Prüfen, ob ein Popupmenü geöffnet ist
Bin aber noch nicht sicher, ob mir das weiterhilft...

funzt :!:

Das bezweifele ich gar nicht, die Frage ist nur, ob ich das für mein Szenario zurechtbiegen kann. Leider hatte himitsu anscheinend mit seiner Vermutung recht, dass das Popupmenu bereits verschwindet, bevor das OnMouseDown ausgelöst wird.

@stahli: Sieht ganz interessant aus, aber ich glaube die Lösung mit der Extra-Unit (s.o.) ist sauberer.

markus5766h 15. Apr 2011 20:38

AW: Testen ob Popupmenu gerade angezeigt wird?
 
O.K.

wenn ich nun nicht prüfen kann (jedenfalls nicht so einfach), ob ein Popup-Menü geschlossen wurde - dann doch zumindest, ob vorher eines geöffnet wurde . . .
oder mach' ich da jetzt einen Denkfehler ?

Code:
    uses . . ., ExPopupList;

    Pop : Boolean;
    procedure CMMenuClosed(var Msg: TMessage ); message CM_MENUCLOSED;
    procedure CM_ENTERMENULOOP(var Msg: TMessage ); message CM_ENTERMENULOOP;



procedure TForm1.CMMenuClosed(var msg: TMessage);
begin
  // nothing
end;

procedure TForm1.CM_ENTERMENULOOP(var Msg: TMessage);
begin
  Pop := True;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Pop := False;
end;

procedure TForm1.Panel2Click(Sender: TObject);
begin
  if Pop
    then ShowMessage('Popup') else ShowMessage('No Popup');
  Pop := False;
end;
das Schließen des Popups über ENTER oder ESCAPE müsste dann noch per
OnKeyDown ausgewertet werden.

Code:
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
 if (Key = VK_Return) or (Key = VK_Escape) then Pop := True;
end;

Namenloser 15. Apr 2011 21:00

AW: Testen ob Popupmenu gerade angezeigt wird?
 
Zitat:

Zitat von markus5766h (Beitrag 1095488)
oder mach' ich da jetzt einen Denkfehler ?

Ja, siehe Post #5 von himitsu.

markus5766h 15. Apr 2011 21:10

AW: Testen ob Popupmenu gerade angezeigt wird?
 
Liste der Anhänge anzeigen (Anzahl: 1)
So hab ich aber immer noch den Status (Variable Pop), ob das Popup-Menü vor dem
Klick auf das Control (hier Panel) geöffnet wurde, egal, ob ich zwischenzeitlich per ESC
oder Klick auf z.B. den Desktop das Popup-Menü schließe.?

Namenloser 15. Apr 2011 21:35

AW: Testen ob Popupmenu gerade angezeigt wird?
 
Danke für dein Beispiel, aber wenn man einen Rechtsklick auf Panel1 macht, dann einen Linksklick auf das Formular und anschließend einen Linksklick auf Panel1, kommt die Meldung „Popup“. Und genau das soll sie in dem Fall eben nicht – das ist es, was ich meine.

Sie soll nur dann erscheinen, wenn unmittelbar vor dem Klick das Popupmenü geöffnet war.

himitsu 15. Apr 2011 22:08

AW: Testen ob Popupmenu gerade angezeigt wird?
 
Du könntest über GetTickCount den Unterschied zwieschen den Aktionen bestimmen.

markus5766h 15. Apr 2011 22:28

AW: Testen ob Popupmenu gerade angezeigt wird?
 
Liste der Anhänge anzeigen (Anzahl: 1)
O.K., hab die Form jetzt noch in die Abfrage mit eingebunden,
wenn allerdings noch weitere Objekte hinzukommen,
die nicht zu den selektierten gehören (Buttons . . .) - und davon gehe ich mal aus -
wird diese Art der Abfrage nicht sonderlich glücklich enden.
. . . ich denk' noch mal drüber nach . . .

blauweiss 15. Apr 2011 22:51

AW: Testen ob Popupmenu gerade angezeigt wird?
 
Hallo Philip,

meiner Meinung nach ist der Vorschlag von Stahli / Marabu / Jens Schumann doch irgendwie der einfachere Weg ?! Setze ich übrigens auch so ein, also in der Art:

Delphi-Quellcode:
procedure TfMyForm.ApplicationEventsIdle(Sender: TObject; var Done: Boolean);
begin
  popupshown := false;
end;

procedure TfMyForm.PopUpMenuPopup(Sender: TObject);
begin
  popupshown := true;
end;

Im MouseDown Deiner Fläche dann einfach noch
Delphi-Quellcode:
if popupshown then
  exit;

Gruß,
blauweiss

EWeiss 15. Apr 2011 22:56

AW: Testen ob Popupmenu gerade angezeigt wird?
 
Hmm ...
Weis nicht ob ich jetzt falsch liege.
Aber ich kann jederzeit feststellen ob mein Popupmenu geöffnet ist oder war.
Muss dazu nur ne globale Variable anlegen mit der man gegenprüfen kann.

Allerdings nonvcl.

Delphi-Quellcode:
    WM_NCRBUTTONDOWN:
    begin
      hPopupMenu := CreatePopupMenu;  // Bitmap Popupmenu
      hSubSkinMenu := CreatePopupMenu; // Bitmap SkinSubmenu
      if hPopupMenu <> 0 then
      begin
        AppendMenu(hPopupMenu, MF_OWNERDRAW, IDM_ABOUT,    '');
        AppendMenu(hPopupMenu, {MF_OWNERDRAW or} MF_SEPARATOR, IDM_Seperator, '');
        AppendMenu(hPopupMenu, MF_OWNERDRAW or MF_POPUP, hSubSkinMenu, 'Skins');

        MnuSkins := nil;
        Files := nil;
        FindAllFiles(ExtractFilePath(ParamStr(0)) + 'Skins', '.ske', True);
        SetLength(MnuSkins, length(Files));
        for IntI := 0 to length(Files) - 1 do
          AppendMenu(hSubSkinMenu, MF_OWNERDRAW, IDM_SKINS + IntI,  '');

        AppendMenu(hPopupMenu, {MF_OWNERDRAW or} MF_SEPARATOR, IDM_Seperator, '');
        AppendMenu(hPopupMenu, MF_OWNERDRAW, IDM_Close,          '');
        GetCursorPos(p);
        MenuWahl := TrackPopupMenuEx(hPopupMenu, TPM_RETURNCMD, p.X, p.Y, WinHandle, nil);
        DestroyMenu(hPopupMenu);
        if MenuWahl then
          SendMessage(WinHandle, WM_COMMAND, Makelong(Word(MenuWahl), 0), 0);
      end;
    end;
Da wo ich mein CreatePopupMenu erstelle kann ich den Status auch abfragen oder?

gruss

Namenloser 15. Apr 2011 22:57

AW: Testen ob Popupmenu gerade angezeigt wird?
 
Das war zunächst auch mein Plan, nur leider funktioniert das nicht, weil (auch mit OnIdle)
Delphi-Quellcode:
popupshown := false;
immer vor dem MouseDown/MouseUp/Click-Event ausgeführt wird :(

Bin gerade etwas ratlos... es muss doch irgendeine bessere Lösung als ein Timeout (GetTickCount) geben :|

@EWeiss: Schau ich mir gleich mal an.
[edit]
Ok, meine WinAPI-Kenntnisse sind zu begrenzt, um zu beurteilen, ob mir dein Code weiterhilft. Herauszufinden, wann das Popup zerstört wird, ist inzwischen aber nicht mehr das Problem. Das Problem ist vielmehr herauszufinden, ob ein MouseDown/MouseUp/Click-Event eine Folge der Zerstörung des Popups ist.
[/edit]

blauweiss 15. Apr 2011 23:12

AW: Testen ob Popupmenu gerade angezeigt wird?
 
Zitat:

Zitat von NamenLozer (Beitrag 1095506)
Das war zunächst auch mein Plan, nur leider funktioniert das nicht, weil (auch mit OnIdle)
Delphi-Quellcode:
popupshown := false;
immer vor dem MouseDown/MouseUp/Click-Event ausgeführt wird :(

Ok, schade, dann hilft es Dir wohl nicht.
Bin gerade in Delphi5, da ist es nicht wie in Deinem (Turbo)Delphi
-> MouseDown (auf Panel oder ListBox) wird vor OnIdle aufgerufen...!

Gruß,
blauweiss

Namenloser 15. Apr 2011 23:24

AW: Testen ob Popupmenu gerade angezeigt wird?
 
Tatsache: MouseDown wird vorher aufgerufen, aber MouseUp später. Macht ja eigentlich auch Sinn.

Hab’s jetzt so gelöst:

Delphi-Quellcode:
  TfrmMain = class(TForm)
    {…}
  private
    FPopupActive,
    FPreventMouseUp: Boolean;
    procedure EnterMenuLoop(var Msg); message CM_ENTERMENULOOP;
  public
    {…}
  end;

procedure TfrmMain.EnterMenuLoop(var Msg);
begin
  FPopupActive := True;
end;

procedure TfrmMain.ApplicationEventsIdle(Sender: TObject; var Done: Boolean);
begin
  FPopupActive := false;
end;

procedure TfrmMain.PaintBoxMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if FPopupActive then
  begin
    FPreventMouseUp := True;
    exit;
  end;
  {…}
end;

procedure TfrmMain.PaintBoxMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if FPreventMouseUp then
  begin
    FPreventMouseUp := False;
    exit;
  end;
  {…}
end;
Vielleicht sollte man noch eine Kontrolle einführen, ob MouseDown und MouseUp sich auf den gleichen MouseButton beziehen, aber vielleicht ist das auch schon wieder Overkill.

So funktioniert es jedenfalls erstmal.

Danke euch allen :thumb:

EWeiss 15. Apr 2011 23:31

AW: Testen ob Popupmenu gerade angezeigt wird?
 
Ah jo das hättest du auch schon hier sehen können ;)
WM_NCRBUTTONDOWN:

Würde nie ein popup in WM_NCRBUTTONUP: erstellen.

gruss

Namenloser 15. Apr 2011 23:35

AW: Testen ob Popupmenu gerade angezeigt wird?
 
Zitat:

Zitat von EWeiss (Beitrag 1095511)
Ah jo das hättest du auch schon hier sehen können ;)
WM_NCRBUTTONDOWN:

Würde nie ein popup in WM_NCRBUTTONUP: erstellen.

gruss

Tu ich, bzw. die VCL auch nicht. Darum geht es auch nicht. Aber im MouseUp-Event wird bei mir die Selektion in meinem Programm zurückgesetzt; und diesen Nebeneffekt beim Schließen eines Popupmenüs wollte ich verhindern, was ja jetzt auch geglückt ist.

EWeiss 15. Apr 2011 23:36

AW: Testen ob Popupmenu gerade angezeigt wird?
 
Zitat:

Zitat von NamenLozer (Beitrag 1095512)
Zitat:

Zitat von EWeiss (Beitrag 1095511)
Ah jo das hättest du auch schon hier sehen können ;)
WM_NCRBUTTONDOWN:

Würde nie ein popup in WM_NCRBUTTONUP: erstellen.

gruss

Tu ich, bzw. die VCL auch nicht. Darum geht es auch nicht. Aber im MouseUp-Event wird bei mir die Selektion in meinem Programm zurückgesetzt; und diesen Nebeneffekt beim Schließen eines Popupmenüs wollte ich verhindern, was ja jetzt auch geglückt ist.

Das freut mich für dich ;)

gruss


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:01 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz