Перетаскивание столбца DataGridView с автоматической горизонтальной прокруткой - PullRequest
0 голосов
/ 21 мая 2010

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

Ответы [ 2 ]

1 голос
/ 29 мая 2010

Я использую следующий класс для автоматической прокрутки TTreeView. TScroller создается в Create the Frame, на котором он сидит, передавая TreeView. Это уничтожено в Разрушении структуры. В OnDragOver TreeView я просто вызываю MyDragScroller.Scroll (State);

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 для каждого элемента управления. В этом случае, вероятно, будет полезно для производительности вашего приложения использовать некоторый механизм наблюдения / наблюдения, чтобы разделить таймер между всеми элементами управления прокруткой.

0 голосов
/ 21 мая 2010

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

...