Autor Beitrag
JayEff
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2971

Windows Vista Ultimate
D7 Enterprise
BeitragVerfasst: Fr 15.06.07 14:36 
Hallo Leute.
Heute geht's mir um ein Problem, das in meinen Augen eigentlich recht häufig ist und bei dem ich mich gewundert hab, dass ich auch nach längerem Googlen und DF-Suchen nichts finden konnte:
Das Öffnen mehrerer Dateien per "Öffnen mit..." oder ähnlichem (Auch: ShellExtention).
Das Problem ergibt sich durch Windows: Anstatt mehrere Dateien (Rahmen ziehen -> Rechtsklick -> Öffnen mit...) einfach als mehrere Parameter zu übergeben, wird für jede Datei eine neue Instanz des Programms gestartet.

Gibt es eine einfache Lösung für das Problem, oder muss man per Semaphore verhindern, dass mehrere Instanzen gestartet werden und per SendMessage die in ParamStr(1) übergebenen Dateien an die zuerst geöffnete Instanz senden? Wenn's nur so ginge, wüsste ich nicht, wie ich das Handle der Instanz bekomme, die am Ende dann "übrig bleibt".

Ich hoffe, ich hab nun beim Suchen nicht irgendeinen Thread übersehen. Danke schonmal für eure Hilfe!
Jan

_________________
>+++[>+++[>++++++++<-]<-]<++++[>++++[>>>+++++++<<<-]<-]<<++
[>++[>++[>>++++<<-]<-]<-]>>>>>++++++++++++++++++.+++++++.>++.-.<<.>>--.<+++++..<+.
JayEff Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2971

Windows Vista Ultimate
D7 Enterprise
BeitragVerfasst: Sa 23.06.07 15:59 
*push*

Folgendes. Über die Semaphore kann ich meinem Programm sagen, dass eine weitere Instanz gestartet wurde (PostMessage an HWND_BROADCAST ).

Wie übergebe ich meinem Programm dann den Dateinamen in ParamStr(1)? Per SendMessage/PostMessage kann ich ja keine Strings/PChars senden. Welche anderen Möglichkeiten gibt es?

Edit: www.delphi-library.d...iewtopic.php?t=20679
:oops:

_________________
>+++[>+++[>++++++++<-]<-]<++++[>++++[>>>+++++++<<<-]<-]<<++
[>++[>++[>>++++<<-]<-]<-]>>>>>++++++++++++++++++.+++++++.>++.-.<<.>>--.<+++++..<+.
JayEff Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2971

Windows Vista Ultimate
D7 Enterprise
BeitragVerfasst: Sa 23.06.07 16:55 
dpr:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
    If (GetLastError = ERROR_ALREADY_EXISTS) Then
    Begin
        WriteStringToMMF(Unit1.GUID + 'MMF', ParamStr(1));
        PostMessage(HWND_BROADCAST, Unit1.ActivationMessage, 0, 0)
    End

Unit:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
Procedure TForm1.ApplicationEvents1Message(Var Msg: tagMSG;
    Var Handled: Boolean);
Begin
    If (Msg.message = ActivationMessage) Then
    Begin
        Application.Restore;
        SetForegroundWindow(Handle);
        SetActiveWindow(Handle);
        Listbox1.Items.Add(ReadStringFromMMF(GUID + 'MMF'));
        Handled := True;
    End;
End;

Leider scheint das ganze nicht so ganz zu klappen. Ich werd noch etwas hin und herprobieren, aber wie's aussieht, gibt die ReadStringFromMMF nichts zurück... :(
Edit: Interessanterweise erhalte ich bei 3 Aufrufen einer zusätzlichen Instanz 6 Einträge in die Liste, also immer 2 mal den selben. Das funktioniert aber auch nur, wenn bereits eine Instanz läuft. Wenn ich das Programm 3 mal per "Öffnen mit" starte, dann klappt die Sache garnicht, die Message wird wohl gesandt, bevor das Programm darauf reagieren kann... :|

_________________
>+++[>+++[>++++++++<-]<-]<++++[>++++[>>>+++++++<<<-]<-]<<++
[>++[>++[>>++++<<-]<-]<-]>>>>>++++++++++++++++++.+++++++.>++.-.<<.>>--.<+++++..<+.
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8554
Erhaltene Danke: 481

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Sa 23.06.07 17:22 
IMHO die einfachste und bequemste Möglichkeit, das zu lösen, ist die Unit OneInst.pas. Gibts auf Luckies Seite unter Nicos Importe. Einfach in die Uses-Liste einfügen, und der Rest geht fast von alleine.

Zum "Öffnen mit": Über Rechtsklick-Öffnen mit kann man immer nur eine Datei öffnen (die fokussierte). Der Rest wird einfach ignoriert. Da lässt sich afaik auch nichts dran ändern.

_________________
We are, we were and will not be.
JayEff Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2971

Windows Vista Ultimate
D7 Enterprise
BeitragVerfasst: Sa 23.06.07 17:45 
user profile iconGausi hat folgendes geschrieben:
Zum "Öffnen mit": Über Rechtsklick-Öffnen mit kann man immer nur eine Datei öffnen (die fokussierte). Der Rest wird einfach ignoriert. Da lässt sich afaik auch nichts dran ändern.
Wenn das so ist, wie kann dann WinZip mehrere Dateien über die ShellExtention archivieren? Wie machen das *die ganzen anderen*? :cry:

Edit: Es scheint, dass die OneInst.pas das für mich übernehmen kann...!

Edit: Folgender, mir nicht ganz klarer Code scheint in den meisten(?) Fällen zu klappen:
ausblenden volle Höhe Delphi-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:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
uses {...}, OneInst;
{...}
type TForm1={...}
        Procedure WMDrop(Var msg: TMessage); Message WM_DROPFILES;
        Procedure WMCopyData(Var Msg: TWMCopyData); Message WM_CopyData;

end;

Procedure TForm1.ProcessCommandline(lpData: Pointer);
Var s: String;
Begin
    s := ParamBlobToStr(lpData);
    If length(s) > 0 Then
        Form1.Listbox1.Items.Add(s);
    SetScrollWidth;
End;

{ Eine zweite Instanz hat uns ihre Kommandozeilenparameter geschickt }

Procedure TForm1.WMCopyData(Var Msg: TWMCopyData);
Begin
    If (Msg.CopyDataStruct.dwData = SecondInstMsgId) And (SecondInstMsgId <> 0)
        Then
        ProcessCommandline(Msg.CopyDataStruct.lpData)
    Else
        { Tcha wohl doch nicht ID - stimmte nicht }
        Inherited;
End;

Procedure TForm1.DefaultHandler(Var Message);
Begin
    If TMessage(Message).Msg = SecondInstMsgId Then
        { Eine zweite Instanz hat uns nach dem Handle gefragt }
        { Es wird in die Message-Queue des Threads gepostet.  }
        PostThreadMessage(TMessage(Message).WParam, SecondInstMsgId, Handle, 0)
    Else
        { Ansonsten rufen wir die geerbte Methode auf }
        Inherited;
End;

Procedure TForm1.ApplicationEvents1Message(Var Msg: tagMSG;
    Var Handled: Boolean);
Var
    lpData: Pointer;
    cbData: DWORD;
Begin
    If Msg.message = SecondInstMsgId Then
    Begin
        lpData := ParamStrToBlob(cbData);
        Try
            ProcessCommandline(lpData);
        Finally
            FreeMemory(lpData);
        End;
    End;
End;

_________________
>+++[>+++[>++++++++<-]<-]<++++[>++++[>>>+++++++<<<-]<-]<<++
[>++[>++[>>++++<<-]<-]<-]>>>>>++++++++++++++++++.+++++++.>++.-.<<.>>--.<+++++..<+.