super.
Zitat:
die arbeitsweise deiner lösung ist mir noch etwas schleierhaft
Für diejenigen die eine Erklärung wollen:
Delphi-Quellcode:
procedure TForm1.MouseMove();
var
C: TControl;
begin
// 1.)
C := FindDragTarget(ClientToScreen(Point(X, Y)), False);
// 2.)
if C <> FCurrentLabel then
begin
// 3.)
if (FCurrentLabel is TLabel) and (FCurrentLabel.Owner = Self) then
TLabel(FCurrentLabel).Font.Color := clBlack;
// 4.)
FCurrentLabel := C;
// 5.)
if (FCurrentLabel is TLabel) and (FCurrentLabel.Owner = Self) then
TLabel(FCurrentLabel).Font.Color := clRed;
end;
end;
1.) die Mauskoordinaten in fast allen Ereignissen beziehen sich immer auf die Clientkoordinaten des Senders. Im Falle eines TForm's also die Koordinaten relativ zur linken oberen Ecke des Formulars unterhalb der Menubar und rechts neben dem Rand des Formulars.
Diese Koordinaten müssen umgewandelt werden in absolute Korrdinaten relativ zum kompletten Bildschrim, sprich dem Screen. Dies macht man mit Control.ClientToScreen(TPoint). Die Funktion Point(X, Y) wandelt nur zwei X,Y Ordinale in einen TPoint um da .ClientToScreen() dies benötigt.
Nun haben wir die richtigen Koordinaten um global auf dem kompletten Screen mit FindDragTarget() das Control an diesen Koordinaten zu suchen. Die Funktion FindDragTarget() nimmt uns dabei sehr viel Arbeit ab, da sie zb. auch einfache Controls abgeleitet von TGraphicControl finden kann. Das besondere von solchen TGraphicControl Klassen ist es das sie für das Windows-
OS quasi nicht existent sind, da sie keinerlei Fensterhandles besitzen.
Desweiteren findet FindDragTarget() auch nur die Controls der eigenen Anwendung, obwohl es durchaus möglich wäre auf ähnliche Weise die Controls fremder Delphi/BCB Anwendungen zu finden.
2.) wir haben nun das Control in C stehen. Und wollen nur auf eine Änderung zum aktuell gefundenen Control reagieren. Indirekt simulieren wir damit das was die Events .OnMouseEnter() und .OnMouseLeave() machen. Aber mit dem Unterschied das dieser Weg allgemeingültig für die komplette Anwendung funktoniert.
3.) da sich das aktuelle Control unter dem Mauszeiger verändert hat, sprich der Anwender hat die Maus bewegt
wird als allererstes das letzte Control in seiner Darstellung zurückgesetzt. Dies darf natürlich nur ein TLabel des eigenen Formulares sein. Deshalb fragen wird dies auch ab. Nebenbei bemerkt wird man wenn man die
VCL Sourcen rückwärts beginnend bei .OnMouseEnter(), .OnMouseLeave() über die Messages cm_MouseEnter, cm_MouseLeave bis hin zur innersten Routine der
VCL zurückverfolgt exakt das Gleiche finden was im obigen Source steht !! Die
VCL Sourcen verwalten also intern ebenfalls ein CurrentMouseControl und fragen bei Mausbewegungen ebenfalls über FindDragTarget() das Control ab, bei Änderung setzen sie einfach die Messages cm_MouseLeave/cm_MouseEnter ab, und rufen somit die Events .OnMouseLeave() und .OnMouseEnter() auf. Nichts Neues also
4.) das Control unter dem Mauszeiger wird zum aktuellen Control, wir speichern also den Zeiger im Form als privates Feld zwischen.
5.) das neue Control muß natürlich noch die Darstellung ändern, sprich wenn es ein TLabel auf dem eigenen Form ist soll der Text rot dargestellt werden.
fertig.
Gruß Hagen