利用TScrollBox控件在OnMouseWheel事件中滑轮滚动事件。
方法一:
模拟人工操作:
if WheelDelta < 0 then
ScrollBox1.VertScrollBar.Position := ScrollBox1.VertScrollBar.Position + 5
else
ScrollBox1.VertScrollBar.Position := ScrollBox1.VertScrollBar.Position - 5;
优点:对于程序员容易理解,容易想到;
缺点:重影很明显;
方法二:
调用Windows发送消息方法:
//Windows API
//如果鼠标不在当前控件之上,则不处理鼠标滚动事件
if not (IsChild(ScrollBox1.Handle, WindowFromPoint(MousePos)) or
(ScrollBox1.Handle = WindowFromPoint(MousePos))) then Exit;
if WheelDelta < 0 then
SendMessage(ScrollBox1.Handle, WM_VSCROLL, SB_LINEDOWN, 0)
else
SendMessage(ScrollBox1.Handle, WM_VSCROLL, SB_LINEUP, 0);
优点:重影有所缓解,原因在于SendMessage机制:如果消息连续重复则执行一次,并且是轮旋机制处理;
缺点:刷新速度级别对于某些特殊要求下不能满足;
方法三:
Delphi 控件的Perform方法:
if WheelDelta < 0 then
ScrollBox1.Perform(WM_VSCROLL, SB_LINEDOWN, 0)
else
ScrollBox1.Perform(WM_VSCROLL, SB_LINEUP, 0);
优点:能看到源代码,直到汇编语言执行内容;
缺点:同上
在执行发送消息之后需要调用控件的重新绘制命令,方法有二:
法一:控件.Update 抖动明显
法二:控件.Repaint 抖动不那么明显
所有代码如下:
procedure TMyTestFrm.ScrollBox1MouseWheel(Sender: TObject;
Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint;
var Handled: Boolean);
begin
//模拟人工操作
// if WheelDelta < 0 then
// ScrollBox1.VertScrollBar.Position := ScrollBox1.VertScrollBar.Position + 5
// else
// ScrollBox1.VertScrollBar.Position := ScrollBox1.VertScrollBar.Position - 5;
//Windows API
//如果鼠标不在当前控件之上,则不处理鼠标滚动事件
if not (IsChild(ScrollBox1.Handle, WindowFromPoint(MousePos)) or
(ScrollBox1.Handle = WindowFromPoint(MousePos))) then Exit;
if WheelDelta < 0 then
SendMessage(ScrollBox1.Handle, WM_VSCROLL, SB_LINEDOWN, 0)
else
SendMessage(ScrollBox1.Handle, WM_VSCROLL, SB_LINEUP, 0);
//Delphi 方法
// if WheelDelta < 0 then
// ScrollBox1.Perform(WM_VSCROLL, SB_LINEDOWN, 0)
// else
// ScrollBox1.Perform(WM_VSCROLL, SB_LINEUP, 0);
//Update 与 Repaint 比较
// ScrollBox1.Parent.Update; //采用Update方法比不用滚动重影没那么明显,但是还是存在;
ScrollBox1.Parent.Repaint;
end;
2022-07-22补充:
对于重影与连续滑动的问题,设置Handled:=True会有比较明显的改善;