Donnerstag, 21. November 2013

Delphi, ScrollBox and mouse wheel

I had a problem using Delphi 2010 that wasn't too easy to solve. Having a ScrollBox on a Frame or a Form and reacting to OnMouseWheel event isn't trivial. The problem seems to be in the VCL implementation of the TScrollBox control.

In my case I have several panels (TPanel) inside the scrollbox, testing it's OnMouseWheel event revealed that it was never fired. Probably this is because the mouse is above one of the panels, it gets the OnMouseWheel event, says that it handled it because it hasn't anything to scroll, and I have the current situation.

After trying different solutions I found the WinAPI style by intercepting and resending the WM_MOUSEWHEEL event to the scrollbox too complicated and finally found a working though a little bit hacky solution.

To solve it you need to use the OnMouseWheel event of the frame or form, where the scrollbox is.


procedure TMyFrame.FrameMouseWheel(Sender: TObject;
  Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint;
  var Handled: Boolean);
var
  LTopLeft, LTopRight, LBottomLeft, LBottomRight: Integer;
  LPoint: TPoint;
begin
  inherited;

  // First you have to get the position of the control on screen
  // as MousePos coordinates are based on the screen positions.
  LPoint := ScrollBox1.ClientToScreen(Point(0,0));
  LTopLeft := LPoint.X;
  LTopRight := LTopLeft + ScrollBox1.Width;
  LBottomLeft := LPoint.Y;
  LBottomRight := LBottomLeft + ScrollBox1.Width;

  if (MousePos.X >= LTopLeft) and
    (MousePos.X <= LTopRight) and
    (MousePos.Y >= LBottomLeft)and
    (MousePos.Y <= LBottomRight) then
  begin
    // If the mouse is inside the scrollbox coordinates,
    // scroll it by setting .VertScrollBar.Position.
    ScrollBox1.VertScrollBar.Position :=
      ScrollBox1.VertScrollBar.Position - WheelDelta;
    Handled := True;
  end;
end;

Funny part of it, you have to set .VertScrollBar.Position and mustn't use the ScrollBy function of the scrollbox as the latter doesn#t look for valid values and you can scroll out of screen beyond the actual content of the scrollbox.

Keine Kommentare:

Kommentar veröffentlichen