Перетаскивание столбца DataGridView с автоматическим горизонтальным прокруткой

StackOverflow https://stackoverflow.com/questions/2877837

Вопрос

Может кто-нибудь, пожалуйста, предложите, как я должен реализовать столбец Drag и Drop (с помощью автоматического прокрутки) в DataGridView. Я знаю, что я могу использовать опцию AllowuserToDragdrop Однако, поскольку My DataGridView Control имеет относительно большое количество столбцов, мне нужен функция автоматической прокрутки, которая следует за текущим положением перетаскивания, чтобы пользователи могли видеть столбцы (ы) назначения, прежде чем падать. Я реализовал пользовательскую функцию перетаскивания, но все же у меня проблемы с возможностью включения автоматической опции прокрутки.

Это было полезно?

Решение

Я использую следующий класс для автоматического прокрутки Ttreeview. Tscroller создан в создании рамки, на котором он сидит, прохождение в TreeView. Это разрушено в разрушении кадра. В Ondragover дерева просмотра я просто звоню mydragscroller.scrolle (штат);

type
  TScroller = class(TObject)
  private
    MyTimer: TTimer;
    FControl: TWinControl;
    FSensitiveSize: Integer;
  protected
    procedure HandleTimer(Sender: TObject);
  public
    constructor Create(aControl: TWinControl);
    destructor Destroy; override;

    procedure Scroll(const aState: TDragState);
  end;

implementation

{ TScroller }

constructor TScroller.Create(aControl: TWinControl);
begin
  inherited Create;
  MyTimer := TTimer.Create(nil);
  MyTimer.Enabled := False;
  MyTimer.Interval := 20; // Not too short, otherwise scrolling flashes by.
  MyTimer.OnTimer := HandleTimer;

  FControl := aControl;
  // Width/Height from edge of FControl within which the mouse has to be for
  // automatic scrolling to occur. By default it is the width of a vertical scrollbar.
  FSensitiveSize := GetSystemMetrics(SM_CXVSCROLL);
end;

destructor TScroller.Destroy;
begin
  FreeAndNil(MyTimer);
  FControl := nil;
  inherited;
end;

procedure TScroller.HandleTimer(Sender: TObject);
var
  MousePos: TPoint;
  MouseX: Integer;
  MouseY: Integer;

  function _MouseInSensitiveSize: Boolean;
  begin

    MousePos := FControl.ScreenToClient(Mouse.CursorPos);
    MouseY := MousePos.Y;
    MouseX := MousePos.X;

    Result :=
         ((MouseY >= 0) and (MouseY < FSensitiveSize))
      or ((MouseY > FControl.ClientHeight - FSensitiveSize) and (MouseY <= FControl.ClientHeight))
      or ((MouseX >= 0) and (MouseX < FSensitiveSize))
      or ((MouseX > FControl.ClientWidth - FSensitiveSize) and (MouseX <= FControl.ClientWidth))
    ;

  end;
begin
  if Mouse.IsDragging and _MouseInSensitiveSize then begin
    if MouseY < FSensitiveSize then begin
      FControl.Perform(WM_VSCROLL, SB_LINEUP, 0);
    end else if MouseY > FControl.ClientHeight - FSensitiveSize then begin
      FControl.Perform(WM_VSCROLL, SB_LINEDOWN, 0);
    end;

    if MouseX < FSensitiveSize then begin
      FControl.Perform(WM_HSCROLL, SB_LINELEFT, 0);
    end else if MouseX > FControl.ClientWidth - FSensitiveSize then begin
      FControl.Perform(WM_HSCROLL, SB_LINERIGHT, 0);
    end;
  end else begin
    MyTimer.Enabled := False;
  end;
end;

procedure TScroller.Scroll(const aState: TDragState);
begin
  if not Mouse.IsDragging then Exit;  // Only scroll while dragging.
  if not (aState in [dsDragMove]) then Exit; // No use scrolling on a dsDragLeave and not nice to do so on a dsDragEnter.

  MyTimer.Enabled := True;
end;

Примечания: Если у вас есть больше элементов управления, которые нуждаются в автоматическом прокрутке, вам нужно будет создать Tscroller за управление. В этом случае это, вероятно, сделает бы выполнение вашего приложения, очень хорошее использование какого-либо наблюдателя / наблюдаемого механизма для деления таймера между всеми элементами управления прокруткой.

Другие советы

Вы можете обрабатывать OnMouseMove и программически прокрутите соответственно.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top