Link to home
Start Free TrialLog in
Avatar of glx2k
glx2k

asked on

Simulate drag 'n' drop

Hi

I want to use drag 'n' drop to add a list of files to another program, programmely. That means without touching the mouse, is that posible, perhaps I could just send a message of some kind?
I have the handle to the window that should receive the files.
Avatar of ginsonic
ginsonic
Flag of Romania image

list
Avatar of albay
albay

listening...
hi glx2k
this is not good. but worth to try

//this example send the file names to a listbox in another program.

procedure TForm1.Button1Click(Sender: TObject);
var xHandle:HWND; i:integer;
begin
   xHandle:=StrToInt(Edit1.Text);
  for i:=0 to FileListBox1.SelCount-1 do begin
   if FileListBox1.Selected[i] then
    //you have to know window handle and already you know.
    try SendMessage(xHandle, LB_ADDSTRING,0,integer(FileListBox1.Items.Strings[i]));
    except
    end;
  end;
end;

regards,
albay
set MultiSelect property of FileListBox to true.
Mmh, I have never done this but worked quite a lot with drag'n drop (including OLE). What you could do is to simulate the WM_DROPFILES message. This message is accompanied with a handle to a global memory object which you can allocate with GlobalAlloc. The handle must be locked (in both cases, when writing and when reading) to get a pointer to the memory. This memory receives then the file names in CF_HDROP format.

Should work I believe...

Ciao, Mike
Avatar of glx2k

ASKER


Avatar of glx2k

ASKER

albay:
I coun't get your ex to work


Lischke:
Hmmm seems interresting but very difficult :-)

I have found some code in the Drag and Drop Component Suite - DropSource.pas - the ConvertFilesToShellIDList function, that I think may work.

I copied the function and some others to my project. I then tried to send the dropdown message to my own project which receives files just fine. But it didn't work, any suggestions?
If you want the dropsource.pas you can get it from http://www.melander.dk/delphi/dragdrop/ or give me your email and I will send it to you.

var
    FilesHandle: THandle;
    strlst: tstringlist;
begin
    strlst := tstringlist.create;
    strlst.add('a.exe');
    FilesHandle := ConvertFilesToShellIDList('d:\',strlst);

    sendmessage(handle,
                WM_DropFiles,
                FilesHandle,
                0);

    strlst.Free;
end;
Well, you said you have received the drop file structure in your own program. Then you wrote it did not work. What did not work? Was it that you did not get the same memory handle or the memory did not contain what you put in or what else do you mean?

Ciao, Mike
hi glx2k
you said "I have the handle to the window that should receive the files."

ok. my example sends the file names to only listbox that you know the handle number.
in editbox, write handle number of listbox on another program you know and click button. that's all. and multiselect property of FileListBox should be True to send multiselected files. if you didn't do that, you would see nothing in ListBox.

regards,
albay
Avatar of glx2k

ASKER

Lischke
As Í said I used the Drag and drop components, to receive the dropfiles message. I don't know anything about drag'n'drop.

albay:
I don't understand you talk about sending strings with filenames, but that is not the same as sending files!
glx2k, you should be a bit more specific, otherwise I can only guess around. You said you have send the WM_DROPFILES message to your own application which "...accepts files just fine". Does this mean that you have registered a window of your application as drop file target? Does this mean you can accept files dropped from, say, the Explorer? Does this mean you don't get correct results from the fake message?

For files and file names, you should be aware that WM_DROPFILES also carries just file names, not file contents. The ConvertFilesToShellIDList from Anders creates a similar but not equal to CF_DROP format structure. Actually, it fills the structure with PIDLs not file names. WM_DROPFILES accepts only file names, however.

To ease the creation of the TDropFiles structure you can use Anders' suite. See TFileClipboardFormat.WriteData which will be given a pointer (you can pass your locked handle there) and fill the memory with the data. You should however copy out the few lines of code instead using the large library.

Ciao, Mike
Avatar of glx2k

ASKER

I can answer yes to all your questions.
I send the fake message to my own program, because Im sure I have got the right handle and I can debug the dropping of files.
But the "only" thing I have done to my program is putting Anders component on the form.

But I don't understand the WriteData function, if you know how to do it, wouldn't you be so kind to create an exampel, please :-)
ASKER CERTIFIED SOLUTION
Avatar of Lischke
Lischke

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Ah yes, just for completeness (to test at least) here the receiver function:

procedure TMainForm.WMDropFiles(var Msg: TWMDropFiles);

var
  Buffer: array[0..MAX_PATH] of Char;
  Count, I: Integer;
  List: TStringList;

begin
  Count := DragQueryFile(Msg.Drop, DWORD(-1), nil, 0);
  List := TStringList.Create;
  try
    for I := 0 to Count - 1 do
    begin
      DragQueryFile(Msg.Drop, I, Buffer, MAX_PATH);
      List.Add(Buffer);
    end;
    AddProjectFiles(List);
  finally
    List.Free;
  end;
  DragFinish(Msg.Drop);
  Msg.Result := 0;
end;


Ciao, Mike
Avatar of glx2k

ASKER

Very great just what I needed
you should however change the sendmessage to postmessage (just before you free memhandle).

I tried to use the code to fake my own app, but it didn't work, strange, perhaps the Drag'n'Drop Target component works that way.

Well I tested it on the app I should use the code with and it worked fine :-)

THANKS!!
:-) Glad to help. Of course some more efforts need to be made to avoid releasing memory when it is still used (as you pointed out) and also whether the memory can be allocated at all. Btw. I have checked the code above using the sender application being also the receiver and it worked fine. Perhaps the drag'n drop suite from Anders is somehow mixing up the drop files message in your own application (or you have the wrong window handle? or DragAcceptFiles has not been called for the used window?).

Ciao, Mike

PS: This was the 500. question I answered here at E-E (moving me over the 200K overall points barrier), so I should make a small celebration and thank you :-)))
Avatar of glx2k

ASKER

I'm glad to give you some points, you really deserve it
Avatar of glx2k

ASKER

I have some problems coping more than one file with the code, if I try to add more than one file, the last filename in the in the stringlist is the only one I see.

Also I can't get it to work with SendMessage, only PostMessage can this mean anything?
Avatar of glx2k

ASKER

Hmm I changed a line to this
Inc(Run, Length(Filenames[I])+1)

from this

Inc(Run, Length(Filenames[I]))

and it seems to work
Oops, stupid me. I'm astonished how I could have overlooked this mistake? And I wondered why the code works from the very first moment on. Have you ever seen code which does not have any bug :-)?

Ciao, Mike