tags:

views:

211

answers:

4

hi all

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

A: 

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
+3  A: 

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
Good points, but how likely are you to have two instances of the same user app running with different security priveliges? :p
Mason Wheeler
Only have to run the first copy "as administrator" to then separate all later "double clicks" from sending messages to the first application.
skamradt
+1  A: 

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.

Aldo
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
+1  A: 

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