Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - MouseWheel und 3 Scrollboxen bessere Lösung gesucht?


ALF - So 05.12.10 18:54
Titel: MouseWheel und 3 Scrollboxen bessere Lösung gesucht?
Hi, wie schon im Topic erwähnt, suche ich ne bessere Lösung dafür. Alle 3 ScrollBoxen zeigen auf das selbe MouseWheelEreignis.

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:
procedure TForm1.ScrollBox1MouseWheel(Sender: TObject;
  Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint;
  var Handled: Boolean);
begin
 //if (Sender as TScrollBox).ClientToScreen = MousePos then;

  if (MousePos.x > ScrollBox1.ClientOrigin.X) and (MousePos.x < (ScrollBox1.ClientOrigin.X + ScrollBox1.Width)) then
      ScrollBox1.SetFocus
  else
  if (MousePos.x > ScrollBox2.ClientOrigin.X) and (MousePos.x < (ScrollBox2.ClientOrigin.X + ScrollBox2.Width)) then
     ScrollBox2.SetFocus
  else
  if  (MousePos.x > ScrollBox3.ClientOrigin.X) and (MousePos.x < (ScrollBox3.ClientOrigin.X+ScrollBox3.Width)) then
      PlayBox3.SetFocus
  else
  Form1.SetFocus;

  if (Sender is TScrollbox)then
  begin
     if WheelDelta = -120 then  (Sender as TScrollBox).Perform(WM_VSCROLL, SB_LINEDOWN, 0);
     if WheelDelta = 120 then   (Sender as TScrollBox).Perform(WM_VSCROLL, SB_LINEUP, 0);
  end;
end;
zumal dies auch nicht die Lösung ist. Speziell wenn ich die Linke bzw. rechte Scrollbox aktiv habe, bleibt sie aktiv, weil mousepos entweder kleiner bzw grösser ist als die jeweilige ScrollBox. Müsste also noch zusätzliche vergleich durchführen.

mh... finde einfach keine bessere Lösung?

Gruss ALf


jaenicke - So 05.12.10 19:01

Ich verstehe gar nicht was du eigentlich erreichen möchtest. Du hast einen gemeinsamen Handler für alle drei Ereignisse der drei ScrollBoxen und sprichst die dennoch direkt alle drei an und setzt den Fokus auf irgendeine. Ansprechen tust du mit dem Scrollen aber ggf. eine ganz andere (immer den Sender). Keine Ahnung was das werden soll. :nixweiss:

Was genau möchtest du denn erreichen?


ALF - So 05.12.10 19:12

Ich möchte, wenn ich mit der Mouse über der jeweiligen ScrollBox bin und mit dem MouseRad arbeite, das die jeweilige ScrollBox aktiv wird also den Fokus erhält. Mousewheel funct ja nur, wenn die Scrollbox den Focus hat.
Sonst hätt ich ja das ganze nicht so aufgebaut, wenn es automatisch per Sender gehen würde.

Noch vergessen zu erwähnen. Die Scrollboxen beinhalten noch andere Komponenten.

Gruss ALf


bummi - So 05.12.10 19:27

Lege Dir eine Klassenvariable FActiveScrollbox:TScrollbox an

in MouseEnter aller Scrollboxen setzt Du FActiveScrollbox auf den Sender, im MouseLeave auf NIL.

Dann kannst wenn assigned Deine Befehle an FActiveScrollbox schicken.


jaenicke - So 05.12.10 19:31

user profile iconALF hat folgendes geschrieben Zum zitierten Posting springen:
Mousewheel funct ja nur, wenn die Scrollbox den Focus hat.
Wie kommst du darauf? Du kannst auch das MouseWheel Ereignis des Formulars nutzen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
procedure TForm273.FormMouseWheel(Sender: TObject; Shift: TShiftState;
  WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
var
  MyScrollBox: TScrollBox;
  CurrentPos: TPoint;
begin
  CurrentPos := ScreenToClient(MousePos);
  if PtInRect(ScrollBox1.BoundsRect, CurrentPos) then
    MyScrollBox := ScrollBox1
  else if PtInRect(ScrollBox2.BoundsRect, CurrentPos) then
    MyScrollBox := ScrollBox2
  else if PtInRect(ScrollBox3.BoundsRect, CurrentPos) then
    MyScrollBox := ScrollBox3
  else
    Exit;
  if WheelDelta < 0 then
    MyScrollBox.Perform(WM_VSCROLL, SB_LINEDOWN, 0)
  else
    MyScrollBox.Perform(WM_VSCROLL, SB_LINEUP, 0)
end;


ALF - So 05.12.10 20:27

mh...

@bummi, dann könnte ich aber auch mit MouseMove die jeweilige ScrollBox den Focus geben, dann hätte ich den Sender in ScrollBox1MouseWheel wieder. Spare also nix ein.

@jaenicke, will nicht funcen, bis auf ScrollBox1. Allerdings kann ich mit den Werten die in Bountrect drin stehen nichts anfangen, zumindestens was den Vergleich mit CurrentPos betrifft. Hab zwar verstanden was PtInRect macht, warum aber nur die ScrollBox1 funct??

Gruss Alf


jaenicke - So 05.12.10 20:30

Kann es sein, dass die ScrollBoxen noch auf anderen Komponenten (z.B. einem Panel) liegen? Dann müsstest du die Koordinaten natürlich noch entsprechend umrechnen.


ALF - So 05.12.10 20:39

So ist es. Die einzelnen ScrollBoxen befinden sich noch in einer GroupBox. Bischen was geändert und siehe da, es funct :D

THX für die geniale Lösung!

Gruss Alf


jaenicke - So 05.12.10 22:44

Falls du das nicht so gemacht hast, am einfachsten ist es, wenn du die Mauskoordinaten direkt entsprechend umrechnest:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
procedure TForm273.FormMouseWheel(Sender: TObject; Shift: TShiftState;
  WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
var
  MyScrollBox: TScrollBox;
  CurrentPos: TPoint;
begin
  CurrentPos := MyGroupBox.ScreenToClient(MousePos);


ALF - Mo 06.12.10 11:44

Nicht gant so, da es ja, habe vergessen zu erwähnen, auch 3 GroupBoxen gibt.
Lösung hab ich so gemacht

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
CurrentPos:= ScreenToClient(MousePos);
if PtInRect(GroupBox1.BoundsRect, CurrentPos) then
   MyScrollBox:= ScrollBox1
else
if PtInRect(GroupBox2.BoundsRect, CurrentPos) then
   MyScrollBox:= ScrollBox2
else
......


Hab zwar noch überlegt das ganze zu optimieren, um nicht 3 if abfragen zu machen.
Aber man muss es ja nicht übertreiben :wink:

Gruss Alf
PS Ich wundere mich, wie man auf solch geniale Lösungen kommt. Findet man doch in keinem Handbuch. Verglichen mit meinem Versuch siehe 1. Post der zwar auch functioniert aber bei weitem nicht so genial ist!