Recent

Author Topic: (SOLVED) Drag and Drop from Windows Explorer  (Read 644 times)

valter.home

  • Jr. Member
  • **
  • Posts: 64
(SOLVED) Drag and Drop from Windows Explorer
« on: April 12, 2021, 11:06:38 pm »
I'm trying to figure out how to use drag and drop files from the windows explorer to my application.
I found several info and examples but none of them seem to work.
So I started from scratch by creating an empty form.
According to a post this should work:

Code: Pascal  [Select][+][-]
  1. AllowDropFiles := true;

and therefore

Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormDropFiles(Sender: TObject; const FileNames: array of String);
  2. var
  3.   i: Integer;
  4. begin
  5.   for i := Low(FileNames) to High(FileNames) do
  6.      DoSomeThingWithFile(FileNames[i]);
  7.   // ShowMessage('Ok');
  8. end;

Nothing is happening.

This is a minimal example but I have tried several others with no success.

Another example;

Code: Pascal  [Select][+][-]
  1. function CreateFileDropSite(const AControl: TControl;
  2.   const ADropFilesEvent: TDropFilesEvent): TForm;
  3. begin
  4.   Result := TForm.Create(AControl);
  5.   Result.AllowDropFiles := True;
  6.   Result.BorderStyle := bsNone;
  7.   Result.BoundsRect := AControl.BoundsRect;
  8.   Result.Align := AControl.Align;
  9.   Result.Parent := AControl.Parent;
  10.   Result.OnDropFiles := ADropFilesEvent;
  11.   AControl.Parent := Result;
  12.   AControl.Align := alClient;
  13.   Result.Visible := True;
  14. end;

Code: Pascal  [Select][+][-]
  1. procedure TMainForm.FormCreate(Sender: TObject);
  2. begin
  3.   LD1 := CreateFileDropSite(shelllistview3, @FormDropFiles);
  4. end;
  5.  

Code: Pascal  [Select][+][-]
  1. procedure TMainForm.FormDropFiles(Sender: TObject;
  2.   const FileNames: array of String);
  3. begin
  4.   if Sender = LD1 then
  5.   begin
  6.     ShowMessage('Ok');
  7.   end;
  8. end;
  9.  

or:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormCreate(Sender: TObject);
  2. begin
  3.   AllowDropFiles:= True;
  4.   DragAcceptFiles(Handle, False);
  5.   DragAcceptFiles(memo1.Handle, True);
  6. end;

Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormDropFiles(Sender: TObject; const FileNames: array of String);
  2. begin
  3.   if Length(FileNames) > 0 then
  4.     memo1.lines.add := FileNames[0];
  5. end;

I have no problem with drag and drop inside my application but from the outside I can't get over it.
Is there something I'm missing?
(Lazarus ver. 2.0.12)

« Last Edit: April 13, 2021, 10:54:34 am by valter.home »

wp

  • Hero Member
  • *****
  • Posts: 8410
Re: Drag and Drop from Windows Explorer
« Reply #1 on: April 12, 2021, 11:35:49 pm »
Your first minimal example is working for me correctly - see attached project.
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

sstvmaster

  • Full Member
  • ***
  • Posts: 243
Re: Drag and Drop from Windows Explorer
« Reply #2 on: April 12, 2021, 11:37:51 pm »
For it works also.
Windows 10 (64 bit)
Lazarus: 2.0.12 / Trunk x32

valter.home

  • Jr. Member
  • **
  • Posts: 64
Re: Drag and Drop from Windows Explorer
« Reply #3 on: April 12, 2021, 11:42:37 pm »
I downloaded your code, nothing happens to me.
The cursor changes icon but when I release the button absolutely nothing happens.
What version of Lazarus do you have?
« Last Edit: April 12, 2021, 11:45:14 pm by valter.home »

wp

  • Hero Member
  • *****
  • Posts: 8410
Re: Drag and Drop from Windows Explorer
« Reply #4 on: April 12, 2021, 11:56:21 pm »
Tested Laz 2.0.12, 2.0.10 and Laz trunk, both with FPC 3.2.0 (32 bit and 64 bit) on Win 10/64 bit, as well as Laz 2.0.12/FPC 3.2 on LMDE 4 Linux (64 bit)

What is your OS?
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

valter.home

  • Jr. Member
  • **
  • Posts: 64
Re: Drag and Drop from Windows Explorer
« Reply #5 on: April 13, 2021, 12:08:15 am »
Win 10 64bit
I am attaching a short video.
https://streamable.com/w0l4g3

jamie

  • Hero Member
  • *****
  • Posts: 4468
Re: Drag and Drop from Windows Explorer
« Reply #6 on: April 13, 2021, 12:23:01 am »
Try this..

Set your BorderStyle before you set the form to accept Dropped files.

A window handle is required to register the form as a drop target and when set the boarderstyle the LCL recreates the window which now has a different handle and your attempt to a dropped target is now gone...

 Recreating windows isn't a good idea because this is a perfect example of how handles get lost in the wild.

 I am not saying this will fix your problem but its a easy try..
The only true wisdom is knowing you know nothing

valter.home

  • Jr. Member
  • **
  • Posts: 64
Re: Drag and Drop from Windows Explorer
« Reply #7 on: April 13, 2021, 12:30:37 am »
I did some tests and I found that if I run the compiled application it works fine. Inside Lazarus, even with Without Debugging mode, it doesn't work.
Some idea? Any parameters to set?

jamie

  • Hero Member
  • *****
  • Posts: 4468
Re: Drag and Drop from Windows Explorer
« Reply #8 on: April 13, 2021, 12:36:44 am »
Did you try my suggestion of setting your borderstyle before you set the form to accept dropped files?
The only true wisdom is knowing you know nothing

valter.home

  • Jr. Member
  • **
  • Posts: 64
Re: Drag and Drop from Windows Explorer
« Reply #9 on: April 13, 2021, 12:51:11 am »
But are you referring to the second example?

At the moment I have this very simple code:

Code: Pascal  [Select][+][-]
  1. AllowDropFiles := true;

Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormDropFiles(Sender: TObject; const FileNames: array of String);
  2. var
  3.   i: Integer;
  4. begin
  5.   ShowMessage('Hello');
  6. end;

If I start the application from inside Lazarus I don't get any ShowMessage, if I start the compiled application directly from the folder it works fine.

Now I try my second example code following your advice.
But I don't understand why the first simple version works for everyone and not for me.


jamie

  • Hero Member
  • *****
  • Posts: 4468
Re: Drag and Drop from Windows Explorer
« Reply #10 on: April 13, 2021, 12:59:03 am »
I blame everything on Aliens ! :o
The only true wisdom is knowing you know nothing

valter.home

  • Jr. Member
  • **
  • Posts: 64
Re: Drag and Drop from Windows Explorer
« Reply #11 on: April 13, 2021, 01:04:12 am »
I tried your suggestion with this code:

Code: Pascal  [Select][+][-]
  1. LD1: TForm;

Code: Pascal  [Select][+][-]
  1. function CreateFileDropSite(const AControl: TControl;
  2.   const ADropFilesEvent: TDropFilesEvent): TForm;
  3. begin
  4.   Result := TForm.Create(AControl);
  5.   Result.BorderStyle := bsNone;
  6.   Result.AllowDropFiles := True;
  7.   Result.BoundsRect := AControl.BoundsRect;
  8.   Result.Align := AControl.Align;
  9.   Result.Parent := AControl.Parent;
  10.   Result.OnDropFiles := ADropFilesEvent;
  11.   AControl.Parent := Result;
  12.   AControl.Align := alClient;
  13.   Result.Visible := True;
  14. end;

Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormCreate(Sender: TObject);
  2. begin
  3.   LD1 := CreateFileDropSite(listbox1, @FormDropFiles);
  4. end;

Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormDropFiles(Sender: TObject; const FileNames: array of string);
  2. var
  3.   fn: String;
  4. begin
  5.   if Sender = LD1 then
  6.   begin
  7.     for fn in FileNames do
  8.       Listbox1.Items.Add(fn)
  9.   end;
  10. end;

Unfortunately nothing changes. Using Run or Run without debugging from inside Lazarus in the TListBox nothing is displayed, starting the executable from its folder instead everything works fine.



jamie

  • Hero Member
  • *****
  • Posts: 4468
Re: Drag and Drop from Windows Explorer
« Reply #12 on: April 13, 2021, 01:51:18 am »
Have you tried putting a break point at the start of the event and run it in debug mode? It would be interesting if the event is actually working and maybe the code to populate the Tlistbox is failing some how ?

The only true wisdom is knowing you know nothing

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 921
    • Lebeau Software
Re: Drag and Drop from Windows Explorer
« Reply #13 on: April 13, 2021, 02:19:27 am »
A window handle is required to register the form as a drop target and when set the boarderstyle the LCL recreates the window which now has a different handle and your attempt to a dropped target is now gone...

One would expect TForm to handle that re-creation internally and automatically register the new window as a drop target if the old window was registered.

I did some tests and I found that if I run the compiled application it works fine. Inside Lazarus, even with Without Debugging mode, it doesn't work.
Some idea? Any parameters to set?

That would imply that Lazarus is interfering with the drop.  For instance, if Lazarus is running elevated, and thus the app gets run elevated.  Lower-integrity processes can't send window messages to higher-integrity processes, unless they explicitly allow it.  Try using ChangeWindowMessageFilter/Ex() to allow WM_DROPFILES, WM_COPYDATA, and WM_COPYGLOBALDATA ($0049) to pass through UIPI.  That should allow files to be dragged from a lower-integrity Windows Explorer.
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

valter.home

  • Jr. Member
  • **
  • Posts: 64
Re: Drag and Drop from Windows Explorer
« Reply #14 on: April 13, 2021, 10:53:25 am »
Thank you all for taking part in this discussion and finally allowing the solution of this strange problem
Yes Remy, you're right. I don't remember why but a long time ago I had to set Lazarus with administrator privileges. Despite subsequent updates to the new versions, the link to start the IDE has always remained configured like this.
Now it works, thanks for suggesting it.

 

TinyPortal © 2005-2018