Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - Problem mit zweiter Programminstanz


dickeWade - Mo 28.02.11 12:16
Titel: Problem mit zweiter Programminstanz
Hallöchen und einen schönen Tag :)

Mich beschäftigt folgendes kleines Problem. Ich will von meinem Programm nur eine Instanz laufen haben. Wird es ein zweites Mal gestartet, suche ich das Hauptfenster, aktiviere ich es, bringe es in den Vordergrund und beende die zweite Instanz wieder.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
FensterHandle := FindWindow('TFestplattenRecorderForm'nil);
if FensterHandle <> 0 then
begin
  ShowWindow(FensterHandle, SW_RESTORE);
  SetForegroundWindow(FensterHandle);
end;

Das funktioniert an sich auch ganz fein, bis auf eine Schwierigkeit. Ist das Fenster der ersten Instanz gerade minimiert, wird es zwar "wieder hervorgeholt" und alles ist schön. Fortan kann ich es aber nicht mehr minimieren. Mit dem nCmdShow - Parameter SW_SHOWNORMAL hab ich das gleiche Ergebnis. Dito wenn ich statt ShowWindow den Befehl:

Delphi-Quelltext
1:
SendMessage(FensterHandle, WM_SYSCOMMAND, SC_RESTORE, 0);                    

benutze.

Vielen Dank im Vorraus :)

Gruß Tommi


guinnes - Mo 28.02.11 12:33

Es gibt dafür die Komponente OneInstance von Andreas Hausladen


Xion - Mo 28.02.11 13:15

Probiers mal so:

Delphi-Quelltext
1:
SendMessage(FensterHandle,WM_SHOWFORM,0,0);                    


dickeWade - Mo 28.02.11 13:16

Vielen Dank für die schnelle Antwort.

Werde ich doch flink mal ausprobieren :D

Gruß Tommi


Sinspin - Mo 28.02.11 16:09

Ich arbeite immer mit einem Mutex. Der Name dessen ist eine GUID und somit weltweit eindeutig. So kann nie aus versehen ein anderes Programm genauso heißen.
Eine GUID kannst Du in Delphi via Strg+Umschalt + G erzeugen.
In der DPR dazu das folgende schreiben:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
var
  Mutex: THandle;

begin
  Mutex := CreateMutex(nil, True, '{30E93268-B040-433A-9E22-96F391F4D4D4}');
  if (Mutex <> 0and (GetLastError = 0then
  begin
    Application.Initialize;
    Application.CreateForm(TForm1, Form1);
    Application.Run;
    if Mutex <> 0 then
      CloseHandle(Mutex);
  end
  else
  begin
    MessageDlg('Programm darf nur einmal gestartet werden!', mtError, [mbOK], 0);
  end;
end.


dickeWade - Mi 02.03.11 18:40

Dankeschön :D

Ich sehe schon, es gibt verschiedene Methoden die erste Instanz zu finden. Werde ich alle mal ausprobieren und schauen was mir am besten gefällt. Das Senden einer Message an die erste Instanz funktioniert bei mir auch gut, nur das mit dem schicken der Kommandezeile werde ich mal mit Atomen probieren. Mit GlobalAlloc kam ich nicht weiter. Kam nix an.

Allerdings funktioniert das Wiederherstellen des Fensters der ersten Instanz immer noch nicht wenn es in der Taskleiste verkleinert schlummert. Es kommt zwar zum Vorschein und alles ist Prima, aber fortan lässt es sich eben nicht mehr verkleinern. "WM_SHOWFORM" hab ich probiert, die Konstante wurde aber nicht gefunden :?

Mir fällt da gerade ein Möglichkleit ein:


Delphi-Quelltext
1:
SendMessage(FensterHandle,WM_DuSollstDichVergroessernFallsDuMinimiertBist,0,0);                    

Also dass die erste Instanz das Wiederherstellen und Anzeigen des Fensters übernimmt. Probier ich heute Abend mal aus...

Gruß Tommi


dickeWade - Sa 05.03.11 17:32

So hab die Lösung gefunden und die funktioniert auch bestens :)


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
const
    WM_ZweiteInstanz = WM_USER + 11;

......

procedure TFestplattenRecorderForm.MessageVonZweiterInstanz(var Msg: TMessage);
begin
  Application.Restore;
  Application.BringToFront;
end;


Dankeschön nochmals :)

Hab ich schon erwähnt, dass das hier ein tolles Forum ist? Ich lese ja schon ein paar Wochen hier und hab schon einige gute Tips gefunden.

Gruß Tommi