Link to home
Start Free TrialLog in
Avatar of hellfire052497
hellfire052497

asked on

Paramstr and multiple files

Hi,

I use this for opening a file when launched from explorer.

Procedure Tform1.FormCreate(Sender: TObject);
Var
 Parameters : String;
 X : Integer;
Begin
 // This code handles long filenames
 For x := 1 To Paramcount do
 Begin
 Parameters := Parameters + paramstr(X);

 If X < Paramcount then Parameters := Parameters + ' ';
 End;
 if Parameters <> '' Then Opencode(Parameters) Else
 //Nothing
End;

And then it is passed to

Procedure TForm1.Opencode(Const CreateFile: Ansistring);
Begin
 Listbox1.Items.Add(CreateFile);
 // I want to use .Assign, but that is not accepted
End;

This all works fine, when using only 1 file, When I select multiple files to open, Let's say 3, it launches 3 instances of my program, each with the next file.

How do I get all of the files in 1 instance, I use a Listbox
to store multiple files.

I also need to know if 1 or multiple files are available.
Can anyone give a suggestion??

Thanks
Marc
Avatar of Epsylon
Epsylon

I can hardly understand what you are doing but is this what you want?


procedure TForm1.FormCreate(Sender: TObject);
Var
 Parameters : String;
 X : Integer;
Begin
 // This code handles long filenames
 For x := 1 To Paramcount do
   ListBox1.Items.Add(paramstr(X));
 //Nothing
End;

Epsylon.

hellfire, I see what you are trying to do, but that is not right.  When windows passes your program a filename, it encloses it in quotes if there are spaces in it.  You code here:

// This code handles long filenames
 For x := 1 To Paramcount do
 Begin
 Parameters := Parameters + paramstr(X);

Is NOT needed at all. Epsylon's code is a textbook example of how to do this correctly.  But I digress, that is not what is causing your problem.  Windows does NOT pass your program the file names of each selected file.  It executes your executable passing each instance one of the selected filenames.  This is by design.  I dont know a simple way around this.  It is possible to do this, but I think you would need to use a DLL which had a exported function that loads the file into the list box.  That way you could detect if your program was already running, and if it was call the function in the DLL, passing it the handle of your first instance so that it could load the file into the listbox.  This would be rather involved code, and I am afraid it wouldnt be very easy.  I hope someone else knows a better way to do this...

Heath
After thinking about it a while, I dont think it would be a good idea to try and change the default behavior of windows.  People expect it to work a certain way, and you would be altering the expected behavior.  Another method which would be much easier is to add filedrop support to your program.  that way a user could drop a group of files onto your program and it would open all of them in the current instance.  this is how most other programs (word, excel, etc) handle it, so you would be doing it the same way as everyone else.  there are components available that add this support to a form, it should be easy enough to find one.

Heath  
There is a standard way to open multiple file using single application instance. It involves DDE, works on Windows 9x and NT and does not alter default behaviour of anything. The information about the method can be found in "Microsoft Programmer's Guide to Windows 95" shipped with Delphi 4. To get  it make a search for either "ddeexec" or "Q122787" in Find tab.
It can also be found in MSDN library.
The only problem with it is that you can not know how many files where selcted for opening, you receive their names one by one (of course you can make dirty trick with timer to see when you stop to receive filenames for some period of time, but, as i said it's dirty trick).

Roman.
hellfire,

As usually also multiple instances of an application are to prevent one can use a very elegant solution for this problem, without using DDE.

When an application is started and has already a running instance it stores its parameters into a shared area and notifies the previous instance, which then retrieves these parameters and acts accordingly. This would also work in your case. If you are interested in proved code I'll post it here...

Ciao, Mike
Avatar of hellfire052497

ASKER

yeah sure, post it

Thanks
Marc
ASKER CERTIFIED SOLUTION
Avatar of Lischke
Lischke

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hi,

Does this code work??, The List.Commatext value remains empty, I added at various places a Showmessage('passed'); But none where called.
But then I may be missing something, it's so complex.

Perhaps it is easier if you send a small working sample, If you could add a listbox on the form, and add all files that are launched from explorer to it automatically, then I have all I need.

You can send it at hellfire@unforgettable.com

Thanks
Marc
Oh yes, this code is proved to be working. Let's make sure that you have build in all you need. Look through the check list below:

1) You have created a project and registered it to be called when double clicking (etc.) on a specific file.
2) In the project source code (*.dpr) you have included the check for another instance.
3) Somewhere in the project you called HookMainWindow.
4) The code which you registered with HookMainWindow is called and you filter out WM_OTHERINSTANCE like:

function TMainForm.WindowHook(var Message: TMessage): Boolean;

// watch other instances of this application

var List: TStringList;

begin
  if Message.Msg = WM_OTHERINSTANCE then
  begin
    List := TStringList.Create;
    List.Duplicates := dupIgnore;

    GetInstanceParams(List);
    // element 0 is the executable itself
    List.Delete(0);
    AddProjectFiles(List);
    List.Free;
    Message.Result := 0;
    Result := True;
  end
  else
  :
5) You received this message and you called GetInstanceParams.

Does this all apply?

Ciao, Mike
How does 2 work?

Never changed anything in a .dpr before?

Thanks
Marc
Go to Project|View Source (D4) or View|Project Source (D3). You can also open the dpr file in any text editor (don't use Delphi's open function, as this will open the project as such).

Ciao, Mike