为什么 FMX TScrollBar OnMouseUp 不工作?

Why is FMX TScrollBar OnMouseUp not working?

我有一个 ScrollBar,鼠标事件分配给了 onChange、onMouseWheel 和 onMouseUp。 onChange 和 wheel 事件工作正常,但 onMouseUp 事件不会触发。在调试时深入到 TControl 方法,我注意到事件变量 (FOnMouseUp) 为空。该事件在 IDE 中分配,我将其放在表单的 onCreate 事件中,另外我尝试在创建表单后在其他各个地方分配它,但无济于事。给出了什么?


这是一个简单的可重现示例,其中所有三个滚动条鼠标事件均未触发:

 `TForm4 = class(TForm)
    ScrollBar1: TScrollBar;
    Label1: TLabel;
    procedure ScrollBar1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Single);
    procedure ScrollBar1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Single);
    procedure ScrollBar1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Single);
    procedure ScrollBar1Change(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form4: TForm4;

implementation

{$R *.fmx}

procedure TForm4.ScrollBar1Change(Sender: TObject);
begin
  Label1.Text := 'onChange: ' + Screen.MousePos.Y.ToString;
end;

procedure TForm4.ScrollBar1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Single);
begin
  Label1.Text := 'mousedown: ' + Y.ToString;
end;

procedure TForm4.ScrollBar1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Single);
begin
  Label1.Text := 'mousemove: ' + Y.ToString;
end;

procedure TForm4.ScrollBar1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Single);
begin
  Label1.Text := 'mouseUP: ' + Y.ToString;
end;

end.`

还有.FMX:

`object Form4: TForm4
  Left = 0
  Top = 0
  Caption = 'Form4'
  ClientHeight = 480
  ClientWidth = 640
  FormFactor.Width = 320
  FormFactor.Height = 480
  FormFactor.Devices = [Desktop]
  DesignerMasterStyle = 0
  object ScrollBar1: TScrollBar
    SmallChange = 0.000000000000000000
    Orientation = Vertical
    Position.X = 616.000000000000000000
    Position.Y = 8.000000000000000000
    Size.Width = 18.000000000000000000
    Size.Height = 449.000000000000000000
    Size.PlatformDefault = False
    TabOrder = 0
    OnChange = ScrollBar1Change
    OnMouseDown = ScrollBar1MouseDown
    OnMouseMove = ScrollBar1MouseMove
    OnMouseUp = ScrollBar1MouseUp
  end
  object Label1: TLabel
    Position.X = 568.000000000000000000
    Position.Y = 152.000000000000000000
    Text = 'Label1'
    TabOrder = 1
  end
end`

原因是滚动条包含轨道、拇指和最小和最大按钮等子对象。响应鼠标事件的是这些对象,而不是父对象。所以解决方案是将鼠标事件设置为这些对象。问题是那些对象是受保护的,因此您必须创建一个新的滚动条 class 来设置这些事件。 TScrollBar 构造函数中尚不存在子对象,因此我发现分配它们的最佳位置是在第一次绘制事件中。

几周前我问了几乎完全相同的问题。在这里查看我自己的答案。

这是您的示例,现在可以使用了。我还将您的一个标签替换为 4 个标签,以便更容易查看调用了哪些事件。

响应鼠标事件的新滚动条class:

unit ScrollBarMouse;

interface

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

type

  // A scroll bar that responds to mouse events
  TScrollBarMouse = class(TScrollBar)
  private
    FMouseEventsSet : Boolean;
  protected
    procedure Paint; override;
  public
    constructor Create(AOwner: TComponent); override;
  end;


implementation

constructor TScrollBarMouse.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);

  FMouseEventsSet := False;
end;

procedure TScrollBarMouse.Paint;
begin
  inherited;

  // Track and Buttons are not assigned in constructor, so set mouse events on first paint
  if not FMouseEventsSet and Assigned(Track) and Assigned(Track.Thumb)
    and Assigned(MinButton) and Assigned(MaxButton) then begin
    Track.OnMouseDown       := OnMouseDown;
    Track.OnMouseUp         := OnMouseUp;
    Track.OnMouseMove       := OnMouseMove;
    Track.Thumb.OnMouseDown := OnMouseDown;
    Track.Thumb.OnMouseUp   := OnMouseUp;
    Track.Thumb.OnMouseMove := OnMouseMove;
    MinButton.OnMouseDown   := OnMouseDown;
    MinButton.OnMouseUp     := OnMouseUp;
    MinButton.OnMouseMove   := OnMouseMove;
    MaxButton.OnMouseDown   := OnMouseDown;
    MaxButton.OnMouseUp     := OnMouseUp;
    MaxButton.OnMouseMove   := OnMouseMove;
    FMouseEventsSet := True;
  end;
end;

end.

表格单位:

unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
  FMX.Controls.Presentation, FMX.StdCtrls, ScrollBarMouse;

type

TForm4 = class(TForm)
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    procedure ScrollBar1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Single);
    procedure ScrollBar1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Single);
    procedure ScrollBar1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Single);
    procedure ScrollBar1Change(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    ScrollBar1 : TScrollBarMouse;
  end;

var
  Form4: TForm4;

implementation

{$R *.fmx}

procedure TForm4.FormCreate(Sender: TObject);
begin
  // Create the scroll bar object
  ScrollBar1 := TScrollBarMouse.Create(Self);
  with ScrollBar1 do begin
    Parent := Self;
    Orientation := TOrientation.Vertical;
    Position.X := 616;
    Position.Y := 8;
    Size.Width := 18;
    Size.Height := 449;
    OnMouseDown := ScrollBar1MouseDown;
    OnMouseUp := ScrollBar1MouseUp;
    OnMouseMove := ScrollBar1MouseMove;
    OnChange := ScrollBar1Change;
  end;
end;

procedure TForm4.ScrollBar1Change(Sender: TObject);
begin
  Label1.Text := 'onChange: ' + IntToStr(Round(Screen.MousePos.Y));
end;

procedure TForm4.ScrollBar1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Single);
begin
  Label2.Text := 'mousedown: ' + IntToStr(Round(Y));
end;

procedure TForm4.ScrollBar1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Single);
begin
  Label3.Text := 'mousemove: ' + IntToStr(Round(Y));
end;

procedure TForm4.ScrollBar1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Single);
begin
  Label4.Text := 'mouseUP: ' + IntToStr(Round(Y));
end;

end.

表单(滚动条被删除,因为它是在 运行 时间创建的):

object Form4: TForm4
  Left = 0
  Top = 0
  Caption = 'Form4'
  ClientHeight = 480
  ClientWidth = 640
  FormFactor.Width = 320
  FormFactor.Height = 480
  FormFactor.Devices = [Desktop]
  OnCreate = FormCreate
  DesignerMasterStyle = 0
  object Label1: TLabel
    Position.X = 424.000000000000000000
    Position.Y = 144.000000000000000000
    Size.Width = 121.000000000000000000
    Size.Height = 17.000000000000000000
    Size.PlatformDefault = False
    Text = 'Label1'
    TabOrder = 3
  end
  object Label2: TLabel
    Position.X = 424.000000000000000000
    Position.Y = 168.000000000000000000
    Size.Width = 121.000000000000000000
    Size.Height = 17.000000000000000000
    Size.PlatformDefault = False
    Text = 'Label1'
    TabOrder = 2
  end
  object Label3: TLabel
    Position.X = 424.000000000000000000
    Position.Y = 192.000000000000000000
    Size.Width = 121.000000000000000000
    Size.Height = 17.000000000000000000
    Size.PlatformDefault = False
    Text = 'Label1'
    TabOrder = 1
  end
  object Label4: TLabel
    Position.X = 424.000000000000000000
    Position.Y = 216.000000000000000000
    Size.Width = 121.000000000000000000
    Size.Height = 17.000000000000000000
    Size.PlatformDefault = False
    Text = 'Label1'
    TabOrder = 0
  end
end

这是使用 Delphi 10.4 和 运行 在 Windows 10 中构建的。