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.
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.
list
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.Te xt);
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(Fil eListBox1. Items.Stri ngs[i]));
except
end;
end;
end;
regards,
albay
this is not good. but worth to try
//this example send the file names to a listbox in another program.
procedure TForm1.Button1Click(Sender
var xHandle:HWND; i:integer;
begin
xHandle:=StrToInt(Edit1.Te
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(Fil
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
Should work I believe...
Ciao, Mike
ASKER
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:\',strl st);
sendmessage(handle,
WM_DropFiles,
FilesHandle,
0);
strlst.Free;
end;
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(
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
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
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
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!
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.Write Data 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
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.Write
Ciao, Mike
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 :-)
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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
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
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!!
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 :-)))
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 :-)))
ASKER
I'm glad to give you some points, you really deserve it
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?
Also I can't get it to work with SendMessage, only PostMessage can this mean anything?
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
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
Ciao, Mike