Article

From:
To:
Norm Carlberg
Subject:
Re: How to programmiclly drag and drop a file onto a window? [Edit]
Newsgroup:
embarcadero.public.delphi.nativeapi

Re: How to programmiclly drag and drop a file onto a window? [Edit]

<Norm Carlberg> wrote in message news:✉forums.embarcadero.com...

> The following link and other code are as close as I could find however
> neither work.
> I am only dragging 1 file if that will simplify any.
> Errors?
> Improvements?
> <EDIT: I am dragging to another application, not receiving a dragged file.

The "preferred" way to pass data around is to implement the IDataObject and
IDragSource interfaces in your code.  Microsoft wants you to use the Win32 
API DoDragDrop() function, however since you want to send data to a specific 
window, that will not work as DoDragDrop() is an interactive function that 
requires human action to do its work.  There is no official way to get an 
IDropTarget interface from a specific HWND, but there is an unofficial way 
(untested):

{code:delphi} var   DT: IDropTarget; begin   DT := IDropTarget(GetProp(hWnd, 'OleDropTargetInterface'));   ... end; {code}
With that (assuming it works), you can then call the IDropTarget.DragEnter() method to ask the other app for permission to "drop" your data, and then if allowed call the IDropTarget.Drop() to do the actual drop.
> procedure DoDropFiles(Wnd: HWND; Files: TStringList);

To future-proof the code if you ever upgrade to D2009+ later on, you should 
take SizeOf(Char) into account in your calculations.  That way, the code 
seemlessly switches to Unicode without requiring any code changes, eg:

{code:delphi} var   ...   Run: PByte; // not PChar   ... begin   ...   // number of characters per string plus one #0 terminator   Inc(Size, (Length(Files[I]) + 1) * SizeOf(Char));   ...   // entire string list is terminated by another #0, add drop files structure size too   Inc(Size, SizeOf(Char) + SizeOf(TDropFiles));   ...   fWide := (SizeOf(Char) > SizeOf(AnsiChar));   ...   Inc(Run, (Length(Files[I])+1) * SizeOf(Char))   ...   // put a final #0 character at the end   PChar(Run)^ := #0; end; {code}
>    PostMessage(Wnd, WM_DROPFILES, MemHandle, 0);
>    // ... and finally release the memory
>    GlobalFree(MemHandle);

You are freeing the memory right away, not giving the other process any 
chance to use it.  Either use SendMessage() instead of PostMessage() so you 
know when the message has finished being processed, or else simply do not 
free the memory at all.  If the other window processes WM_DROPFILES 
messages, then it should be calling DragFinish() to free the memory on its 
end.  If it does not, the memory is leaked.

Also, in order for the other window to know that it should process WM_DROPFILES messages at all, it had to have actively called DragAcceptFiles() on itself beforehand. There is no way for your app to detect whether it has done that or not.
-- Remy Lebeau (TeamB)
FYI: Phrase searches are enclosed in either single or double quotes
 
 
Originally created by
Tamarack Associates
Fri, 17 May 2024 17:34:32 UTC
Copyright © 2009-2024
HREF Tools Corp.