对于FMX,TScrollBar的等效OnScroll事件是什么?

时间:2016-07-28 00:14:49

标签: delphi scrollbar firemonkey

我没有遇到Delphi 10 Seattle下TScrollBar的Event(OnScroll)处理程序的解决方案。我选择它是因为它不是我将把任何内容放入的TScrollBox(如Panel或DBGrid)。它只是检测鼠标动作(MouseUp / Down / Side-to-Side都没有工作),它将被用作文件搜索工具,它将强制一堆TeeCharts更新,基于在滚动的方向。

到目前为止,我只遇到了由WindowsMessages(WM_HScroll)和VLC.StdCtrls.TScrollBar.OnScroll

组成的难以理解的示例。

除了OnChange之外,检测ScrollBar移动的有效方法是什么?

能够操纵ScrollBar并将其自身重置在中间是有帮助的。就像我设置的值非常相似,如果我设置Min = -50和Max = 50(0)

1 个答案:

答案 0 :(得分:0)

要克服FMX TScrollBar的限制,您可以使用以下内容作为进一步增强的基础(部分受您提供的链接启发)。

如果您将使用滚动条滚动的控件具有(或可以配备)存储当前滚动位置的属性,您可以使用/定义类型single。对于测试,我只是将其定义为表单的私有属性,并将其命名为sbIncremental

我将TScrollBar的属性设置为Orientation = VerticalSmallChange = 10Max = 100Min = -100

然后,OnChange事件在我的测试中看起来像这样:

procedure TForm6.ScrollBarChange(Sender: TObject);
var
  sb: TScrollBar;
  sbOnChange: TNotifyEvent;
begin
  sb := (Sender as TScrollBar);
  sbIncremental := sbIncremental + sb.Value;

  Label1.Text := FloatToStr(sbIncremental); // Use the new value

  sbOnChange := sb.OnChange; // Disable OnChange event
  sb.OnChange := nil;         // -"-
  sb.Value := (sb.Min + sb.Max) / 2; // Reset position
  sb.OnChange := sbOnChange; // Re-enable OnChange event
end;

要将ScrollBar位置重置为中心,我们需要暂时禁用OnChange事件。

评论后更新。

正如我现在所理解的那样,你的问题是滚动条的视觉外观不会返回到零位置,即使它的值被改变(在OnChange内)为零(min = -100且max = 100为零)位置在中间)。单击箭头按钮时会发生这种情况,但如果拖动拇指按钮或单击拇指按钮的任一侧则不会。在OnChange事件中的这两种情况下似乎可以防止可视更新。此外,调用ScrollBar.Repaint不会更新视觉外观。我发现无法使用OnMouseDown / OnMouseUp事件。它们似乎没有内部联系?

这给我们留下了以下(hacky)解决方案:使用一个小延迟,比如300毫秒来启动计时器。发生超时时,滚动条已准备好接受新值更改并直观更新。计时器也有正面效果,拇指握柄在你点击时移动,然后向后移动。没有任何时间之间就没有可见的迹象表明事情发生了。

使用计时器时的OnChange事件处理程序

procedure TForm6.ScrollBarChange(Sender: TObject);
begin
  // Use the scrollbar value
  Label1.Text := FloatToStr((Sender as TScrollBar).Value);

  // Enable reset timer
  ScrollBarTimer.Enabled := False;
  ScrollBarTimer.Enabled := True;
end;

OnTimer事件

procedure TForm6.ScrollBarTimerTimer(Sender: TObject);
var
  sbOnChange: TNotifyEvent;
begin
  ScrollBarTimer.Enabled := False;

  sbOnChange := ScrollBar.OnChange; // store OnChange event
  ScrollBar.OnChange := nil;        // disable OnChange event
  ScrollBar.Value := (ScrollBar.Min + ScrollBar.Max) / 2; // reset position
  ScrollBar.OnChange := sbOnChange; // re-enable OnChange event
end;