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/)
-   -   Delphi Panel automatisch schließen (https://www.delphipraxis.net/138551-panel-automatisch-schliessen.html)

Roaster 12. Aug 2009 12:57


Panel automatisch schließen
 
Hi,

ich bastle gerade an einem neuen Control, dass im Wesentlichen aus einem Button besteht, der beim Klick darauf ein TPanel mit einer TTrackbar öffnet.

Das funktioniert bereits einwandfrei, nur möchte ich jetzt, dass dieses Panel wieder automatisch schließt, sobald ich bspw. mit der Maus die Größe des Hauptformulars ändere, oder einfach nur irgendwo mit der Maus hinklicke, und zwar nicht auf das Panel oder die TrackBar). Was natürlich bereits geht, ist das Schließen durch einen erneuten Klick auf den Button.

Im Prinzip ist es eigentlich das gleiche Verhalten, dass eine Standard ComboBox zeigt: Nachdem der Button angeklickt wurde, klappt die Liste auf und wieder zu, sobald man irgendwo ausserhalb des Controls/der Liste klickt.

In meinem Fall besteht das neue Control aber aus mehreren einzelnen, so dass bspw. die Nachricht WM_KILLFOCUS oder CM_FOCUSCHANGED hier nicht weiterhilft, zumindest verliert der Button ja bereits den Focus sobald das Panel angezeigt wird. Genau in diesem Fall macht es natürlich noch keinen Sinn das Panel wieder zu schließen.

Wie könnte man dies jetzt lösen?

guidok 12. Aug 2009 13:15

Re: Panel automatisch schließen
 
Das Panel hat doch ein Ereignis OnExit, das aufgerufen wird, wenn es den Fokus verliert (und das macht es, wenn du auf ein anderes Element klickst).

Roaster 13. Aug 2009 07:55

Re: Panel automatisch schließen
 
Hi,

du hast recht, dies funktioniert solang der User auf ein neues Control wie ein TEdit oder eine TCheckbox klickt. Es funktioniert hingegen nicht, wenn der User auf einen freien Platz im Formular klickt, oder die Größe des Formulars verändert.

Gibt's da auch etwas Entsprechendes dafür. WM_SIZE wird ja nur gesendet, wenn sich das Control, in meinem Fall der neue Button, in der Größe ändert, nicht aber, wenn das Formular in der Größe geändert wird.

xZise 13. Aug 2009 11:31

Re: Panel automatisch schließen
 
Naja dann kannst du doch gucken mit OnMouseDown/Up ob auf das Formular geklickt wurde?

MfG
xZise

Roaster 13. Aug 2009 11:38

Re: Panel automatisch schließen
 
Ja,

das könnte ich schon, allerdings regt sich da ein wenig Widerstand in mir, da diese Funktionalität ja das Control mitbringen und nicht vom Programmierer von ausserhalb des Controls gelöst werden soll.

Ich muss ja auch keine ComboBox manuell schließen,indem ich jedesmal nach einem Mausklick prüfe, ob es nicht das Control selbst war, zum Zeitpunkt des Mausklicks. Ich denke da muss es noch irgendetwas anderes geben.

OnExit funktioniert bereits in meinem neuen Control, lediglich für den Klick auf das Formular suche ich noch eine Lösung.

Edit: OnExit funktioniert für fast alle Standard Controls, wenn ich jedoch ein TUpDown Control noch auf's Formular lege und dann bei geöffnetem Panel auf das TUpDown klicke, dann wird komischerweise das OnExit Event nicht aufgerufen und logischerweise auch nicht das Panel geschlossen - sehr seltsam das Ganze.

Optiplex 14. Aug 2009 11:39

Re: Panel automatisch schließen
 
Hallo, ich weis nicht ob dir das hilft aber mit GetParentForm kann man auf das Formular zugreifen und eventuell die Ereignisse auf eigene Methoden umleiten. Weis allerdings nicht ob das so funktioniert, war nur so eine Idee.

Gruß
Dieter

Guido Eisenbeis 16. Aug 2009 00:53

Re: Panel automatisch schließen
 
Probier mal SetCapture.

Starthilfe:

Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
begin
  Panel1.Visible := false;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Panel1.Visible := true;
  SetCapture(Panel1.Handle);
end;

procedure TForm1.Panel1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  Pnt: TPoint;
  Rct: TRect;
begin
  GetCursorPos(Pnt);
  GetWindowRect(Panel1.Handle, Rct);
  if not PtInRect(Rct, Pnt) then
    Panel1.Visible := false
  else
    SetCapture(Panel1.Handle);
end;
Das ist nun zunächst mal ein Rundumschlag, der dir den systemweiten Mouseinput sichert, bis ein MouseUp oder -Down eintrifft. Den Feinschliff kannst du vielleicht mit PtInRect durchführen.

Guido.

Edit:
Beispiel-Code verbessert.

jaenicke 16. Aug 2009 03:45

Re: Panel automatisch schließen
 
SetCapture funktioniert aber nur solange der Benutzer in das angegebene Control geklickt hat und dann die Maus außerhalb zieht. Wenn die linke Maustaste nicht gedrückt bleibt, klappt das nicht... ;-)

Guido Eisenbeis 16. Aug 2009 03:55

Re: Panel automatisch schließen
 
Hallo Sebastian,

ich kann dir gerade nicht folgen. Hast du den Code oben getestet? Der Ablauf wurde von Roaster vorgegeben und funktioniert in meinem Beispiel oben (halt im Ansatz). Zum Starten wird der Button geklickt, dadurch wird das Beispiel-Panel angezeigt und erhält das nächste MouseEvent, egal wo geklickt wird.

Ich weiß jetzt nicht, wie du auf das Ziehen und Festhalten kommst. Oder hab ich was falsch verstanden.

Guido.

jaenicke 16. Aug 2009 03:59

Re: Panel automatisch schließen
 
Nein, ich habe den Code oben nicht getestet, aber SetCapture funktioniert so nicht. Hast du es getestet? Siehe Dokumentation:
Zitat:

SetCapture captures mouse input either when the mouse is over the capturing window, or when the mouse button was pressed while the mouse was over the capturing window and the button is still down. [...]

If the mouse cursor is over a window created by another thread, the system will direct mouse input to the specified window only if a mouse button is down.
Heißt: Zumindest, wenn man mit der Maus über ein anderes Programm geht, bekommt das Programm das Mausereignis nicht.

// EDIT:
Aber es funktioniert trotzdem. Tut mir leid, damit hatte ich nicht gerechnet. :gruebel:

Guido Eisenbeis 16. Aug 2009 04:06

Re: Panel automatisch schließen
 
Ich habe die Dokumentation gelesen und den Code getestet. Es funktioniert. Ich verstehe nicht, warum das nicht gehen soll.

Guido.


Edit:

Ups, hast es schon gemerkt. :wink:

jaenicke 16. Aug 2009 04:10

Re: Panel automatisch schließen
 
Ja, es geht, habe ich eben auch editiert. Der Punkt ist, dass ein MouseUp gesendet wird, wenn die Maus woanders gedrückt wird. Das heißt es ist nicht wie in der Dokumentation beschrieben, dass dann gar nichts gesendet wird, es wird nur kein MouseDown gesendet, sondern stattdessen ein MouseUp. :shock:

Guido Eisenbeis 16. Aug 2009 04:25

Re: Panel automatisch schließen
 
Zitat:

Zitat von jaenicke
es wird nur kein MouseDown gesendet, sondern stattdessen ein MouseUp. :shock:

Es ist genau umgekehrt. :wink: Ich habe gerade mal je ein ShowMessage in das Panle-MouseUp und -MouseDown gesetzt, und das MouseDown kommt an, das MouseUp wird "verschluckt". Das hängt daran, dass das MouseDown das Capturing releast.

Guido.

jaenicke 16. Aug 2009 04:28

Re: Panel automatisch schließen
 
Dann hast du das vermutlich unter einem anderen Betriebssystem getestet? Bei mir ist es Vista. Und da kam das MouseUp an als ich die Maustaste nur über einem fremden Fenster gedrückt habe. //EDIT: Und das MouseDown auch, stimmt. Beides kommt beim Drücken an.
XP habe ich nicht mehr direkt da, kann ich aber in einer VM einmal testen.
// EDIT:
Grade getan, dort ist es genauso. Von einem fremden Fenster kommt beides zugleich an. Dein ShowMessage verursacht, dass das bei dir nicht passiert, nehme ich an. ;-)

Guido Eisenbeis 16. Aug 2009 04:38

Re: Panel automatisch schließen
 
Rofl ... :oops: ShowMessage ist für solch einen Test natürlich ziemlich ungeeignet. *ablenk-und-pfeif*

Ich hab jetzt zum Testen (auf XP) eine ListBox genommen und siehe da, es kommen beide Events an (MouseUp und -Down). Wenn man jedoch, wie in deinem Test, auf ein fremdes Fenster klickt, werden die beiden Events so schnell gefeuert, dass man das nur mit ListBox...Add o. ä. mitkriegen kann.
Ich hoffe, dass Roaster jetzt überhaupt noch den Faden von SetCapture mitbekommt. :gruebel: Ansonsten gehen wir halt einen :cheers:

Guido.


Edit:
Verflixt, haben sich unsere Postings schon wieder überschnitten. :wall: Ich glaube, ich sollte mir mit dem Antworten mehr Zeit lassen, dann schreibst du von selbst alles, was ich auch sagen will. :-D


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:45 Uhr.

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