Entwickler-Ecke

Windows API - Popup als Dropdown missbrauchen


LonghornUser - Fr 23.03.07 17:28
Titel: Popup als Dropdown missbrauchen
Hallo,

ich habe hier einen speziellen Button, der keine Dropdown-Funktion hat. Jetzt möchte ich, dass auf einem Linksklick ein PopupMenu genau unter dem Button erscheint.
Nun habe ich dafür ja nur die Funktion PopupMenu1.Popup(x,y), wobei x und y als Variablen für die gesamte Windows-Oberfläche stehen und nicht nur in der Form.
Da habe ich folgendes probiert: x := Form1.Left+Button1.Left+Button1.Width. Das geht auch aber bei y variiert das ja, je nachdem, welches Windows ich habe. Die Titelleiste jeder Form ist ja zB. in Win98 weniger hoch als in XP, wodurch ja der Top-Wert verfälscht würde. Dadurch wäre das Popup ja nicht exakt unter dem Button.
Hat jemand eine bessere Idee, das ganze zu machen ?

Danke schonmal.

Ciao LHUser


Lannes - Fr 23.03.07 23:20

Hallo,

da gibt es schöne Funktionen zum umrechnen.
ScreenToClient
ClientToScreen

Beispiel, der Button liegt auf einem Panel:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
procedure TForm1.Button1Click(Sender: TObject);
var aPoint : TPoint;
begin
  aPoint := Panel1.ClientToScreen(Point(Button1.Left,Button1.Top + Button1.Height));
  PopupMenu1.Popup(aPoint.x,aPoint.y);
end;


BenBE - Sa 24.03.07 00:08

Warum so umständlich: TButton kennt ClientToScreen ja auch :P


LonghornUser - Sa 24.03.07 00:18

Jo, funktioniert schon sehr schön.
Nur: Der Button ist auf transparent gesetzt und hat ein Hover-Event (sprich, er ändert sein Erscheinungsbild beim Drüberfahren mit der Maus). Wenn ich nun im Popup etwas anklicke, oder neben es klicke, um es wieder zu schließen. Leider verbleibt der Button im Zustand, als wäre die Maus drüber. Erst wenn ich per Hand noch mal mit der Maus drüber und wieder runter gehe, ist er wieder im Normalzustand.

Eine Idee, wie man das beheben könnte ?


Lannes - Sa 24.03.07 00:23

Hallo,

@user profile iconBenBe
Button.Left ist der Abstand zum linken Rand des Parent-Elements :P

Also gut, machen wir es universeller:

Delphi-Quelltext
1:
2:
3:
4:
5:
  with TButton(Sender) do
    begin
    aPoint := Parent.ClientToScreen(Point(Left,Top + Height));
    PopupMenu1.Popup(aPoint.x,aPoint.y);
    end;


Blackheart666 - Sa 24.03.07 00:24

button.refresh - repaint


BenBE - Sa 24.03.07 00:26

Das ist ein Problem bei der Behandlung der Events. Versuche das aufrufen des Popups mal Synchronized in einen separaten Thread auszulagern, wenn der Tipp von Blackbird, den ich grad eingeblendet bekommt :P nicht funzt. Ansonsten ruf die Methode zum Aufheben des Hovers einfach manuell nach dem öffnen des Popups auf.


LonghornUser - Sa 24.03.07 00:51

user profile iconBenBE hat folgendes geschrieben:
Versuche das aufrufen des Popups mal Synchronized in einen separaten Thread auszulagern, [...] Ansonsten ruf die Methode zum Aufheben des Hovers einfach manuell nach dem öffnen des Popups auf.


Wie würde ich das beides machen ?
Aber ich glaube auch, das würde nicht helfen, da ja meine Maus trotzdem nach dem Klick auf dem Button ist und somit das Hover-EVent wieder ausgelöst würde.

@Blackheart666: Das hatte ich auch gedacht, es klappt aber leider nicht. :(


BenBE - Sa 24.03.07 00:56

user profile iconLonghornUser hat folgendes geschrieben:
user profile iconBenBE hat folgendes geschrieben:
Versuche das aufrufen des Popups mal Synchronized in einen separaten Thread auszulagern, [...] Ansonsten ruf die Methode zum Aufheben des Hovers einfach manuell nach dem öffnen des Popups auf.


Wie würde ich das beides machen ?

Schau Dir einfach mal die ganzen Beispiele zu Suche in: Delphi-Forum, Delphi-Library TTHREAD hierim Forum an. Da gibt es einige u.a. auch mit Suche in: Delphi-Forum, Delphi-Library SYNCHRONIZE.

user profile iconLonghornUser hat folgendes geschrieben:
Aber ich glaube auch, das würde nicht helfen, da ja meine Maus trotzdem nach dem Klick auf dem Button ist und somit das Hover-EVent wieder ausgelöst würde.

Meist werden solche MouseIn\Out-Effekte über die Windows-Botschaften WM_MOUSEENTER und WM_MOUSELEAVE realisiert. Diese werden von Windows nur für den aktiven Control (in dem Falle das Popup-Menü) und nur wenn angefordert erzeugt. Im Einzelfall hilft das Konsultieren des Quelltexts der Komponente ;-)