Fokusproblem nach WaitForSingleObject und EnableWindow
-
Dein Problem ist vollkommen hausgemacht. Windows würde sicher genre machen was Du willst!

Aber das Problem ist, dass Dein Fenster inaktiv ist. Du selbst hast ein EnableWindow(FALSE) gemacht.
Wenn der andere Prozess terminiert will Windows Dein Fenster aktiv machen, kann es aber nicht, denn es ist inaktiv.Erzeuge ein kleines Toplevel Window (Dialog o.ä.) der Dein Main-Window disabled, selbst aber aktiv bleibt und auf Deinen Prozess wartet.
PS: Was Belli schreibt spielt hier keine Rolle.
-
Dein Problem ist vollkommen hausgemacht. Windows würde sicher genre machen was Du willst!

Keine Sorge, ich bin kein Mensch der nach dem Motto "Wenn du ein Problem hast, suche dir immer einen Sündenbock (Windows)." handelt.
Wenn ich sogar ehrlich bin, empfinde ich mich eher Linux nach Windows Konvertit. Es scheint wohl immer ein wenig davon abzuhängen unter welchem Betreibssystem man arbeitet.Ich habe das von Belli mal ausprobiert und es funktioniert leider nur zum Teil. Benutze ich den Quellcode wie ich ihn hier angegeben habe, funktioniert es relativ gut. Aber selbst dann sieht man schön dass das Hauptfenster in den Hintergrund gelegt wird und danach wieder in den Vordergrund gelegt wird. Wenn ich aber doch auf einen Prozess in der Funktion CallProcess (eig. Funktion CallProcess2) warte, taucht die Problematik immer wieder auf.
Aber das Problem ist, dass Dein Fenster inaktiv ist. Du selbst hast ein EnableWindow(FALSE) gemacht.
Wenn der andere Prozess terminiert will Windows Dein Fenster aktiv machen, kann es aber nicht, denn es ist inaktiv.Dumme Frage:
Kann es sein das Windows mein Fenster aktiv machen will sobald der Prozess terminiert bzw. sobald die Funktion WaitForSingleObject beendet wurde ? Kann es sein das mein EnableWindow(ghWnd, TRUE) aufgerufen wird nachdem Windows das Fenster aktiv machen wollte ?
-
Bitte ein Bit schrieb:
Aber das Problem ist, dass Dein Fenster inaktiv ist. Du selbst hast ein EnableWindow(FALSE) gemacht.
Wenn der andere Prozess terminiert will Windows Dein Fenster aktiv machen, kann es aber nicht, denn es ist inaktiv.Dumme Frage:
Kann es sein das Windows mein Fenster aktiv machen will sobald der Prozess terminiert bzw. sobald die Funktion WaitForSingleObject beendet wurde ? Kann es sein das mein EnableWindow(ghWnd, TRUE) aufgerufen wird nachdem Windows das Fenster aktiv machen wollte ?Genau so ist es. Es ist ein immer wiederkehrendes Problem wie auch bei der Implementierung einer modalen Message-Loop (siehe CDialog::DoModal)
Die Lösung habe ich Dir schon genannt.
-
Und sie funktioniert saugeil
Danke, danke, danke 
Ich muss mal jetzt nur noch schauen ob ich den Dialog versteckt bekomme oder ob ich daraus einen Hinweisdialog bastele.
-
Aber was ist der Grund dafür, daß SetForeGroundWindow mit der von mir erwähnten Methode (AttachThreadInput usw) nicht funktionieren will?
-
Belli schrieb:
Aber was ist der Grund dafür, daß SetForeGroundWindow mit der von mir erwähnten Methode (AttachThreadInput usw) nicht funktionieren will?
Müsste man debuggen. Dieses Umsetzen des Focus und aktiven Fensters ohne das die Message-Loop zwischen drin läuft führt zu allerlei komischen Effekten, die sich meistens schnell erklären lassen, wenn man das ganze mit Spy++ analysiert.
Ein Grund wäre: Windows hat genau das zuvor probiert, da ging es nicht, Nachrichten die diesen Zusatnd verändern sind nicht eingegangen, also wird der Versuch ignoeriert, obwohl EnableWindow ausgeführt wurde...
Nur eine Vermutung oder ins blaue rein geraten.PS: Wenn man es richtig macht, benötigt man SetForegroundWindow für diese Aktion gar nicht.
PPS: Nur mal so, warum ich diesen Weg sogar als falsch erachte:
Nehmen wir an, Programm1 startet Programm2 und das dauert lange. Warum sollte Programm1 sich in den Vordergrund zwängen wenn der User weggeschaltet hatr (ALT-TAB) wenn nun Programm2 terminiert?
SetForeGroundWindow mit AttachThreadInput des aktuellen Fensters wäre genau das was man garantiert nicht will! Es unterbricht den Benutzer in der von ihm gewählten Arbeit und zwängt Programm1 wieder in den Vordergrund.
-
Martin Richter schrieb:
Belli schrieb:
Aber was ist der Grund dafür, daß SetForeGroundWindow mit der von mir erwähnten Methode (AttachThreadInput usw) nicht funktionieren will?
Müsste man debuggen. Dieses Umsetzen des Focus und aktiven Fensters ohne das die Message-Loop zwischen drin läuft führt zu allerlei komischen Effekten, die sich meistens schnell erklären lassen, wenn man das ganze mit Spy++ analysiert.
Du meinst, weil das Ganze in einem Thread ohne Loop geschieht, denn die MessageLoop des "Haupt"Threads läuft doch weiter?
Martin Richter schrieb:
Ein Grund wäre: Windows hat genau das zuvor probiert, da ging es nicht, Nachrichten die diesen Zusatnd verändern sind nicht eingegangen, also wird der Versuch ignoeriert, obwohl EnableWindow ausgeführt wurde...
Nur eine Vermutung oder ins blaue rein geraten.Nun, ich war überzeugt, daß EnableWindow eben genau diesen Zustand, der dem entgegensteht, ändert.
Martin Richter schrieb:
PPS: Nur mal so, warum ich diesen Weg sogar als falsch erachte:
Nehmen wir an, Programm1 startet Programm2 und das dauert lange. Warum sollte Programm1 sich in den Vordergrund zwängen wenn der User weggeschaltet hatr (ALT-TAB) wenn nun Programm2 terminiert?
SetForeGroundWindow mit AttachThreadInput des aktuellen Fensters wäre genau das was man garantiert nicht will! Es unterbricht den Benutzer in der von ihm gewählten Arbeit und zwängt Programm1 wieder in den Vordergrund.Okay, falsch im Sinne von falscher/schlechter Designentscheidung des Entwicklers, aber nicht falsch im Sinne von 'geht nicht' - obwohl, irgendwie scheint es ja im hier geschilderten Fall tatsächlich nicht zu gehen

-
@Belli:
Ich habe mir leider das Problem dahinter nicht genau angeschaut, warum deine Lösung im zweiten Fall nicht funktionierte.
Mein Code macht im zweiten Fall wesentlich mehr als ich in meinem Code-Beispiel angedeutet habe. Ich starte anfangs den Prozess B. Wenn dieser terminiert sende ich eine Nachricht an die Hauptschleife meines Programs. Diese ruft wiederrum den Prozess C auf und wartet auf das Ende des Prozesses. Danach macht die Funktion noch einige Dinge und kehrt dann zur Threadfunktion für B zurück, welche das Hauptfenster in den Vordergrund legt...
void WaitForProcess(void*) { WaitForSingleObject(ghProcess, INFINITE); CloseHandle(ghThread); CloseHandle(ghProcess); SendMessage(ghWnd, WM_MYMSG_1, 0, 0); // Kritisch da die Nachricht wiederrum einen Prozess startet ? EnableWindow(ghWnd, TRUE); Sleep(100); GetWindowThreadProcessId(...); GetCurrentThreadId(...); AttachThreadInput(..., TRUE); SetForegroundWindow(ghWnd); AttachThreadInput(..., FALSE); }Hmm, könnte mir gut vorstellen das hier der Hase vergraben ist.

Aber danke euch allen. Es funktioniert tadellos.

-
Und an was für ein Fensterhandle hast Du den AttachThreadInput ausgeführt?
Doch nicht etwa an das Dein aktuelles Fenster?
Hoffentlich doch wohl an das aktuelle aktive?
-
Und an was für ein Fensterhandle hast Du den AttachThreadInput ausgeführt?
Doch nicht etwa an das Dein aktuelles Fenster?
Hoffentlich doch wohl an das aktuelle aktive?Das hatte ich überprüft und müsste auch soweit gestimmt haben.
-
Hier mal ein Link in die MSDN:
http://msdn.microsoft.com/de-de/library/bb979463.aspx
Ich glaube, das Problem ist tatsächlich, daß der Attach-Thread nicht der Thread ist, der das in den Vordergrund zu holende Fenster erstellt hat, und die Mess.Loop dazu verwaltet, sondern der Wartethread.
-
Nein! Es muss der Thread sein der aktuell im Vordergrund liegt! (GetForegroundWindow)
Denn dieser wird ja geschützt und nur dieser hat freie Erlaubnis beliebige Fenster in den Vordergrund zu bringen!
-
Klar, ich meine den anderen, mit diesem zusammenzuattachenden Thread. Das ist in diesem Fall hier ja der Wartethread, der keine Msg.Loop hat, und dementsprechend gar keine In-Message verarbeiten kann. Das könnte doch das Problem sein ... ich denke, wenn man stattdessen den "Haupt"thread mit der Msg.Loop nähme, würde es vllt. klappen ...