Autor |
Beitrag |
JacFab
      
Beiträge: 111
|
Verfasst: Sa 25.01.03 16:55
Ich hab mein Programm für den Dateityp *.bmp registriert, aber möchte, dass alle im Explorer markierten Dateien in der selben Instanz des Programms geöffnet werden. Zur Zeit öffnet jede Datei ein eigenes Fenster. Wie vermeide ich das??
|
|
MathiasSimmack
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Sa 25.01.03 17:09
Am besten, indem du
1. einen Mutex für dein Programm schreibst, der nur eine Instanz zulässt
2. mit Hilfe der Nachricht WM_COPYDATA den Parameter jeder weiteren, geladenen Instanz an die bereits laufende weiterreichst
|
|
Andreas Pfau
      
Beiträge: 997
|
Verfasst: Sa 25.01.03 17:14
Ohne DDE gar nicht (oder nur mit extremem Aufwand). DDE geht so:
Du hast ja in der Registry einen Kea angelegt, sagen wir mal, "HKCR\Paint.Picture\Shell\MeinProg". Dort ist dein Command-Ordner. Im Ordner "MeinProg" (oder so ähnlich) legst du den Ordner "DdeExec" an. Der Standard-String hat den Wert "%1". Unterordner "Application" anlegen, Standard-String = "MeinProg". Zurück in "DdeExec" Unterordner "Topic" anlegen, Standard="OpenFile".
Jetzt lädtst Du dein Delphi-Projekt. Den Code zum auswerten der Parameters löschen, den brauchst du für DDe nicht. Dann fügst du die Komponente "TDDEServerConv" ein, Name = "OpenFile". Im Event "OnExecuteMacro" das hier eintragen:
Quelltext 1: 2: 3: 4: 5: 6: 7:
| var I: Integer; begin For I := 0 To Msg.Count - 1 Do begin If FileExists(Msg[I]) Then OpenFile(Msg[I]); end; |
wobei du OpenFile() delbst deklarieren musst. Die Prozedur lädt ganz einfach die angegebene Datei.
|
|
JacFab 
      
Beiträge: 111
|
Verfasst: Sa 25.01.03 18:11
ja, dann wird das prog nur einmal geöffnet, aber die parameter kommen nur einmal an!
|
|
Andreas Pfau
      
Beiträge: 997
|
Verfasst: Sa 25.01.03 18:24
Immer, wenn das Ereignis von TDDEServerConv aufgerufen wird, kommen neue Dateinamen. Konsolenparameter gibt's keine mehr, läuft alles über DDE. Evtl. kommen mehrere Dateiamen auf einmal, daher ja auch die Schleife.
Noch fragen? 
|
|
MathiasSimmack
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Sa 25.01.03 18:52
Andreas Pfau hat folgendes geschrieben: | Ohne DDE gar nicht (oder nur mit extremem Aufwand). |
Sagen wir als Beispiel: ein VCL-Projekt. Eine neue Nachricht und eine Zeile in der Unit bezeichnest du als extremen Aufwand? Dazu kommen im Projektquelltext noch ein paar Zeilen zum Senden des Parameters.
Mutex-Code und WM_COPYDATA; als Beispiel im Projektquelltext (*.dpr):
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28:
| var cpydata : TCopyDataStruct; begin hm := CreateMutex(nil,false,'MeinProgramm_Version1.0'); if(GetLastError = ERROR_ALREADY_EXISTS) then begin
// Parameter übermitteln if(paramcount = 1) then begin cpydata.dwData := 0; cpydata.cbData := length(paramstr(1)) + 1; cpydata.lpData := @paramstr(1)[1];
// Fenster der alten Instanz suchen // (als Beispiel die VCL-Version) aWnd := findwindow('TForm1','Form1'); if(aWnd <> 0) then SendMessage(aWnd,WM_COPYDATA,0,LPARAM(@cpydata)); end;
// diese Instanz beenden! Halt; end;
// der Rest vom DPR-Quelltext { ... }
CloseHandle(hm); end. |
Abfrage des Parameters:
- Non-VCL (am Beispiel einer Dialogprozedur):
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| function dlgproc(hwndDlg: HWND; uMsg: UINT; wp: WPARAM; lp: LPARAM): bool; stdcall; var buf : array[0..MAX_PATH]of char; begin Result := true;
case uMsg of WM_COPYDATA: begin ZeroMemory(@buf,sizeof(buf)); lstrcpyn(buf,PCopyDataStruct(lp)^.lpData,PCopyDataStruct(lp)^.cbData);
MessageBox(hwndDlg,buf,'Empfangen ->',0); end; else Result := false; end; end; |
- VCL:
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| type TForm1 = class(TForm) { ... } private procedure WmCopyData(var Msg: TWMCopyData); message WM_COPYDATA; { ... }
procedure TForm1.WmCopyData(var Msg: TWMCopyData); var buf : array[0..MAX_PATH]of char; begin StrLCopy(buf,Msg.CopyDataStruct.lpData,Msg.CopyDataStruct.cbData); MessageBox(Form1.Handle,buf,'Empfangen ->',0); end; |
Gruß.
|
|
Andreas Pfau
      
Beiträge: 997
|
Verfasst: Sa 25.01.03 19:40
Na ja, @Mathias, so geht's auch. Aber eines ist mir ein Dorn im Auge: Wenn ich weder Die caption noch die Klasse kenne (z.B. habe ich ja bei jedem Delphi-Programm "TForm", und Die Caption kann je nach geöffneter Datei anders sein), wie kann ich dann das Fenster-Handle rausfinden? Ich würde das auch so machen wie Du, aber wie kann ich das Handle global speichern? Klar, Registry, aber gibt es auch eine professionelle Lösung???
|
|
AndyB
      
Beiträge: 1173
Erhaltene Danke: 14
RAD Studio XE2
|
Verfasst: Sa 25.01.03 20:02
Andreas Pfau hat folgendes geschrieben: | Klar, Registry |
Da würde ich dann lieber MMFs einsetzen.
Du könntest deinem Formular eine Botschaft hinzufpgen (RegisterWindowMessage) und dann alle Formulare mit EnumWindows durchlaufen. Das Formular, dass eine bestimmte Antwort auf diese Botschaft gibt, ist dann das gesuchte.
Diese Komponente dürfte etwas für dich sein.
_________________ Ist Zeit wirklich Geld?
|
|
Andreas Pfau
      
Beiträge: 997
|
Verfasst: Sa 25.01.03 22:00
Danke, @Andy, aber was ist eine MMF? Ehrlich gesagt, das habe ich noch nie gehört und kann mir rein gar nix drunter vorstellen.
|
|
Rool
      
Beiträge: 211
|
Verfasst: So 02.02.03 18:48
Titel: Irgendwas funzt nicht!!!
Hab die Methode von MathiasSimmack mal ausprobiert, vom Kontext-Menu des Dateityps funktionierts ja, aber wie übergebe ich diese Parameter per Code (ShellExecute) oder mit Start->Ausführen ???
Habs so versucht: "C:\Prog.exe" "Datei1" "Datei2" usw. aber das geht nicht!!!
Was muss ich aufrufen???
_________________ MFG Rool
|
|
GSE
      
Beiträge: 740
Win 2k, Win XP Pro
D5 Prof, D6 Ent, D2k5 PE
|
Verfasst: So 02.02.03 20:28
Hab´ was bei Torry gefunden:
www.torry.net/samples_software.htm
-> How to prevent a second instance
By Theodoros Bebekis. Example on How to prevent a second instance of application and take its parameters.
Funktioniert (verwende es selbst in meinen Programmen)!
mfg
GSE
_________________ Programming today is a race between software engineers striving to build bigger and better idiot-proof programs
and the universe trying to produce bigger and better idiots. So far, the universe is winning. (Richard Cook)
|
|
MathiasSimmack
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: So 02.02.03 21:24
Titel: Re: Irgendwas funzt nicht!!!
Rool hat folgendes geschrieben: | aber wie übergebe ich diese Parameter per Code (ShellExecute) oder mit Start->Ausführen ???
Habs so versucht: "C:\Prog.exe" "Datei1" "Datei2" usw. aber das geht nicht!!!
Was muss ich aufrufen??? |
Da ich via WM_COPYDATA nur den ersten Parameter an die laufende Instanz weiterreiche, sollte der Aufruf von
Quelltext
erfolgreich sein. Die zweite Variante wäre eine for-Schleife, die sich durch die übergebenen Parameter "loopt" und jeden nacheinander an die laufende Instanz weiterreicht. Dann, und wirklich erst dann!, kannst du auch
Quelltext 1:
| prog.exe Datei1 Datei2 ... |
aufrufen.
|
|
Rool
      
Beiträge: 211
|
Verfasst: Mo 03.02.03 13:58
Titel: Jau...
Ok, alles klar, wenn mans dann noch mit Anführungszeiczhen macht, kann man auch Dateinamen mit Leertasten übergeben!
Danke vielmals!!!
_________________ MFG Rool
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mo 03.02.03 15:03
Na ja meine Taste wollte ich schon noch behalten  . Du redest wohl von Leer zeichen 
|
|
Rool
      
Beiträge: 211
|
Verfasst: Mo 03.02.03 15:33
Titel: ;-)))
Ja logo, sorry natürlich meine ich ZEICHEN!!! 
_________________ MFG Rool
|
|