How can I fix the TScrollBar MouseWheel malfunction?
Asked Answered
H

2

2

I have a TScrollBox inside of a TFrame and when I use my mouse's wheel it simply does not goes up nor down the ScrollBox scrolling.

I have tried to use

TScrollBox(Sender).Perform(WM_VSCROLL,1,0); 

on the FrameMouseWheelDown but it does not trigger.

Any Ideas?

Hale answered 18/10, 2012 at 12:45 Comment(0)
W
5

My scroll box looks like this:

type
  TMyScrollBox = class(TScrollBox)
  protected
    function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint): Boolean; override;
    procedure WndProc(var Message: TMessage); override;
  end;

function TMyScrollBox.DoMouseWheel(Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint): Boolean;
begin
  Result := inherited DoMouseWheel(Shift, WheelDelta, MousePos);
  if not Result then begin
    if Shift*[ssShift..ssCtrl]=[] then begin
      VertScrollBar.Position := VertScrollBar.Position - WheelDelta;
      Result := True;
    end;
  end;
end;

procedure TMyScrollBox.WndProc(var Message: TMessage);
begin
  if Message.Msg=WM_MOUSEHWHEEL then begin
    (* For some reason using a message handler for WM_MOUSEHWHEEL doesn't work. The messages
       don't always arrive. It seems to occur when both scroll bars are active. Strangely,
       if we handle the message here, then the messages all get through. Go figure! *)
    if TWMMouseWheel(Message).Keys=0 then begin
      HorzScrollBar.Position := HorzScrollBar.Position + TWMMouseWheel(Message).WheelDelta;
      Message.Result := 0;
    end else begin
      Message.Result := 1;
    end;
  end else begin
    inherited;
  end;
end;
Wilie answered 18/10, 2012 at 12:51 Comment(19)
David, shouldn't the scroll box (a child) receive CM_MOUSEWHEEL rather than WM_MOUSEHWHEEL (just a guess, don't have Delphi by hand) ?Kleiman
@Kleiman Why do you feel it should be different?Wilie
Isn't the CM_MOUSEWHEEL <> WM_MOUSEHWHEEL ?Kleiman
@Kleiman Yes it is. Explain why it should be CM_MOUSEWHEEL?Wilie
You're telling in your code, that the message handler for the WM_MOUSEHWHEEL doesn't work and if I remember that right, the WM_MOUSEHWHEEL is handled by a form and dispatched as the CM_MOUSEWHEEL to its children (and that might be the reason why don't you get notified about the WM_MOUSEHWHEEL).Kleiman
@David: The CM_ messages are traditionally used. CM is Control Message (or Component?) and is used internally throughout the VCL. It differentiates between the normal Windows messages and those internally created/dispatched messages. (The CM_ messages have different values than their WM counterparts.)Vulgarize
@Ken Yes, I know that perfectly well.Wilie
@Kleiman I think there's a Delphi bug somewhere here and I just could not get to the bottom of it. I wrote a message handler, i.e. procedure ... message WM_MOUSEWHEEL and in some circumstances it never got called. But picking it up in WndProc was fine. I didn't chase it further because I had a reasonable workaround.Wilie
@David: I was commenting in response to your "Explain why" comment above. Why the "perfectly well" snap when you're the one who asked?Vulgarize
@Ken You did not give explanation of why it should be CM rather than WM. You just contrasted them. In this case I explicitly want WM. I don't want CM.Wilie
"It differentiates between the normal Windows messages and those internally created/dispatched" is not an explanation? I thought it was stated pretty clearly. I guess I should have expected it, though. When will I learn? sighVulgarize
@Ken But I don't want to handle CM. I was asking for a justification of why CM should be preferred here. I was not asking to know the difference between WM and CM. You see my point? Sorry for snapping.Wilie
I can not find WM_MOUSEHWHEEL in Delphi library. I switched to WM_MOUSEWHEEL. But it worked!Hale
They mean completely different things. One is for horizontal scrolling, the other for vertical. You need the code as it is in the answer.Wilie
As for the value of WM_MOUSEHWHEEL, if you don't have it in your Delphi RTL, use websearch to find the value. Search leads you here: msdn.microsoft.com/en-us/library/windows/desktop/ms645614.aspx and so the value is $020E.Wilie
@KenWhite For what it is worth, there is no CM_MOUSEHWHEEL as it happens. Note that it is CM_MOUSEHWHEEL and not CM_MOUSEWHEEL.Wilie
@DavidHeffernan, When does the control gets a "WM_MOUSEHWHEEL" message? do I need a mice with 2 wheels or what?Kelseykelsi
@Kelseykelsi H wheel is usually not a wheel. The wheel can be pushed to left or right to simulate page left/right.Wilie
Check WM_VSCROLL tooPryce
K
4

You can use the OnMouseWheel event handler:

ScrollBar1.OnMouseWheel := ScrollBoxMouseWheel;
...
procedure TFrame1.ScrollBoxMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
begin
  Handled := True;
  if WheelDelta < 0 then
    TScrollBox(Sender).VertScrollBar.Position := TScrollBox(Sender).VertScrollBar.Position + TScrollBox(Sender).VertScrollBar.Increment 
  else
    TScrollBox(Sender).VertScrollBar.Position := TScrollBox(Sender).VertScrollBar.Position - TScrollBox(Sender).VertScrollBar.Increment;
end;
Kelseykelsi answered 18/10, 2012 at 17:22 Comment(1)
it worked for me, but not in this way. I had to use the ScrollBoxMouseWheel-event of the form itself and replace TScrollBox(Sender) by the name of the scrollbox.Monochromatism

© 2022 - 2024 — McMap. All rights reserved.