Gibt es eine "globale Message" um ein Popup zu schließen

Rund um die LCL und andere Komponenten
Antworten
cle
Beiträge: 30
Registriert: Mi 31. Jan 2018, 11:54
OS, Lazarus, FPC: Winux (L trunc FPC 3.3.1)
CPU-Target: 64Bit

Gibt es eine "globale Message" um ein Popup zu schließen

Beitrag von cle »

Moin,

ich habe eine Art von PopUp-Info kreiert, also einfach nur ein TPanel, das sichtbar wird, wenn man auf einer Schaltfläche einer rechten (nicht politisch) Mausklick ausführt. Das Panel kann ich natürlich auch wieder verschwinden lassen, durch einen erneuten Mausklick oder durch eine Auswahl auf dem Panel.
Wie aber kann ich darauf reagieren, wenn der User sonstwo hinklickt? Woher bekommen TMainMenu und TPopupMenu in solchen Fällen die Nachricht geschickt, sich wieder zu schließen? Und wie kann ich das in meinem Programm verwenden? Die onClick Ereignisse von allen verbauten Komponenten auszuwerten erschient mir etwas aufwenig.

Besten Dank
Alex

hubblec4
Beiträge: 245
Registriert: Sa 25. Jan 2014, 17:50

Re: Gibt es eine "globale Message" um ein Popup zu schließen

Beitrag von hubblec4 »

Hi

Ich hatte soetwas damals für mein erstes Projekt(Terminplaner) realisieren müssen.
Jede Menge Panles mit unterschiedlichen Sachen, die aufpopen wenn sie benötigt werden.

Wie das genau das TMainMenu macht weis ich auch nicht.

Ich habe es so gelöst das im Panel im onExit-Event ein Panel.visible steht.
Sobald man nun eine andere Komponente auf der Form anklick, bekommt diese den Focus, und das Panel verschwindet.

cle
Beiträge: 30
Registriert: Mi 31. Jan 2018, 11:54
OS, Lazarus, FPC: Winux (L trunc FPC 3.3.1)
CPU-Target: 64Bit

Re: Gibt es eine "globale Message" um ein Popup zu schließen

Beitrag von cle »

Hm, hört sich auf den ersten Blick plausibel an, funzt bei mir aber nicht.
Ich habe zur Kontrolle mal ein neues Projekt erstellt, ein TPanel und ein TMemo draufgezogen und im onEnter on onExit Event des Panels jeweils die Ausgabe einer Zeile im Memo eingetragen.
Passiert bei beiden nüscht.
onMouseEnter und -Exit funktionieren, die bringen hier aber nix.
Kann man ein TPanel überhaupt "entern" und wieder verlassen?
Wenn es bei dir funktioniert, wo stehe ich dann auf dem Schlauch?

Jedenfals danke für die Antwort.

wp_xyz
Beiträge: 3249
Registriert: Fr 8. Apr 2011, 09:01

Re: Gibt es eine "globale Message" um ein Popup zu schließen

Beitrag von wp_xyz »

Also ich weiß konkret nicht, wie's geht. Aber du solltest dir mal den Quellcode der TEditButton-Komponente und ihrer Nachfahren ansehen - da ist genau das gelöst. Beim TimeEdit zum Beispiel ist das Popup ein simples Formular, allerdings mit einem speziellen OnDeactivate-Handler:

Code: Alles auswählen

procedure TTimePopupForm.FormDeactivate(Sender: TObject);
begin
  //Immediately hide the form, otherwise it stays visible while e.g. user is draging
  //another form (Issue 0028441)
  Hide;
  if (not FClosed) then
    Close;
endM

Möglicherweise ist das schon die Lösung.

cle
Beiträge: 30
Registriert: Mi 31. Jan 2018, 11:54
OS, Lazarus, FPC: Winux (L trunc FPC 3.3.1)
CPU-Target: 64Bit

Re: Gibt es eine "globale Message" um ein Popup zu schließen

Beitrag von cle »

Gut vielen Dank, das werde ich mir mal anschauen.

Es gibt wohl so etwas wie eine PopupList, zumindest unter Delphi. Da bin ich aber nicht weiter gekommen.

kupferstecher
Beiträge: 269
Registriert: Do 17. Nov 2016, 11:52

Re: Gibt es eine "globale Message" um ein Popup zu schließen

Beitrag von kupferstecher »

Das Panel muss ja erstmal den Focus haben um ihn verlieren zu koennen. Ich wuerde es mal mit Panel.SetFocus beim Anzeigen des Popups versuchen. Wenn das Panel keinen Focus annehmen kann, gibts sicher Moeglichkeiten, das zu aendern.

cle
Beiträge: 30
Registriert: Mi 31. Jan 2018, 11:54
OS, Lazarus, FPC: Winux (L trunc FPC 3.3.1)
CPU-Target: 64Bit

Re: Gibt es eine "globale Message" um ein Popup zu schließen

Beitrag von cle »

Naja, eigentlich ist es schon komisch, dass ein Panel ein onEnter/onExit Event haben kann. Bei einem TEdit ist die Sache klar. Aber wann soll das bei einem Panel stattfinden? Wenn man drauf klickt? Das wäre onClick. In Prinzip ist es mit dem SetFocus genauso. Wann hat ein Panel den Focus? Hat übrigens bei einem schnellen Test nicht funktioniert.
Ich dachte wirklich, dass es da eine einfache Möglichkeit gibt, da der Fall ja nicht so selten auftaucht, wie man am Beitrag von hubblec4 sieht.
Wenn ich am WE dazu komme, werde ich mir den Vorschlag von wp_xyz genauer ansehen.

Warf
Beiträge: 1421
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: MacOS | Win 10 | Linux
CPU-Target: x86_64
Wohnort: Aachen

Re: Gibt es eine "globale Message" um ein Popup zu schließen

Beitrag von Warf »

cle hat geschrieben:Naja, eigentlich ist es schon komisch, dass ein Panel ein onEnter/onExit Event haben kann. Bei einem TEdit ist die Sache klar. Aber wann soll das bei einem Panel stattfinden? Wenn man drauf klickt? Das wäre onClick. In Prinzip ist es mit dem SetFocus genauso. Wann hat ein Panel den Focus? Hat übrigens bei einem schnellen Test nicht funktioniert.


z.b. Wenn man Panel.SetFocus aufruft

Der grund dafür ist wahrscheinlich weil ein panel ein WinControl ist, was den Fokus haben kann. Die gründe dafür stecken wahrscheinlich irgendwo in der grundstrutkur der Windows API, von der sich Delphi abgeleitet hat und zu dem die LCL kompatibel ist.
Das heist aber nicht das es nicht trozdem nützlich sein kann. Ich hab schon öfters mal wenn ich nen eigens designten button haben wollte einfach ein Panel genommen und mit dem Canvas ein bisschen drauf rumgemalt. Geht einfach und schnell, und da es ein TWinControl ist wie ein button, kann man sehr viel LCL funktionalität nutzen um einen button zu emulieren. Manchmal will man nicht eine neue komponente erstellen die man erst in Lazarus linken muss nur um einen einzigen button schön zu machen

kupferstecher
Beiträge: 269
Registriert: Do 17. Nov 2016, 11:52

Re: Gibt es eine "globale Message" um ein Popup zu schließen

Beitrag von kupferstecher »

Hab das mal kurz probiert, das geht schon. Problem ist, beim Click in den Hintergrund muss das Panel den Fokus auch wieder verlieren, sonst gibts kein OnExit-Event.
Die Form nimmt scheinbar keinen Focus an. Ich hab mal ein 'PanelForm' in den Hintergrund gelegt, die sich bei Click den Fokus gibt. So würde es gehen, ist aber natürlich nicht gerade schön. Code unten.

Was noch gehen könnte, ist das Popup-Element als eigene Form anlegen, dann dürfte das OnEnter/OnExit tatsächlich bei jedem Klick auftreten. Ist aber wieder ein Aufwand.



Code: Alles auswählen

procedure TForm1.Panel1Click(Sender: TObject);
begin
  Panel1.SetFocus;
end;
 
procedure TForm1.Button1Click(Sender: TObject);
begin
  Panel1.Show;
  Panel1.SetFocus;
end;
 
 
procedure TForm1.Panel1Enter(Sender: TObject);
begin
  Writeln('Panel1Enter');
end;
 
procedure TForm1.Panel1Exit(Sender: TObject);
begin
  Writeln('Panel1Exit');
  Panel1.Hide;
end;
 
procedure TForm1.PanelFormClick(Sender: TObject);
begin
  PanelForm.SetFocus;
end;

cle
Beiträge: 30
Registriert: Mi 31. Jan 2018, 11:54
OS, Lazarus, FPC: Winux (L trunc FPC 3.3.1)
CPU-Target: 64Bit

Re: Gibt es eine "globale Message" um ein Popup zu schließen

Beitrag von cle »

Warf hat geschrieben:Das heist aber nicht das es nicht trozdem nützlich sein kann.

Natürlich nicht, wahrscheinlich mit die nützlichste Komponente, von Container, Abstandshalter, Button, wie hier Menü und MenuItem etc.

@kupferstecher
Das mit dem 'PanelForm' hab ich nicht verstanden. Meinst du ein Panel über die ganze Form ziehen?
(...Momente des Nachdenkens...) Ah, okay, doch ich glaube jetzt klickt es langsam. Hm, in der Tat nicht sehr elegant.
Es müsste "einfach" analog zum KeyPreview ein ClickPreview geben ...

cle
Beiträge: 30
Registriert: Mi 31. Jan 2018, 11:54
OS, Lazarus, FPC: Winux (L trunc FPC 3.3.1)
CPU-Target: 64Bit

Re: Gibt es eine "globale Message" um ein Popup zu schließen

Beitrag von cle »

Also, ausgehend von kupferstechers Idee, habe ich mal versucht ein durchsichtiges shape über das Formular zu ziehen:

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
begin
  Shape1.Show;
  Shape1.Align := alClient;
  Panel1.Show;
  Shape1.BringToFront;
  Panel1.BringToFront;
end;
 
procedure TForm1.Shape1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  Panel1.Hide;
  Shape1.Hide;
end;             


Das funktioniert auf den ersten Blick ganz gut, bis auf die (nicht unwichtige) Tatsache, dass man ein shape scheinbar nicht in den Vordergrund bringen kann. D.h. alles, was sich sonst noch auf dem Fomular befindet, ist weiter anwählbar.
Also nix mit MacGyver-Programmierung.

kupferstecher
Beiträge: 269
Registriert: Do 17. Nov 2016, 11:52

Re: Gibt es eine "globale Message" um ein Popup zu schließen

Beitrag von kupferstecher »

cle hat geschrieben:Das funktioniert auf den ersten Blick ganz gut, bis auf die (nicht unwichtige) Tatsache, dass man ein shape scheinbar nicht in den Vordergrund bringen kann.

Shapes sind von TGraphicControl abgeleitet und nicht von TWinControl. GraphicControls sind immer hinter WinControls (zumindest unter WIndows).
Von TWinControl abgeleitete kennen allerdings keine Transparenz...

Du könntest es höchstens noch mit einer Form versuchen.
Insbesondere wenn sie in einem eigenen Fenster ist, sollte OnExit bei jedem Klick funktionieren, also auch ohne die OnClick-Tricks.
TPopUpMenu funktioniert wohl in der Art.

cle
Beiträge: 30
Registriert: Mi 31. Jan 2018, 11:54
OS, Lazarus, FPC: Winux (L trunc FPC 3.3.1)
CPU-Target: 64Bit

Re: Gibt es eine "globale Message" um ein Popup zu schließen

Beitrag von cle »

kupferstecher hat geschrieben:GraphicControls sind immer hinter WinControls (zumindest unter WIndows).


Hier unter Linux eben auch.


Du könntest es höchstens noch mit einer Form versuchen.
Insbesondere wenn sie in einem eigenen Fenster ist, sollte OnExit bei jedem Klick funktionieren, also auch ohne die OnClick-Tricks.
TPopUpMenu funktioniert wohl in der Art.


Mit onDeactivate funzt es auf den ersten Blick problemlos. Wobei wir wieder dort sind, was wp_xyz vorgeschlagen hatte ;)
Scheint also die Lösung zu sein.
Nochmals Danke.

cle
Beiträge: 30
Registriert: Mi 31. Jan 2018, 11:54
OS, Lazarus, FPC: Winux (L trunc FPC 3.3.1)
CPU-Target: 64Bit

Re: Gibt es eine "globale Message" um ein Popup zu schließen

Beitrag von cle »

Nachtrag, da es wahrscheinlich der eine oder andere gebrauchen kann.
Zunächst hat sich die 'Lösung' mit dem Formular doch nicht als praktikabel herausgestellt. Wie kupferstecher schon festgestellt hatte, funktioniert das nur, wenn das Formular sich in einem eigenen Fenster befindet. Das hat zur Folge, dass das Hauptfenster dann natürlich deaktiviert wird, was die meisten Desktop-Umgebungen mit einem Farbwechsel der Fensterdekoration oder sogar mit einem Abdunkeln des Fensters signalisieren. Sieht beim Öffnen eines Popups natürlich bescheuert aus.

Da aber noch mehr Leute nach so etwas wie einem 'ClickPreview' gesucht haben, bin ich im englischen Lazarus-Forum fündig geworden.
Link
Hier mal der entscheidende Schnipsel aus dem Thread:

Code: Alles auswählen

uses
  ..., Forms, LMessages;
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  Application.AddOnUserInputHandler(@MouseHook);
end;
 
procedure TForm1.FormDestroy(Sender: TObject);
begin
  // To prevent possible system resource leaks
  Application.RemoveOnUserInputHandler(@MouseHook);
end;
 
procedure TForm1.MouseHook(Sender: TObject; Msg: Cardinal);
begin
   if (Msg <> LM_MOUSEMOVE) and (Msg <> LM_NCMOUSEMOVE) then Exit;
 
  // Do stuff
end;


Wenn ich Msg auf LM_LBUTTONUP prüfe (und da gibt es noch einen Haufen anderer Möglichkeiten) erreiche genau das, was ich in dem ThreadTitel gefragt hatte.
Unerwünschte Nebenwirkungen habe ich bisher nicht festgestellt.

[gelöst] passt nicht mehr vor den Titel

Antworten