2

I am writing a MDI Text Editor and I was wondering how can I open all text files with my app. (If I associate te *.txt to my app I want that each time someone double-clicks on a txt file to open it in my app, in a new child window)

thanks

skamradt
  • 15,366
  • 2
  • 36
  • 53
Remus Rigo
  • 1,454
  • 8
  • 34
  • 60
  • Duplicate: http://stackoverflow.com/questions/600490/how-to-open-multiple-files-with-delphi-program-invoked-via-shell-open – Rob Kennedy Oct 26 '09 at 21:11
  • Not exactly a duplicate, this questing is asking how to open additional files into an already running application. – skamradt Oct 26 '09 at 21:40
  • open additional files into an already running application is what i want – Remus Rigo Oct 26 '09 at 21:42
  • How to run a single instance of an application http://www.delphidabbler.com/articles?article=13 – Remus Rigo Oct 26 '09 at 22:08
  • Controlling the number of application instances http://delphi.about.com/od/windowsshellapi/l/aa100703a.htm – Remus Rigo Oct 26 '09 at 22:19
  • @Remus: The [delphi] StackOverflow question dealing with your problem is http://stackoverflow.com/questions/512366/how-do-i-send-a-string-from-one-instance-of-my-delphi-program-to-another – mghie Oct 27 '09 at 05:04

4 Answers4

4

The solution to this is also the solution to not allowing more than one application to run at the same time. What you want to do is first detect that the program is already running, then pass a parameter to the running application and shut down.

There are several methods to determine if your application is already running. Once you pick one that fits your programming preferences, the next step is to feed the file to open to your running program. This can be done via named pipes, messages (although messages do fail on Vista/Win7 if your app is running in another security context), or any other method of IPC.

skamradt
  • 15,366
  • 2
  • 36
  • 53
  • Good points, but how likely are you to have two instances of the same user app running with different security priveliges? :p – Mason Wheeler Oct 27 '09 at 01:01
  • Only have to run the first copy "as administrator" to then separate all later "double clicks" from sending messages to the first application. – skamradt Oct 27 '09 at 18:13
2

I Currently have the following implementation for this :

The .dpr file

var
  PrevWindow : HWND;
  S : string;
  CData : TCopyDataStruct;

begin
  PrevWindow := 0;
  if OpenMutex(MUTEX_ALL_ACCESS, False, 'YourUniqueStringHere') <> 0 then
    begin
      PrevWindow:=FindWindow('TYourMainFormClassName', nil);

      if IsWindow(PrevWindow) then
      begin
        SendMessage(PrevWindow, WM_SYSCOMMAND, SC_RESTORE, 0);
        BringWindowToTop(PrevWindow);
        SetForegroundWindow(PrevWindow);

        if FileExists(ParamStr(1)) then
        begin
          S:=ParamStr(1);
          CData.dwData:=0;
          CData.lpData:=PChar(S);
          CData.cbData:=1+Length(S);

          SendMessage(PrevWindow, WM_COPYDATA, 0, DWORD(@CData) );
        end;
      end;
    end
  else
    CreateMutex(nil, False, 'YourUniqueStringHere');

in the main unit we process the WM_COPYDATA message :

we declare the message handler

procedure ReceiveData_Handler ( var msg : TWMCopyData ) ; message WM_COPYDATA;


procedure TForm1.ReceiveData_Handler(var msg: TWMCopyData);
begin
  // Your file name is in the msg.CopyDataStruct.lpData
  // Cast it to PChar();
end;

Hope it works for you.

zz1433
  • 3,528
  • 2
  • 28
  • 36
  • 1
    Your code contains a race condition, it should always call `CreateMutex()` and check whether `GetLastError()` returns `ERROR_ALREADY_EXISTS`. See http://msdn.microsoft.com/en-us/library/ms682411%28VS.85%29.aspx. And I find the general lack of error handling disturbing... – mghie Oct 27 '09 at 13:26
1

Check out the Windows DDE documentation. I modify the DDEExec options in the registry, so the shell correctly directs the opened file to my existing application instance. The following code makes the registry changes necessary. Replace "AppName" with your application name (and remove the brackets).

     // add the ddeexec key
     if not reg.OpenKey( '\Software\Classes\<AppName>.file\shell\open\ddeexec', true ) then
        raise Exception.Create( 'Error setting ddeexec key' );

     try
        reg.WriteString( '', 'FileOpen("""%1""")' );
     finally
        reg.CloseKey;
     end;

     // modify the command key to not include the parameter, as we don't use it
     if not reg.OpenKey( '\Software\Classes\<AppName>.file\shell\Open\command', true ) then
        raise Exception.Create( 'Error opening command key.' );

     try
        strTemp := reg.ReadString( '' );

        strTemp := StringReplace( strTemp, '"%1"', '', [] );
        reg.WriteString( '', strTemp );

     finally
        reg.CloseKey;
     end;
Jeremy Mullin
  • 4,170
  • 4
  • 36
  • 54
0

I don't know the version of Delphi that you're using, but in Delphi 7 at the examples folder you will see a MDI Text Editor example.

Nathan Campos
  • 28,769
  • 59
  • 194
  • 300