2010-05-20 5 views
0

Quelqu'un peut-il suggérer comment je devrais implémenter la fonction glisser-déposer de colonne (avec défilement automatique) dans DataGridView. Je sais que je peux utiliser l'option AllowUserToDragDrop du contrôleur. Cependant, étant donné que mon contrôle datagridview a un nombre de colonnes relativement important, j'ai besoin d'une fonction de défilement automatique qui suit la position actuelle de glisser-déposer afin que les utilisateurs puissent voir les colonnes de destination avant de les déposer. J'ai mis en place la fonction de glisser-déposer personnalisée, mais j'ai toujours des problèmes pour activer l'option de défilement automatique.DataGridView Glisser-Déposer avec le défilement auto-horizontal

Répondre

1

J'utilise la classe suivante pour faire défiler automatiquement un TTreeView. Le TScroller est créé dans la création du cadre sur lequel il se trouve, en passant dans le TreeView. Il est détruit dans le 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; 

Remarques: Si vous avez plus de contrôles qui ont besoin de défilement automatique, vous devez créer un TScroller par commande. Dans ce cas, les performances de votre application seront probablement très utiles si vous utilisez un mécanisme observateur/observé pour partager une minuterie entre tous les contrôles de défilement.

0

Vous pouvez gérer OnMouseMove et faire défiler le programme en conséquence.

+0

Merci, j'ai essayé cela (en fait, j'ai essayé les deux événements OnMouseMove et OnDragDrop). Cela fonctionne bien, sauf qu'il ne fait pas défiler de manière flexible les directions arrière et avant. Quelle méthode de la barre de défilement horizontale recommanderiez-vous pour assigner la potion actuelle du curseur de la souris? – Bedasso

+0

Avez-vous regardé la propriété FirstDisplayedScrollingRowIndex? – TreDubZedd

+0

Oui, j'ai utilisé FirstDisplayedColumnIndex sur les événements spécifiés ci-dessus. Le tings est si le défilement automatique fonctionne de cette façon, ce n'est pas aussi pratique que cela devrait être pour l'utilisateur. – Bedasso