Autor Beitrag
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mi 15.12.04 19:37 
Moin!

Ich hab mal wieder einen Knoten in den Gehirnwindungen... :|

Mit folgendem (Standard-)Code verhindere ich einen Mehrfachstart:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
Application.Initialize;
Application.Title := 'MeinProg';

// Mehrfachstart unterbinden
hMutex := CreateMutex(NIL, TRUE, 'MeinProg gestartet');
if (GetLastError() = ERROR_ALREADY_EXISTS) then begin
  hWndFirst := FindWindow('TMeinProg', NIL);
  if (hWndFirst <> 0) then begin
    // Dinge tun, wenn Fenster ausgeblendet
    SetForegroundWindow(hWndFirst);
    BringWindowToTop(hWndFirst);
  end;
  Application.Terminate;
  Application.ProcessMessages;
  Exit;
end;

Application.CreateForm(TMeinProg, MeinProg);
Application.Run;

ReleaseMutex(hMutex);


Falls eine ältere Programminstanz gefunden wurde, soll deren Fenster wieder eingeblendet werden. Klappt auch an sich ganz gut, nur dann nicht, wenn das Fenster in die Tasteleiste ausgeblendet ist. Hab schon reichlich an diesem Fenster rumge"handled" :wink: , aber ich krieg das doofe Ding nicht aufgeblendet!?!

Kann mir da einer helfen? Ideen?

cu
Narses
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Mi 15.12.04 22:56 
ausblenden Delphi-Quelltext
1:
2:
if IsIconic(hWndFirst) then
  ShowWindow(hWndFirst, SW_RESTORE);


BTW: du solltest den Mutex-Handle auch schließen wenn bereits eine Instanz deines Progs läuft. Windows räumt zwar sowieso auf wenn die zweite Instanz wieder terminiert, aber es wäre "sauberer".

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
Narses Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mi 15.12.04 23:16 
Moin!

Danke! Der ShowWindow(hWndFirst, SW_RESTORE) hat´s dann gebracht. Allerdings ohne die IF-Klausel; das Fenster scheint nicht im Status ICONIC zu sein... ?!

Zitat:
du solltest den Mutex-Handle auch schließen wenn bereits eine Instanz deines Progs läuft. Windows räumt zwar sowieso auf wenn die zweite Instanz wieder terminiert, aber es wäre "sauberer".

Schon klar, aber nach meinem Verständnis der Funktion CreateMutex() wird im Fehlerfall erst gar kein Handle angelegt, wieso dann also schließen? Liege ich da falsch?

cu
Narses
wulfskin
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1349
Erhaltene Danke: 1

Win XP
D5 Pers (SSL), D2005 Pro, C, C#
BeitragVerfasst: Mi 15.12.04 23:34 
Hallo,

leider ist mir auch schon aufgefallen, dass die Funktion IsIconic nie anspricht. Kann jemand mal erklären, welches Handle man der Funktion übergeben muss und ob es irgend etwas zu beachten gibt?

Gruß Hape!

_________________
Manche antworten um ihren Beitragszähler zu erhöhen, andere um zu Helfen.
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Mi 15.12.04 23:42 
@Narses:
PSDK hat folgendes geschrieben:
If the named mutex object existed before the function call, the function returns a handle to the existing object and GetLastError returns ERROR_ALREADY_EXISTS.

D.h. wenn bereits eine Instanz läuft wird nur das Handle des bereits existierenden Mutex zurückgegeben, ABER es wird der interne Refernzzähler des Mutex erhöht, da ja ein gültiges Handle zurückgeliefert wurde. Um diesen wieder zu dekrementieren musst du den Mutex wieder schließen.

@wulfskin: also ich hatte mit IsIconic() noch nie Problem.. :gruebel: Man übergibt nur das Handle des Fensters, mehr nicht (geht ja auch gar nicht)...

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
Narses Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Do 16.12.04 23:43 
Moin!

@Motzi:
Stimmt, hast recht, wer lesen kann, ist klar im Vorteil, es wird ein Referenz-Zähler mitgezählt. Also, Unsauberkeit bereinigt.

Allerdings gibt es noch ein Problem, was diese Frage wieder in den Status "unbeantwortet" schiebt...

Wenn das Fenster mit dem ShowWindow() wieder aus der Taskleiste aufgepopt wird, ist dieses zwar wieder da, aber der Status, den Windows für das Fenster protokolliert, ist offensichtlich nicht korrekt umgestellt. Denn: wenn man den "Minimieren-Button" anklickt, kann man das Fenster nicht mehr ausblenden. Macht man einen Rechtsklick auf dem Taskleisteneintrag, kann man das Fenster immer noch "Wiederherstellen", obwohl das Fenster bereits wieder da ist... ?!?

Noch jemand eine Idee?

cu
Narses


Zuletzt bearbeitet von Narses am Fr 17.12.04 08:52, insgesamt 1-mal bearbeitet
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Fr 17.12.04 00:55 
Achja.. Delphi-Programme haben ja noch das versteckte TApplication-Fenster und das is das eigentlich minimierte Fenster...
ausblenden 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:
Application.Initialize;
Application.Title := 'MeinProg';

// Mehrfachstart unterbinden
hMutex := CreateMutex(NIL, TRUE, 'MeinProg gestartet');
if (GetLastError() = ERROR_ALREADY_EXISTS) then
begin
  hWndFirst := FindWindow('TMeinProg', NIL);
  if (hWndFirst <> 0) then
  begin
    hWndApp := GetWindow(hWndFirst, GW_OWNER); // Owner-Handle holen (Handle des TApplication-Fensters)
    if IsIconic(hWndApp) then
      ShowWindow(hWndApp, SW_RESTORE); // restoren wenn minimiert

    // Hauptfenster in den Vordergrund holen
    SetForegroundWindow(hWndFirst);
    BringWindowToTop(hWndFirst);
  end;
  CloseHandle(hMutex);
  Exit;
end;

Application.CreateForm(TMeinProg, MeinProg);
Application.Run;

CloseHandle(hMutex);


BTW: Kernel-Objekte (wie einen Mutex) schließt man (fast) alle mit CloseHandle! ;)

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
Narses Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Fr 17.12.04 08:37 
Perfekt, funktioniert!

Und fragt man das richtige Fenster, sagt IsIconic auch tatsächlich das korrekte Ergebnis! :wink:
@wulfskin: Das ist vermutlich auch dein Fehler!?

Danke nochmal.

cu
Narses
wulfskin
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1349
Erhaltene Danke: 1

Win XP
D5 Pers (SSL), D2005 Pro, C, C#
BeitragVerfasst: Do 06.01.05 18:10 
Narses hat folgendes geschrieben:
Und fragt man das richtige Fenster, sagt IsIconic auch tatsächlich das korrekte Ergebnis! :wink:
@wulfskin: Das ist vermutlich auch dein Fehler!?
Stimmt, ich habe immer das Handle des Main-Formulars übergeben.

Danke auch von meiner Seite,
Hape!

_________________
Manche antworten um ihren Beitragszähler zu erhöhen, andere um zu Helfen.