delphi - 在边缘上方/附近拖动时滚动 TTreeView

标签 delphi treeview scroll

我有一个 TTreeView,它可以有很多节点,当展开很多节点时,树会使用大量屏幕空间。

现在假设我想将 TreeView 底部附近的节点拖到顶部,但我实际上看不到 TreeView 的顶部部分,因为我选择的节点位于底部。当将节点拖动到 TreeView 的顶部时,我希望 TreeView 在拖动时自动与我一起滚动,默认情况下这似乎不会发生。

Windows 资源管理器中可以看到这种行为的完美示例。如果您尝试拖动文件或文件夹,当您将鼠标悬停在拖动的项目(节点)上时,它会根据光标位置自动向上或向下滚动。

希望这是有道理的。

PS,我已经知道如何拖动节点,如果将鼠标悬停在 TreeView 的顶部或底部附近,我希望在拖动时 TreeView 能够与我一起滚动。

谢谢。

最佳答案

这是我使用的代码。它适用于任何 TWinControl 后代:列表框、 TreeView 、 ListView 等。

type
  TAutoScrollTimer = class(TTimer)
  private
    FControl: TWinControl;
    FScrollCount: Integer;
    procedure InitialiseTimer;
    procedure Timer(Sender: TObject);
  public
    constructor Create(Control: TWinControl);
  end;

{ TAutoScrollTimer }

constructor TAutoScrollTimer.Create(Control: TWinControl);
begin
  inherited Create(Control);
  FControl := Control;
  InitialiseTimer;
end;

procedure TAutoScrollTimer.InitialiseTimer;
begin
  FScrollCount := 0;
  Interval := 250;
  Enabled := True;
  OnTimer := Timer;
end;

procedure TAutoScrollTimer.Timer(Sender: TObject);

  procedure DoScroll;
  var
    WindowEdgeTolerance: Integer;
    Pos: TPoint;
  begin
    WindowEdgeTolerance := Min(25, FControl.Height div 4);
    GetCursorPos(Pos);
    Pos := FControl.ScreenToClient(Pos);
    if not InRange(Pos.X, 0, FControl.Width) then begin
      exit;
    end;
    if Pos.Y<WindowEdgeTolerance then begin
      SendMessage(FControl.Handle, WM_VSCROLL, SB_LINEUP, 0);
    end else if Pos.Y>FControl.Height-WindowEdgeTolerance then begin
      SendMessage(FControl.Handle, WM_VSCROLL, SB_LINEDOWN, 0);
    end else begin
      InitialiseTimer;
      exit;
    end;

    if FScrollCount<50 then begin
      inc(FScrollCount);
      if FScrollCount mod 5=0 then begin
        //speed up the scrolling by reducing the timer interval
        Interval := MulDiv(Interval, 3, 4);
      end;
    end;

    if Win32MajorVersion<6 then begin
      //in XP we need to clear up transient "fluff"; results in flickering so only do it in XP where it is needed
      FControl.Invalidate;
    end;
  end;

begin
  if Mouse.IsDragging then begin
    DoScroll;
  end else begin
    Free;
  end;
end;

然后要使用它,请为控件添加一个 OnStartDrag 事件处理程序并按如下方式实现:

procedure TMyForm.SomeControlStartDrag(Sender: TObject; var DragObject: TDragObject);
begin
  TAutoScrollTimer.Create(Sender as TWinControl);
end;

关于delphi - 在边缘上方/附近拖动时滚动 TTreeView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6243193/

相关文章:

scroll - 如何平滑滚动SWT composite?

javascript - 等待函数再次执行

c# - 用一对或多对字符之间的点确定单词排列的算法

c# - 如何导出C#编写的接口(interface)来实现TLB生成的Delphi代码

插入带有标签的行时,Tkinter Treeview 出现问题

wpf - 在 TreeView 中拖放,在节点之间插入

javascript - 为什么不能触发窗口滚动事件

delphi - 如何使用delphi在word中查找表格并更新表格中的值

Delphi 界面帮助程序/解决方法

javascript - 按项目的标题和描述过滤 TreeView 并显示父项的算法