Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Bereich beim Mouseover hervorheben (https://www.delphipraxis.net/113540-bereich-beim-mouseover-hervorheben.html)

Keks 9. Mai 2008 14:39


Bereich beim Mouseover hervorheben
 
Hallo zusammen,

ich würde gerne einige Komponenten bei einem Mouseover optisch gruppieren / highlighten. Es gibt dafür sicherlich viele verschiedene Lösungen, aber bevor ich alle selbst ausprobieren muss, würde ich gerne eine Meinung von jemandem hören, der sich hier auskennt.

So sollte das dann funktionieren:
- Sobald der Mauszeiger über einem festgelegten Bereich liegt, soll sich dieser einfärben.
- Beim Verlassen des Bereiches wird dieser wieder transparent
- Es gibt mehrere solcher Bereiche, die ich gerne codeseitig mit x-y-Koordinaten festlegen würde.
- Die darüberliegenden Komponenten sollten durchscheinen, also nicht wie im Mockup beim Label noch einen anderen Hintergrund zeigen.
- Das ganze muss sowohl unter Win2000 als auch WinXP funktionieren, auf Transparenzmöglichkeiten des XP-Manifests kann man sich also nicht verlassen.
- Es sollte zudem flüssig und resourcensparend funktionieren, also weder Flakern noch den Computer auslasten.

http://img120.imageshack.us/img120/7...ghlightts9.gif

Was wäre die beste Lösung dafür?

mirage228 9. Mai 2008 14:43

Re: Bereich beim Mouseover hervorheben
 
Entweder legst du da in Panel hin und die Komponenten rein (und dann im Panel mouseover etc.) oder du machst es manuell mit CreateWindowRgn und IsPtInRegion etc.

mfG
mirage228

RavenIV 9. Mai 2008 15:10

Re: Bereich beim Mouseover hervorheben
 
Oder Du verwendest Komponenten, die das "Hot-Tracking" beherrschen.
z.B. die von DevExpress oder bei torry.net suchen.

Keks 9. Mai 2008 15:18

Re: Bereich beim Mouseover hervorheben
 
@mirage228
Beim Panel werden die OnMouseEnter und OnMouseLeave Funktionen leider nur aktiv, wenn direkt auf das Panel gezeigt wird. Zeige ich auf ein Editfeld darin, dann zählt das wie ein Verlassen des Panels. Außerdem würde ich gerne darauf verzichten, noch weiter in Panels zu schachteln.

CreateWindowRgn klingt interessant, ich finde dazu aber leider keine brauchbaren Informationen. Kannst Du hier etwas weiterhelfen?

@RavenIV
Falls möglich, würde ich gerne auf Fremdkomponenten verzichten. Das sollte doch auch mit einfachereren Mitteln machbar sein!?


Eine Art Zeichenbereich hinter den eigentlichen Elementen, der dann auf die Mausposition reagiert, wäre gut...

The_Doomed 9. Mai 2008 15:48

Re: Bereich beim Mouseover hervorheben
 
ich würde es auch über panel machen und dann halt auch beim mouse.enter des edits die panelfarbe ändern
außerdem ist es keine viel größere schachtelung als wenn du zeichenbereiche dahinterlegts oder??

Keks 9. Mai 2008 16:50

Re: Bereich beim Mouseover hervorheben
 
Zitat:

Zitat von The_Doomed
ich würde es auch über panel machen und dann halt auch beim mouse.enter des edits die panelfarbe ändern

Dann sag mir bitte, was gegen die angesprochene Tatsache zu machen ist, dass beim Zeigen auf ein Element innerhalb des Panels bereits das OnMouseLeave-Event des Panels ausgelöst wird und der Hintergrund nicht mehr farbig ist!?

Zitat:

Zitat von The_Doomed
außerdem ist es keine viel größere schachtelung als wenn du zeichenbereiche dahinterlegts oder??

Bei einer Zeichenfläche lege ich diese ein Mal hinter die Elemente oder erstelle das noch besser dynamisch und färbe hier nur bestimmte Bereiche ein. Bei den Panels muss ich das ja schon von vornherein schachteln, brauche pro Gruppe ein Panel und bin damit absolut unflexibel.


Ich dachte eigentlich, dass der eine oder andere schon so etwas in der Art gemacht haben könnete!? So abgehoben ist die Idee ja nun auch nicht...

grenzgaenger 9. Mai 2008 17:18

Re: Bereich beim Mouseover hervorheben
 
wie wäre es, die koordinaten in eine liste zu stellen und dann die maus zu überwachen und beim drüberfahren entsprechend die aktionen durchzuführen....

hier könntest dann mit findcomponent und der tag eigenschaft releativ komfortable mehere komponenten anpassen.

Fussball-Robby 9. Mai 2008 18:28

Re: Bereich beim Mouseover hervorheben
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich hab mal ein kleines Beispielprojekt gemacht. So würde ich das lösen. Hebt zwar bisher nur den Bereich um 1 Control hervor, das solltest du aber leicht ändern können. Achte auf die Kommentare :wink:

Keks 9. Mai 2008 20:24

Re: Bereich beim Mouseover hervorheben
 
@Fussball-Robby
Danke, sieht interessant aus. Aber ich glaube, das hilft in dem Fall nicht weiter. In Deinem Beispiel wird jede Komponente beim Draufzeigen umrandet. Das ist ganz nett, aber lässt sich schwer auf einen ganzen Bereich übertragen.

@grenzgaenger
Das klingt gut und könnte funktionieren.
Ich versuche gerade die Mauskoordinaten in der MainForm zuverlässig zu ermitteln.
Ich frage die aktuelle Zeigerposition im FormMouseMove-Event ab. Das Problem ist dann aber, dass sobald ich auf ein anderes Element (Button, Checkbox, ...) zeige, das FormMouseMove-Event nicht mehr aktiviert wird. Ich habe jetzt eine Weile gesucht, aber finde dafür keine geschickte Lösung. Wie frage ich die Mauskoordinaten im Hauptprogrammfenster ab, unabhängig davon, ob die Maus sich gerade über anderen Komponenten befindet oder nicht. (Mit einem Timer würde das gehen, aber deswegen jetzt noch dauerhafte Timer setzen würde ich gerne vermeiden.) Gibt es eine andere Möglichkeit?

bitsetter 9. Mai 2008 20:43

Re: Bereich beim Mouseover hervorheben
 
Du kannst doch allen Komponenten die gleiche MouseMove Prozedur zuweisen.
Edit: In der Prozedur kannst du dann auch sowas reinschreiben:
Delphi-Quellcode:
var
  Pt: TPoint;
begin
  Pt:= self.ClientToScreen(mouse.CursorPos);
 //Caption:= Format('X: %d, Y: %d', [Pt.X, Pt.Y]);

Oder du verwendest das Ereignis onMessage der Komponente TApplicationEvents.
Edit: Im Ereignis onMessage brauchst du natürlich nur die Nachricht WM_MOUSEMOVE verarbeiten!

Keks 9. Mai 2008 22:30

Re: Bereich beim Mouseover hervorheben
 
Zitat:

Zitat von bitsetter
Du kannst doch allen Komponenten die gleiche MouseMove Prozedur zuweisen.

Das finde ich nicht sehr geschickt...

Zitat:

Zitat von bitsetter
Oder du verwendest das Ereignis onMessage der Komponente TApplicationEvents.

Das habe ich jetzt mal gemacht und es funktioniert soweit, dass die Koordinaten ständig aktualisiert werden, egal, worauf der Mauszeiger zeigt. Super!
Das Problem ist aber nun, dass die Koordinaten vom Gesamtbildschirm angezeigt werden und nicht die Koordinaten im Programmfenster, was ich aber bräuchte, um die Hervorhebung an die exakte Stelle zeichnen zu können. Kriegt man das nun auch noch irgendwie hin?
Wenn ich das hier versuche:
Delphi-Quellcode:
Label1.Caption := Format('%d:%d', [Mouse.CursorPos.X-Form1.Left, Mouse.CursorPos.Y-Form1.Top]);
dann stimmen die Werte immer noch nicht exakt. Ich vermute, es muss noch der Fensterrand abgezogen werden, aber das ist mir irgendwie nicht so ganz geheuer. Je nach Systemeinstellung (anderer Windows-Skin, große Schriftarten) wird das dann nachher doch anders berechnet und die Position stimmt nicht mehr. Also wie geht das richtig?

Fussball-Robby 9. Mai 2008 22:41

Re: Bereich beim Mouseover hervorheben
 
Zitat:

Zitat von Keks
Das Problem ist aber nun, dass die Koordinaten vom Gesamtbildschirm angezeigt werden und nicht die Koordinaten im Programmfenster, was ich aber bräuchte, um die Hervorhebung an die exakte Stelle zeichnen zu können. Kriegt man das nun auch noch irgendwie hin?

Delphi-Quellcode:
var
  Pt: TPoint;
begin
  Pt := {Form1.}ScreenToClient(Mouse.CursorPos);
end;

Keks 9. Mai 2008 23:25

Re: Bereich beim Mouseover hervorheben
 
Bestens! So sieht das ganze nun aus und gibt zuverlässig die Mausposition an:

Delphi-Quellcode:
procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG; var Handled: Boolean);
  var Pt : TPoint;
begin
  if (Msg.message = WM_MOUSEMOVE) then
  begin
    Pt := ScreenToClient(Mouse.CursorPos);
    Label6.Caption := Format('%d:%d', [Pt.X, Pt.Y]);
  end;
end;
Zu muss ich die möglichen Flächen definieren können. Dabei muss ich pro Fläche zwei Points bzw. 4 Integer speichern.
Erstelle ich dafür nun eigene Records und verwalte die in einem Array oder geht das auch geschickter? Ich muss ja anschließend bei jeder Mausbewegung die gesamte Liste durchgehen und schauen, ob sich der Mauszeiger in einem dieser Felder befindet. Entsprechend wäre es super, wenn das performanceoptimiert gehandhabt werden könnte. Was ist dafür die beste Vorgehensweise?

bitsetter 9. Mai 2008 23:38

Re: Bereich beim Mouseover hervorheben
 
Nimm doch die Struktur TRect dafür und teste mit der Funktion PtInRect() ob sich der Cursor in dem Bereich befindet.
Da sich die Bereiche zur Laufzeit wahrscheinlich nicht ändern werden, würde ein statischer Array dafür sicherlich ausreichen.

Keks 10. Mai 2008 14:39

Re: Bereich beim Mouseover hervorheben
 
Danke! Das klapt jetzt sehr gut. :)

Jetzt hoffentlich das letzte Problem: Wenn sich farblich etwas hinter einem Element verändert, nimmt das auf dessen Hintergrundfarbe keinen Einfluss. Es muss erst sowas wie Label1.Repaint gemacht werden, dann klappt das. Nun möchte ich das aber nicht für jedes Element einzeln machen. Kann man irgendwie alle Elemente in z.B. einer Groupbox gleichzeitig neu zeichnen?

Fussball-Robby 10. Mai 2008 14:56

Re: Bereich beim Mouseover hervorheben
 
Zitat:

Zitat von Keks
Kann man irgendwie alle Elemente in z.B. einer Groupbox gleichzeitig neu zeichnen?

Delphi-Quellcode:
procedure DoRepaint(c: TWinControl);
begin
  if (c = nil) or (c.Handle = 0) then
    Exit;
  RedrawWindow(c.Handle, nil, 0,
      RDW_ERASE or RDW_FRAME or RDW_INVALIDATE or RDW_ALLCHILDREN);
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  DoRepaint(GroupBox1);
end;
So dürfte es funktionieren.

Mfg

Keks 10. Mai 2008 15:27

Re: Bereich beim Mouseover hervorheben
 
Stark! Vielen Dank! :thumb:


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