views:

51

answers:

2

I have set up a file extension in the Registry for my program as Windows requires.

In the Registry, under shell/open/command, I've got:

"C:\MyProgramPath\MyProgram.exe" "%1" 

This works fine for me. When someone clicks on one or more files associated with my application, my application correctly opens the file(s) but each one is opened in a separate program instance.

Is there any way I can do this and open up all files in one program instance?

+2  A: 

This is a rather common question, and it has really nothing to do with Windows file extensions. When you doubleclick a file of your program's custom type, Windows will start the associated application MyProgram.exe and pass the file name %1 as a command-line argument.

Now, if you want only a single instance of your application, you need to do this:

  1. When your program (MyProgram.exe) starts, it should check if there is already an instance of it running.
  2. If there is a previous instance, the new instance of MyProgram.exe should send a message (of some kind, not necessarily a windows message) to the old instance telling it to open the file %1.
  3. The new instance should now terminate itself.

A very simplistic approach

There are several ways of accomplishing this. One of the simplest ways is to set a registry key/value each time your application starts, and remove it when the application exists. Then, when (a new instance of) your application starts, prior to setting this key/value, it should check if it is already set. If, so, follow the steps (2) and (3) above. This might not be the most stable approach (in fact it is a very bad idea, since you cannot guarantee that the app will remove the key/value when it exists if it does so abnormally), but it will give you the basic idea. Other, perhaps better ways, include FindWindow and, even better, the use of mutexes.

Step two might be implemented by sending a windows message (maybe WM_COPYDATA), or by setting a registry value, or, by writing a file, or ... There are many ways of communication between different processess.

The details

Since this is a rather common question, it has been dealt with before. See, for instance, this Delphi-specific article.

Andreas Rejbrand
@Andreas: Unfortunately, building this into my program would always prevent multiple instances. But that's not what I want. If file A is clicked on, I want it in instance 1. If then file B is clicked on, then I want it in instance 2. However if both A and B are clicked on in the same click, then they will be 2 parameters passed to the program at once, and I want them both opened in one instance. Why do I want that? So that it will have the same effect as running my program from the command line with 2 parameters, or dragging and dropping 2 files to my program. Thanks, but this doesn't help me.
lkessler
@Ikessler: I see. I did not understand that you meant like so. Maybe you should write this in your question?
Andreas Rejbrand
@Andreas: Sorry for not mentioning it earlier, but I didn't realize that it was relevant until you gave your answer. Thanks very much for the time you took to write your detailed answer.
lkessler
+1  A: 

You can when using DDE. See http://cc.embarcadero.com/Item/17787 for an example in Delphi.

EDIT:

The link you gave talks about another method: using IDropTarget. This might fit better with your already running drag and drop capabilities.

Lars Truijens
@Lars: At the MSDN page I link to, it says "Note: The DDE method is being deprecated; use the DropTarget method instead." I'm having trouble figuring out how to set up the IDropTarget in Delphi. Should I go with DDE anyway?
lkessler
@Lars: Seems IDropHandler is the way to go. Now all I've got to do is figure out how to do that. I've asked another question for help on that at: http://stackoverflow.com/questions/3613333/how-do-i-get-droptarget-to-work-with-my-drop-handler-in-delphi
lkessler