Pregunta

Puede alguien por favor sugerir cómo debería implementar arrastrar y soltar la columna (con desplazamiento automático) en función DataGridView. Sé que puedo utilizar la opción AllowUserToDragDrop del controll. Sin embargo, desde mi control DataGridView tiene relativamente gran número de columnas, necesito una función de desplazamiento automático que sigue a la posición actual de arrastrar y soltar para que los usuarios puedan ver la columna de destino de la (s) antes de caer. He implementado el arrastre de encargo y soltar, pero todavía estoy teniendo problemas para activar la opción de desplazamiento automático.

¿Fue útil?

Solución

Estoy utilizando la siguiente clase que se desplace automáticamente un TTreeView. El TScroller se crea en el marco de la Creación en la que se asienta, que pasa en el TreeView. Se destruye en el marco de destruir. En el OnDragOver del TreeView simplemente llamar MyDragScroller.Scroll (Estado);

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;

Notas: Si usted tiene más controles que necesitan auto-desplazamiento, lo que se necesita para crear un TScroller por el control. En ese caso, probablemente haría el rendimiento de la aplicación mucho bien a utilizar algún tipo de mecanismo de observador / observado que compartir un contador de tiempo entre todos los controles de desplazamiento.

Otros consejos

Se puede manejar OnMouseMove y programáticamente desplazamiento en consecuencia.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top