Autor Beitrag
Stefan S.
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 184


D5
BeitragVerfasst: Fr 05.01.07 21:11 
Hallo allerseits,
Ich habe in einem Programm Buttons mit Highlight-Effekt, d.h. ihre Farbe ändert sich, wenn man den Mauszeiger auf sie bewegt. Das mach ich ganz simpel mit OnMouseMove, nämlich hab ich den Befehl, der die Farbe ändert, beim OnMouseMove des jeweiligen Buttons und den Befehl, der sie zurücksetzt beim OnMouseMove von allen anderen Buttons und auch ganz anderen Objekten (wie z.B. der Form selber).
Damit ist es aber noch nicht getan, denn wenn man den Cursor sehr schnell an eine Stelle außerhalb des Formulars bewegt, bleibt das Highlight erhalten. Ich muss also auch abfragen, ob sich der Cursor außerhalb der Form befindet und in diesem Falle die Farbe zurücksetzen. Und da ist mein Problem: Wo bring ich diese Abfrage unter? In meiner Unerfahrenheit habe ich bisher einfach immer einen Timer mit Intervall '1' platziert, der quasi 1000 mal pro Sekunde abfrägt, ob der Cursor außerhalb der Form ist und das ganze funktioniert natürlich, aber diese Methode ist doch wohl sehr unschön und unprofessionell, schon allein, weil der Timer ja ständig Rechenleistung verbraucht (wenn auch bei den heutigen Systemen ein Timer mit einer Abfrage wahrscheinlich kaum was ausmacht).
Wo bringe ich die Abfrage am besten unter? In einer Prozedur, die ständig wiederholt ausgeführt wird? Oder gibt es ein Ereignis, das sich dafür eignet? Gibt es überhaupt einen besseren Weg, so ein Button-Highlight umzusetzen?

MfG,
Stefan
Jakob Schöttl
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 929
Erhaltene Danke: 1


Delphi 7 Professional
BeitragVerfasst: Sa 06.01.07 01:07 
Also, da gibts glaub ich was viel besseres als OnMouseMove!
Application.OnHint ist ein Ereignis, das sofort dann auftritt, wenn der Benutzer auf eine Komponente zeigt mit der Maus...

Wenn der Auslöser von OnHint = Form1, dann kannst du die Farbe des Buttons zurücksetzen, und wenn der Auslöser Button1 ist, dann kannst du die Farbe setzen.

Nimm dazu ein Objekt der Klasse TApplicationEvent.
Stefan S. Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 184


D5
BeitragVerfasst: Sa 06.01.07 01:15 
Ähm, mal blöd gefragt - was ist daran jetzt besser als an OnMouseMove? Einfacher wird es dadurch nicht und eigentlich ist OnHint für einen anderen Zweck gedacht:

Zitat:
Mit einer OnHint-Ereignisbehandlungsroutine können Sie Aktionen programmieren, die eingeleitet werden, wenn sich der Mauszeiger über einem Steuerelement befindet, dessen Eigenschaft Hint keinen Leerstring enthält.


Geholfen wäre mir zum Beispiel, wenn es für den Button ein Ereignis gäbe, was eintritt, wenn der Mauszeiger nicht auf ihn zeigt, dann könnte ich mir die Abfrage der Mauskoordinaten sparen. Aber sieht nicht so aus, als gäbe es so etwas.
Wie auch immer, es würde mich so oder so mal interessieren, wo man so eine Abfrage, die im Prinzip ständig wiederholt durchgeführt werden soll, am besten unterbringt.
Jakob Schöttl
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 929
Erhaltene Danke: 1


Delphi 7 Professional
BeitragVerfasst: Sa 06.01.07 01:21 
Eben! die ständige Abfrage kannst du dir sparen, wennd u OnHint nimmst! Wenn der Mauszeiger zum ersten mal wieder auf den Button zeigt, dann kannst du die Farbe ändern. Wenn er danach zum ersten mal wieder aufs Form zeigt, dann kannst du sie wieder auf leer ändern!

Das ist der Vorteil an onHint: das Ereignis wird nicht bei der Mausbewegung ausgelöst, sondern einmalig eben dann, wenn der Cursor auf das Steuerelement fährt.

und so viel ich weiß, wird es auch ausgelöst, wenn der Hint = '' ist. und es wird nicht verzögert ausgelöst, so wie der hint auch verzögert angezeigt wird...
wulfskin
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1349
Erhaltene Danke: 1

Win XP
D5 Pers (SSL), D2005 Pro, C, C#
BeitragVerfasst: Sa 06.01.07 01:27 
Hallo,

für diesen Zweck gibt es die beiden "Nachrichten" CM_MOUSEENTER und CM_MOUSELEAVE. Allerdings finde ich dazu nichts mehr in der API-Dokumentation, aber ich denke die gibt es immer noch.
Ein Beispiel findet man bei den Schweizern!

Gute Nacht,
Hape

_________________
Manche antworten um ihren Beitragszähler zu erhöhen, andere um zu Helfen.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19341
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Sa 06.01.07 01:50 
Ja, die gibt es noch... Und es gibt sogar OnMouseLeave beim Formular. ;-)

Das wird, wie der Name schon sagt, ausgelöst, wenn die Maus das Formular verlässt.
Bei extrem schnellen Mausbewegungen oder langsamen PCs wird es aber u.U. anscheinend nicht ausgelöst bzw. die Botschaften nicht gesendet. Oder die Anwendung verarbeitet die nicht korrekt.

Dieses Problem konnte man ja auch an der Delphi 7 IDE beobachten. Wenn man da schnell mit der Maus über die ToolButtons gegangen ist, dann blieben die aktiviert. Allerdings nur bei etwas langsameren PCs. (Oder war es nicht Delphi 7 sondern eine andere Version? Egal...)
Jakob Schöttl
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 929
Erhaltene Danke: 1


Delphi 7 Professional
BeitragVerfasst: Sa 06.01.07 13:38 
user profile iconwulfskin hat folgendes geschrieben:
Hallo,

für diesen Zweck gibt es die beiden "Nachrichten" CM_MOUSEENTER und CM_MOUSELEAVE. Allerdings finde ich dazu nichts mehr in der API-Dokumentation, aber ich denke die gibt es immer noch.
Ein Beispiel findet man bei den Schweizern!

Gute Nacht,
Hape


Aber da müsste man ja für jeden Hightlight-Button eine Klasse ableiten THighlightButton, weil wo soll man sonst die Nachrichten behandeln?
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19341
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Sa 06.01.07 13:42 
CM_MOUSEENTER und CM_MOUSELEAVE sind doch schon eingebaut...
In OnMouseEnter und OnMouseLeave.
(Delphi 2006)
// EDIT: Ich seh grad, bei Delphi 7 und früher nicht.
Ja, da muss man dann eine abgeleitete Klasse erstellen...

// EDIT2:
user profile iconJakob Schöttl hat folgendes geschrieben:
Aber da müsste man ja für jeden Hightlight-Button eine Klasse ableiten THighlightButton, weil wo soll man sonst die Nachrichten behandeln?

Wie für jeden? Einmal reicht ja.
Jakob Schöttl
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 929
Erhaltene Danke: 1


Delphi 7 Professional
BeitragVerfasst: Sa 06.01.07 14:12 
user profile iconjaenicke hat folgendes geschrieben:
user profile iconJakob Schöttl hat folgendes geschrieben:
Aber da müsste man ja für jeden Hightlight-Button eine Klasse ableiten THighlightButton, weil wo soll man sonst die Nachrichten behandeln?

Wie für jeden? Einmal reicht ja.


Ja, klar reicht einmal, hab mich schlecht ausgedrückt!
Stefan S. Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 184


D5
BeitragVerfasst: Sa 06.01.07 16:31 
user profile iconjaenicke hat folgendes geschrieben:
Ja, die gibt es noch... Und es gibt sogar OnMouseLeave beim Formular. ;-)


Ich arbeite mit Delphi 5 und da gibt es kein "OnMouseLeave". Aber wenn es da bei langsameren PCs zu Ungenauigkeiten kommt, ist das eh nix für mich.

@jaenicke: Ehrlich gesagt versteh ich da rein gar nichts. Wenn ich den Code aus dem Beispiel einfach in ein neues Beispielprojekt kopiere, wird mir gemeldet, dass die Deklaration von Form1 fehlt. Zu CM_MOUSEENTER und CM_MOUSELEAVE hab ich weder in der Delphi Hilfe noch bei Windows SDK etwas gefunden. Könntest du es mal genauer erklären oder einen entsprechenden Code posten?
wulfskin
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1349
Erhaltene Danke: 1

Win XP
D5 Pers (SSL), D2005 Pro, C, C#
BeitragVerfasst: Sa 06.01.07 16:32 
Hallo,

was spricht denn dagegen, dass Beispiel bei den Schweizern einfach einmal auszuprobieren?

Gruß Hape!

_________________
Manche antworten um ihren Beitragszähler zu erhöhen, andere um zu Helfen.
Lannes
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2352
Erhaltene Danke: 4

Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
BeitragVerfasst: Sa 06.01.07 16:41 
Hallo,

man muss nicht unbedingt eine Klasse ableiten,
hier mal ein Beispiel mit mehreren Labels, funktioniert auch mit D3.
Zum Testen, ein paar Labels auf die Form setzen und den Code übernehmen:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, StdCtrls, ComCtrls;
//************* bei Delphi 3 erforderlich 
type
  TCMMOUSEENTER = record
    Msg : Cardinal;
    Unused : Integer;
    Sender : TControl;
    Result : Longint;
  end;
  TCMMOUSELEAVE = TCMMOUSEENTER;
//************* 
type
  TForm1 = class(TForm)
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
    Procedure MouseEnter(Var Msg: TCMMOUSEENTER); message CM_MOUSEENTER;
    Procedure MouseLeave(Var Msg: TCMMOUSELEAVE); message CM_MOUSELEAVE;
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}
procedure TForm1.MouseEnter(var Msg: TCMMOUSEENTER);
begin
  if ((Msg.Sender) is TLabel) then
    TLabel(Msg.Sender).Color := clRed;
end;

procedure TForm1.MouseLeave(var Msg: TCMMOUSELEAVE);
begin
  if ((Msg.Sender) is TLabel) then
    TLabel(Msg.Sender).Color := clBtnFace;
end;

end.

_________________
MfG Lannes
(Nichts ist nicht Nichts) and ('' <> nil ) and (Pointer('') = nil ) and (@('') <> nil )
Stefan S. Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 184


D5
BeitragVerfasst: Sa 06.01.07 16:41 
@wulfskin: OK, jetzt hab ichs geschnallt. ^^ Komponente installiert, funktioniert wunderbar.

@Lannes: Das gefällt mir fast noch besser, wenn ich ohne abgeleitete Klasse auskomme. Werde mir den Code später nochmal genauer ansehen, aber funktionieren tut es auf jeden Fall.
Stefan S. Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 184


D5
BeitragVerfasst: So 07.01.07 15:16 
(Sorry wegen Doppelpost, aber es gibt ja Neuigkeiten)

Also ein Nachteil ist mir bei dieser Methode dann doch aufgefallen: Der Highlight-Effekt wird auf alle Komponenten dieses Typs (in diesem Fall TLabel) angewendet und damit auch auf welche, die eigentlich kein Highlight haben sollen oder z.B. eine andere Farbe. Da müsste ich dann noch den Controls-Wert abfragen, um festzustellen, ob die jeweilige Komponente ein Highlight hat oder nicht, oder?

Um nochmal auf meine ursprüngliche Methode mit OnMouseMove zurückzukommen: Kann man nicht einfach die Abfrage, wo sich der Mauscursor befindet, mit einner sinnvolleren Programmierweise unterbringen (statt dem Timer)? Denn in einem der Formulare des Projektes muss ich auch wegen etwas anderem die Mauskoordinaten ständig abfragen, da hab ich dann das selbe Problem. Auch kann man ja, wenn man das ganze Userinterface nicht mit Komponenten macht sondern Buttons und Texte z.B. in eine Paintbox zeichnet, auch nicht mit OnMouseMove oder CM_MOUSEENTER arbeiten und dann muss es ja auch irgendwie anders gehen.
wulfskin
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1349
Erhaltene Danke: 1

Win XP
D5 Pers (SSL), D2005 Pro, C, C#
BeitragVerfasst: So 07.01.07 15:35 
Hallo Stefan,

zu deinem ersten Absatz: NEIN! Wenn du diese Ereignisse selber implementierst, dann kannst du doch auch selber festlegen, bei welchen Komponenten das Eregnis existiert und bei welchen nicht.
Wenn du das ohne Ableiten einer Komponente machst, dann könnte das natürlich etwas "komplizierter" werden, da du dann ja kein Ereignis implementierst, sondern nur die Methode aufrufst und die Komponente übergibst. In diesem Fall könnte man zum Beispiel die Eigenschaft Tag verwenden um dies zu steuern.

Zum zweiten Absatz: Diese Methode (OnMouseEnter, OnMouseLeave) ist einfach die beste. Nimm diese, oder lass es. Dieses geschustere mit OnMouseMove ist einfach nicht das wahre. Genau für diesen Zweck gibt es ja genau diese Nachrichten!
Wenn du das ganze in eine Paintbox zeichnest, dann musst du natürlich auf OnMouseMove reagieren und überprüfen ob sich die Maus oberhalb eines Unterobjekts befindet, dann sendet aber die PaintBox wieder diese Nachrichten an die jeweiligen Unterobjekte.

Gruß Hape!

_________________
Manche antworten um ihren Beitragszähler zu erhöhen, andere um zu Helfen.
Stefan S. Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 184


D5
BeitragVerfasst: So 07.01.07 15:54 
user profile iconwulfskin hat folgendes geschrieben:
zu deinem ersten Absatz: NEIN! Wenn du diese Ereignisse selber implementierst, dann kannst du doch auch selber festlegen, bei welchen Komponenten das Eregnis existiert und bei welchen nicht.


Ich hab mich da jetzt auf Lannes' Code bezogen, also auf die Methode ohne Ableiten einer Komponente.

user profile iconwulfskin hat folgendes geschrieben:
Wenn du das ohne Ableiten einer Komponente machst, dann könnte das natürlich etwas "komplizierter" werden, da du dann ja kein Ereignis implementierst, sondern nur die Methode aufrufst und die Komponente übergibst. In diesem Fall könnte man zum Beispiel die Eigenschaft Tag verwenden um dies zu steuern.


Das mit "Tag" ist eine gute Idee, hab ich auch gleich mal ausprobiert. Also sofern diese Methode nicht irgendwelche Nachteile hat, mach ich das jetzt so, wie Lannes es beschrieben hat, das ist relativ simpel und funktioniert einwandfrei.
wulfskin
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1349
Erhaltene Danke: 1

Win XP
D5 Pers (SSL), D2005 Pro, C, C#
BeitragVerfasst: So 07.01.07 16:01 
user profile iconStefan S. hat folgendes geschrieben:
Das mit "Tag" ist eine gute Idee, hab ich auch gleich mal ausprobiert. Also sofern diese Methode nicht irgendwelche Nachteile hat, mach ich das jetzt so, wie Lannes es beschrieben hat, das ist relativ simpel und funktioniert einwandfrei.
Nachteile fallen mir spontan nicht ein. Gerade für solche Dinge ist so eine Eigenschaft Tag eigentlich auch gedacht. Wenn du mehrere Dinge im Tag speichern möchtest, kannst du ja immer noch OR-Verknüpfungen auf Konstanten (2er-Potenzen) benutzen.

Viele Grüße,
Hape

_________________
Manche antworten um ihren Beitragszähler zu erhöhen, andere um zu Helfen.