0 votes

DataGridView : glisser-déposer de colonnes avec défilement horizontal automatique

Quelqu'un peut-il me suggérer comment mettre en œuvre la fonction de glisser-déposer de colonne (avec défilement automatique) dans DataGridView ? Je sais que je peux utiliser l'option AllowUserToDragDrop du contrôle. Cependant, comme mon contrôle DataGridView comporte un nombre relativement important de colonnes, j'ai besoin d'une fonction de défilement automatique qui suive la position actuelle du glisser-déposer afin que les utilisateurs puissent voir la ou les colonnes de destination avant de les déposer. J'ai implémenté la fonction personnalisée de glisser-déposer mais j'ai toujours des problèmes pour activer l'option de défilement automatique.

1voto

Marjan Venema Points 14626

J'utilise la classe suivante pour faire défiler automatiquement un TTreeView. Le TScroller est créé dans le Create du Frame sur lequel il se trouve, en passant par le TreeView. Il est détruit dans la fonction Destroy du cadre. Dans le OnDragOver du TreeView, j'appelle simplement 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;

Notes : Si vous avez plus de contrôles qui nécessitent un défilement automatique, vous devrez créer un TScroller par contrôle. Dans ce cas, les performances de votre application seraient probablement meilleures si vous utilisiez une sorte de mécanisme d'observateur/observé pour partager une minuterie entre tous les contrôles de défilement.

0voto

TreDubZedd Points 2070

Vous pourriez gérer OnMouseMove, et programmer le défilement en conséquence.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X