You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FMX TScrollBar的MouseDown、MouseUp事件不触发如何解决及滚动响应优化

问题原因
  • FireMonkey框架下的TScrollBar为复合控件,内部包含滑块、上下/左右按钮、滚动轨道三个子控件。所有鼠标交互事件默认被子控件捕获处理,不会向上冒泡到TScrollBar父组件本身,因此直接绑定父组件的OnMouseDown、OnMouseUp事件不会触发。
解决方案

方案1:使用自带OnScroll事件实现(推荐)

TScrollBar原生的OnScroll事件自带拖动状态标识,完全可以替代鼠标事件实现你的逻辑,无需处理子控件事件,修改后的完整代码如下:

unit ScrollBarSmoothUnit;

interface

uses
  System.Classes, System.UITypes, FMX.StdCtrls, FMX.Types;

type
  TScrollBarSmooth = class(TScrollBar)
  private
    FTimer : TTimer;
    FLastValue : Single;
    procedure DoScroll(Sender: TObject; ScrollCode: TScrollCode; var ScrollPos: Single);
    procedure DoChange(Sender: TObject);
  public
    OnChangeSmooth : TNotifyEvent;
    constructor Create(AOwner: TComponent); override;
  end;

implementation

constructor TScrollBarSmooth.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  OnScroll := DoScroll;

  FTimer := TTimer.Create(Self);
  FTimer.Interval := 40;
  FTimer.Enabled := False;
  FTimer.OnTimer := DoChange;

  FLastValue := -1;
end;

procedure TScrollBarSmooth.DoScroll(Sender: TObject; ScrollCode: TScrollCode; var ScrollPos: Single);
begin
  case ScrollCode of
    scBeginDrag: FTimer.Enabled := True;
    scEndDrag: 
      begin
        FTimer.Enabled := False;
        DoChange(Self);
      end;
  end;
end;

procedure TScrollBarSmooth.DoChange(Sender: TObject);
begin
  if Value = FLastValue then Exit;
  FLastValue := Value;
  if Assigned(OnChangeSmooth) then OnChangeSmooth(Self);
end;

end.

方案2:给子控件绑定鼠标事件

如果确实需要监听鼠标事件,可以在控件创建时遍历所有子控件,统一绑定事件,修改构造函数即可:

constructor TScrollBarSmooth.Create(AOwner: TComponent);
var
  i: Integer;
begin
  inherited Create(AOwner);
  AutoCapture := True;
  HitTest := True;

  // 给自身和所有子控件绑定鼠标事件
  OnMouseDown := ScrollMouseDown;
  OnMouseUp := ScrollMouseUp;
  for i := 0 to ControlsCount - 1 do
  begin
    Controls[i].HitTest := True;
    Controls[i].OnMouseDown := ScrollMouseDown;
    Controls[i].OnMouseUp := ScrollMouseUp;
  end;

  // 原计时器逻辑保持不变
  FTimer := TTimer.Create(Self);
  FTimer.Interval := 40;
  FTimer.Enabled := False;
  FTimer.OnTimer := DoChange;
  FLastValue := -1;
end;
其他优化滚动条响应的方案
  • 耗时的重绘逻辑拆分到后台线程执行,仅将渲染完成的位图抛到主线程更新,避免阻塞主线程消息循环
  • 拖动过程中可先绘制低精度的预览内容,拖动停止后再绘制完整的高精度内容,进一步降低拖动时的性能消耗
  • 调整计时器间隔匹配屏幕刷新率,普通60Hz屏幕对应16ms间隔,可平衡流畅度和资源占用

内容的提问来源于stack exchange,提问作者XylemFlow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 19:48:02