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(CreateF ile);
// 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
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(CreateF
// 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
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
// 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
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.
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
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
ASKER
yeah sure, post it
Thanks
Marc
Thanks
Marc
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
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
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
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
ASKER
How does 2 work?
Never changed anything in a .dpr before?
Thanks
Marc
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
Ciao, Mike
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(paramst
//Nothing
End;
Epsylon.