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/)
-   -   Das Problem mit MouseOver-Effekt (https://www.delphipraxis.net/172802-das-problem-mit-mouseover-effekt.html)

Popov 23. Jan 2013 15:01

Das Problem mit MouseOver-Effekt
 
Ich entwickle nur selten Komponenten. Vielleicht ist das Problem also überhaupt nicht der Rede wert und allgemein bekannt, nur ich komme nicht drauf.

Es ist das Problem mit MouseOver-Effekt. Es klappt nicht so wie ich es mir denke. Ich habe hier drei Methoden. Die erste ist die einzig wahre Methode, die funktioniert aber nicht so richtig. Zumindest nicht wie ich es brauche. Die anderen zwei sind getrickst, aber funktionieren.

Eines vorweg, es geht hier nicht um Panel, es ist nur für das Beispiel, mir geht es allgemein um andere Komponenten. Also bitte nicht auf Panel versteifen.

Beispiel mit MouseEnter und MoseLave Messages:

Delphi-Quellcode:
  TPanel2 = class(TPanel)
    procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
    procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
  end;

implementation

procedure TPanel2.CMMouseEnter(var Message: TMessage);
begin
  Color := clGreen;
end;

procedure TPanel2.CMMouseLeave(var Message: TMessage);
begin
  Color := clRed;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  Panel: TPanel2;
begin
  Panel := TPanel2.Create(Self); //hier wird das Panel zur Laufzeit erzeugt
  Panel.Parent := Self;
  Panel.Align := alClient;
end;
Es ist zwar eine auf das notwendigste verkürzte Version, aber das wesentliche ist drinn. Nur funktioniert es nicht so wie ich mir das vorstelle, denn auch wenn auf beide Ereignisse reagiert wird (Mauszeiger rein und raus), es funktioniert nicht, wenn der Mauszeiger zu schnell ist. Bewege ich den Mauszeiger ruckartig aus dem Formular, wird nicht reagiert. Es funktioniert also nur wenn der Mauszeiger beim Verlassen des Panels das Formular berührt. In der Form ist es für mich unbrauchbar, da hier immer klar sein muss wenn dier Mauszeiger draußen ist.

Eine andere Methode die ich mal entwickelt habe ist die mit dem Timer:

Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
begin
  Panel1.Align := alClient;
  Timer1.Interval := 50;
  Timer1.Enabled := False;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
  P: TPoint;
  R: TRect;
  H: THandle;
begin
  with Panel1 do
  begin
    if Boolean(GetCursorPos(P)) then
    begin
      H := WindowFromPoint(P);
      GetWindowRect(H, R);

      if PtInRect(R, P) and (H = Handle)then
        Color := clRed else
      begin
        Color := clGreen;
        Timer1.Enabled := False;
      end;
    end;
  end;
end;

procedure TForm1.Panel1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  Timer1.Enabled := True;
end;
Funktioniert eigentlich sehr gut, bis auf, dass es nicht elegant ist, und etwas aufwendig.

Zuletzt eine dritte Methode (die bin ich noch am entwickeln):

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

procedure TForm1.Panel1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
  R: TRect;
  P: TPoint;
begin
  with Panel1 do
  begin
    GetWindowRect(Handle, R);
    P := ClientToScreen(Point(X, Y));

    if GetCapture = 0 then
      SetCapture(Handle);

    if PtInRect(R, P) and (WindowFromPoint(P) = Handle) then
      Color := clGreen;
    else
    begin
      Color := clRed;
      ReleaseCapture;
    end;
  end;
end;
Funktioniert eigentlich auch sehr gut, bis auf, dass, ich vor Monaten, als ich es entwickelt habe, am Beispiel den Vermerk angebracht habe, dass es u. U. Probleme bereitet (ich kann mich aber nicht erinnern wo und was), und das man dazu ein Handle der Komponente braucht.

So, und nun mein Problem - die beiden letzten Beispiele sind getrickst, funktionieren aber wie ich es brauche. Es wird auch dann erkannt, dass der Zeiger sich außerhalb der Komponente befindet, wenn er außerhalb des Formulars ist. Das erste Beispiel soll wohl das einzig wahre sein, funktioniert aber nicht perfekt. Ich würde also gerne die erste Methode nutzen, aber ich hab keine Ideen wie ich es an meine Bedürfnisse anpassen kann.

Hat irgendwer Ideen?

stahli 23. Jan 2013 16:20

AW: Das Problem mit MouseOver-Effekt
 
Ich denke, besser wirst Du es nicht lösen können.
Evtl. könnte man auf Mausereignisse im Application-Objekt reagieren und dann die Mauspostion prüfen. Aber das käme letztlich auf´s gleiche raus.

Olli73 23. Jan 2013 16:25

AW: Das Problem mit MouseOver-Effekt
 
Zitat:

Zitat von Popov (Beitrag 1200270)
es funktioniert nicht, wenn der Mauszeiger zu schnell ist. Bewege ich den Mauszeiger ruckartig aus dem Formular, wird nicht reagiert. Es funktioniert also nur wenn der Mauszeiger beim Verlassen des Panels das Formular berührt.

Ich habe das mal unter W8 und XE3 getestet und keine Probleme festgestellt. Vielleicht bin ich aber auch nur zu langsam?

Hatte allerdings ein anderes Problem: Die Farbe des Panels kann ich nicht setzen; habe dafür dann halt die Caption geändert.

RSE 30. Jan 2013 12:08

AW: Das Problem mit MouseOver-Effekt
 
Ungetestete Idee: Was passiert, wenn du in der ersten Methode noch OnMouseLeave des Formulars mit einbeziehst? Das ist zwar für die Komponente evtl. nur schwerlich umsetzbar, wäre aber testweise sicherlich interessant.

CCRDude 30. Jan 2013 12:47

AW: Das Problem mit MouseOver-Effekt
 
Die Probleme mit ersterer Methode kann ich bestätigen, "massiver" werden die, wenn man andere Kompontenten abhängig von der Maus sichtbar/unsichtbar schaltet oder in der Größe verändert.

Ich weiß allerdings nicht, warum die das einzig wahre sein soll, oder warum nur eine einzige Methode "die" wahre Methode sein soll ;)

Anstelle des Timers habe ich schonmal das OnIdle der Application verwendet, und halt die Events des Formulares. Also halte ich Varianten 2 und 3 prinzipiell auch nicht für total verkehrt.

Übrigens: anstelle der Zuweisung (hier an Color) würde ich den aktuellen Status erst überprüfen, das vermeidet ggfls. überflüssiges Neugezeichne.


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:20 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