views:

84

answers:

2

I have associated a file extension with my Delphi 2009 program. I have been using the command line call method to pass the filename to my Delphi program so it can be opened.

However, I found that when selecting multiple files, and clicking on them all at once, it opens each file in a separate instance of my program. I asked about this, and apparently the solution is to use one of the other two Windows methods: DDE or IDropTarget.

But DDE is being deprecated, and MSDN recommends the IDropTarget method. Also Lars Truijens in his answer to me, says that IDropTarget might fit better if I'm already running drag and drop capabilities, which I am.

Currently, this is my drop handler:

private
  procedure WMDropFiles(var WinMsg: TMessage);
            message wm_DropFiles;

procedure TLogoAppForm.FormShow(Sender: TObject);
begin
  DragAcceptFiles(Handle, true);
end;

procedure TLogoAppForm.WMDropFiles(var WinMsg: TMessage);
// From Delphi 3 - User Interface Design, pg 170
const
  BufSize = 255;
var
  TempStr : array[0..BufSize] of Char;
  NumDroppedFiles, I: integer;
  Filenames: TStringList;
begin
  NumDroppedFiles := DragQueryFile(TWMDropFiles(WinMsg).Drop, $ffffffff, nil, 0);
  if NumDroppedFiles >= 1 then begin
    Filenames := TStringList.Create;
    for I := 0 to NumDroppedFiles - 1 do begin
      DragQueryFile(TWMDropFiles(WinMsg).Drop, I, TempStr, BufSize);
      Filenames.Add(TempStr);
    end;
    OpenFiles(Filenames, '');
    Filenames.Free;
  end;
  DragFinish(TWMDropFiles(WinMsg).Drop);
  WinMsg.Result := 0;
end;

It now accepts one or multiple files and will open them as I require. It is very old code, from a Delphi 3 book, but it still seems to work.

What I can't find is any documentation anywhere on how to implement IDropHandler in Delphi, and specifically to get it working with the Drop Handler (above) that I am using.

Can someone tell me how to use IDropHandler so that clicking on selected files with my file extension will pass them to my Drop Handler and my program can open all the files clicked on?

+1  A: 

Use Delphi's wizards to add a standard COM out-of-process server object to your project, have it implement the IDropHandler interface (the article's code is in C++, but many of the the concepts can be applied to Delphi code as well, and some of them are already implemented by the VCL for you), and then override its virtual UpdateRegistry() method to add a couple of extra Registry keys (see the bottom of the above article) that are needed for your IDropHandler object to work with Windows Explorer double-clicking and popup menu operations.

Then, change your app code to use RegisterDragDrop() instead of DragAcceptFiles() so users can still drag-n-drop files onto your app's window via an instance of your IDropTarget-based class.

Inside your implementations of the IDropHandler methods, you can then query the passed-in IDataObject interface to see if it can provide its data in HDROP format, and if so then you can pass it to your existing WM_DROPFILES message handler (which is old and also deprecated, BTW, so you should consider removing it).

It sounds like a lot of work, but once you actually get into it, it is not very much at all. I recently implemented IDropTarget support in one of my C++Builder VCL apps and it did not take very long at all to get it working.

Once you have IDropTarget working, there are plenty of other Shell formats that you can then support if desired, such as when dropping data from non-filesystem sources.

Remy Lebeau - TeamB
Thanks @Remy. You gave me good information +1, but make me work for the code. @Lars was able to clue me to the code samples.
lkessler
+1  A: 

This page has an example of implementing IDropTarget in Delphi. Here is another from Jedi Code Formatter. But this library might be even better. It, amongst other things, enables dragging and dropping from Windows Explorer and therefore already supports IDropTarget in the TDropHandler class.

Lars Truijens
Thank you @Lars. That's what I needed. Delphi Dabbler also has another related useful article about a TFileCatcher class: http://www.delphidabbler.com/articles?article=11
lkessler