Recent

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

valter.home

  • Jr. Member
  • **
  • Posts: 81
(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: 11830
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.

sstvmaster

  • Sr. Member
  • ****
  • Posts: 299
Re: Drag and Drop from Windows Explorer
« Reply #2 on: April 12, 2021, 11:37:51 pm »
For it works also.
greetings Maik

Windows 10,
- Lazarus 2.2.6 (stable) + fpc 3.2.2 (stable)
- Lazarus 2.2.7 (fixes) + fpc 3.3.1 (main/trunk)

valter.home

  • Jr. Member
  • **
  • Posts: 81
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: 11830
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?

valter.home

  • Jr. Member
  • **
  • Posts: 81
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

valter.home

  • Jr. Member
  • **
  • Posts: 81
Re: Drag and Drop from Windows Explorer
« Reply #6 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?

valter.home

  • Jr. Member
  • **
  • Posts: 81
Re: Drag and Drop from Windows Explorer
« Reply #7 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.


valter.home

  • Jr. Member
  • **
  • Posts: 81
Re: Drag and Drop from Windows Explorer
« Reply #8 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.



Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1311
    • Lebeau Software
Re: Drag and Drop from Windows Explorer
« Reply #9 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: 81
Re: Drag and Drop from Windows Explorer
« Reply #10 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