Recent

Author Topic: DragDrop Files in Listview  (Read 5945 times)

aradeonas

  • Hero Member
  • *****
  • Posts: 824
DragDrop Files in Listview
« on: March 05, 2015, 03:29:00 pm »
Hi,
As subject said I want drop files from explorer to a list view but I want to know mouse pointer X,Y so when file drag over of list view I could choose where of list drop file,End,middle or first.
I mad such thing but with a list item to that list again but I don't know how to make this with files from explorer.
http://forum.lazarus.freepascal.org/index.php/topic,26604.0.html
(the demo project in this post works but has a bug that seems it is Lazarus bug.)
« Last Edit: March 05, 2015, 03:37:57 pm by skalogryz »

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Re: DragDrop Files in Listview
« Reply #1 on: March 05, 2015, 03:38:07 pm »
corrected spelling in the topic name

aradeonas

  • Hero Member
  • *****
  • Posts: 824
Re: DragDrop Files in Listview
« Reply #2 on: March 05, 2015, 03:46:34 pm »
Thank you,My English is not really good.
I will appreciate helping the problem also.

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: DragDrop Files in Listview
« Reply #3 on: March 05, 2015, 04:41:38 pm »
I don't know how to get filenames dropped at specific locations in a list (if that is what you are asking). But the functionality for dropping files is already built-in to TForm, which provides an OnDropFiles event. Here's a simple example that you can build by adapting a new blank Lazarus project by adding an OnCreate and an OnDropFiles event.

Code: [Select]
unit mainFilesDragDrop;

{$mode objfpc}{$H+}

interface

uses
  Forms, Controls, ComCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDropFiles(Sender: TObject; const FileNames: array of String);
  private
    lv: TListView;
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.FormDropFiles(Sender: TObject; const FileNames: array of String);
var
  i: integer;
  li: TListItem;
begin
  lv.Clear;
  for i:=Low(FileNames) to High(FileNames) do begin
    li:=lv.Items.Add;
    li.Caption:=FileNames[i];
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  col: TListColumn;
begin
  AllowDropFiles:=True;
  Caption:='Drop Files example';

  lv:=TListView.Create(Self);
  lv.Align:=alClient;
  lv.ViewStyle:=vsReport;
  lv.Parent:=Self;

  col:=lv.Columns.Add;
  col.Caption:='Dropped Files';
  col.MinWidth:=ClientWidth;
  col.Width:=ClientWidth;
end;

end.


aradeonas

  • Hero Member
  • *****
  • Posts: 824
Re: DragDrop Files in Listview
« Reply #4 on: March 05, 2015, 04:44:46 pm »
Quote
I don't know how to get filenames dropped at specific locations in a list (if that is what you are asking).
Thank you howardpc but Im asking that.Just DragDrop file is not hard but find out where is the mouse pointer while DragOver to doping in specific locations is a question.

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: DragDrop Files in Listview
« Reply #5 on: March 05, 2015, 06:17:39 pm »
After a bit more thought...  %) ...try changing the FormDropFiles to this (you probably need to tweak it to get exactly the effect you want, and replace the hard-coded constants that apply for my Windows theme with something more generic):

Code: [Select]
procedure TForm1.FormDropFiles(Sender: TObject; const FileNames: array of String);
var
  i: integer;
  li: TListItem;
  mPt: TPoint;
  itemCount, index: integer;
begin
  mpt:=ScreenToClient(Mouse.CursorPos);
  itemCount:=lv.Items.Count;
  case itemCount of
   0: for i:=Low(FileNames) to High(FileNames) do begin
        li:=lv.Items.Add;
        li.Caption:=FileNames[i];
      end;
   else begin
          index:=(mPt.y - lv.Top - 23) div 20;
          if (index < 0) then
           index:=0;
          if (index > lv.Items.Count-1) then
           index:=lv.Items.Count-1;
          for i:=Low(FileNames) to High(FileNames) do begin
            li:=lv.Items.Insert(i+index);
            li.Caption:=FileNames[i];
          end;
   end;
  end;
end;   

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: DragDrop Files in Listview
« Reply #6 on: March 05, 2015, 06:42:33 pm »
I want drop files from explorer to a list view but I want to know mouse pointer X,Y

Use DragQueryPoint. When files are dropped on a form, Windows sends a message WM_DROPFILES that has a handle hDrop in wParam. Passing hDrop at this point to DragQueryPoint would give you the needed coordinates relative to the client area of the form. To catch WM_DROPFILES you have to change the window procedure of the form:
Code: [Select]
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  Windows;

type

  { TForm1 }

  TForm1 = class(TForm)
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormDropFiles(Sender: TObject; const FileNames: array of String);
  private
    PrvWndProc: LONG;
    DropPoint: POINT;
  public
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

function NewWndProc(hWnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
  if Msg=WM_DROPFILES then { get dropping point }
    DragQueryPoint(wParam, @Form1.DropPoint);

  Result := CallWindowProc(WNDPROC(Form1.PrvWndProc), hWnd, Msg, wParam, lParam)
end;

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  AllowDropFiles := True;

  { Change WndProc }
  PrvWndProc := SetWindowLong(Handle, GWL_WNDPROC, Long(@NewWndProc));
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  { Restore previous WndProc }
  SetWindowLong(Handle, GWL_WNDPROC, PrvWndProc);
end;

procedure TForm1.FormDropFiles(Sender: TObject; const FileNames: array of String
  );
begin
  Memo1.Lines.Add(Format('Dropping point - x: %d, y: %d',[DropPoint.x, DropPoint.y]));
end;

end.

aradeonas

  • Hero Member
  • *****
  • Posts: 824
Re: DragDrop Files in Listview
« Reply #7 on: March 05, 2015, 07:21:18 pm »
Thank you both, howardpc your way is interesting ;) do you know how getting the mouse pointer while dragging file? so we can paint an splitter line in view so user find out where file will drop.

engkin your way is classic but I should ask what I ask howardpc about mouse pointer while dragging.
And also I want to ask about  changing and restoring WndProc,why you do this? can you explain it in short for me?

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: DragDrop Files in Listview
« Reply #8 on: March 05, 2015, 08:09:48 pm »
I should ask what I ask howardpc about mouse pointer while dragging.

AFAIK, Windows does not let you know when file dragging process starts, not through classic programming in my example.

And also I want to ask about  changing and restoring WndProc,why you do this? can you explain it in short for me?

LCL filters some messages and does not pass them to the form. To catch these messages you have to override (or subclass) the window procedure of the form. That's what I did.

aradeonas

  • Hero Member
  • *****
  • Posts: 824
Re: DragDrop Files in Listview
« Reply #9 on: March 05, 2015, 08:16:37 pm »
Thank you engkin,Interesting point.

 

TinyPortal © 2005-2018