Frage

Kann jemand bitte vorschlagen, wie soll ich Spalte per Drag-and-Drop implementieren (mit Autoscroll) Funktion in Datagridview. Ich weiß, ich kann den AllowUserToDragDrop Wahl des controll verwenden. Da jedoch meine Datagridview Steuerung relativ große Anzahl von Spalten hat, muß ich eine Auto-Scroll-Funktion, die die aktuelle Drag & Drop-Position folgt, so dass Benutzer die Zielspalt sehen (e) vor Abwurf. Ich habe die benutzerdefinierte Drag-and-Drop-Funktion implementiert, aber immer noch ich Problem habe Autoscroll Option zu aktivieren.

War es hilfreich?

Lösung

Ich bin die folgende Klasse mit Auto-Blättern eine TTreeView. Die TScroller wird in der Erstellen des Rahmens erstellt, auf dem er sitzt, in dem TreeView vorbei. Es wird Zerstören im Rahmen der zerstört. Im OnDragOver des TreeView ich einfach anrufen 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;

Weitere Informationen: Wenn Sie mehr Kontrollen haben die Notwendigkeit Auto-Scrolling, müssten Sie eine TScroller pro Steuerelement erstellen. In diesem Fall wäre es wahrscheinlich eine Menge guter Sie die Leistung Ihrer App tut irgendeine Art von Beobachtern / beobachteten Mechanismus zu verwenden, um einen Timer zwischen allen Scrolling-Kontrollen zu teilen.

Andere Tipps

Sie könnten OnMouseMove handhaben, und programmatisch blättern entsprechend.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top