سؤال

هل يمكن لأي شخص أن يقترح كيف يمكنني تنفيذ ميزة السحب والإفلات (مع التمرير التلقائي) في DataGridView. أعلم أنه يمكنني استخدام خيار Control's ALTERUSERTODRAGDROP. ومع ذلك ، نظرًا لأن التحكم في DataGridView الخاص بي يحتوي على عدد كبير نسبيًا من الأعمدة ، فأنا بحاجة إلى ميزة التمرير التلقائي تتبع موضع drop-drop الحالي حتى يتمكن المستخدمون من رؤية عمود (عمود) الوجهة قبل الانخفاض. لقد قمت بتطبيق ميزة السحب والإفلات المخصصة ولكن ما زلت أواجه مشكلة لتمكين خيار التمرير التلقائي.

هل كانت مفيدة؟

المحلول

أنا أستخدم الفئة التالية لتفكيك TtreeView. يتم إنشاء tscroller في إنشاء الإطار الذي يجلس عليه ، يمر في TreeView. يتم تدميره في تدمير الإطار. في Ondragover من TreeView أنا ببساطة أسمي mydragscroller.scroll (الدولة) ؛

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 لكل عنصر تحكم. في هذه الحالة ، من المحتمل أن يقوم بأداء تطبيقك كثيرًا لاستخدام نوع من الآلية المراقب/الملاحظة لمشاركة مؤقت بين جميع عناصر التحكم في التمرير.

نصائح أخرى

يمكنك التعامل مع onMousemove ، والتمرير برمجي وفقا لذلك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top