Prozess im Vordergrund von eigener Anwendung erstellen?
-
Naja, kann sein dass es mit
SetParent
doch nicht geht.Was du machen willst wäre das Owner-Window zu ändern, nicht das Parent-Window.
An einigen Stellen in der WinAPI werden für Parent und Owner die gleichen Funktionen/Member/Parameter verwendet, daher dachte ich es sollte mitSetParent
funktionieren. Muss aber nicht sein dass das so ist, ich hab's nicht ausprobiert.Bzw. bist du sicher dass das Fenster der anderen Anwendung ein Top-Level Fenster ist? Wenn du
SetParent
auf ein Child-Window aufrufst, dann ist klar dass es danach IN deiner Form drinnen ist, und nicht davor -- weil halt Child Window.
-
Aaaaaah,
hier
http://stackoverflow.com/questions/133122/how-to-change-a-window-owner-using-its-handle
steht dass manSetWindowLongPtr(..., GWLP_HWNDPARENT, ...)
verwenden kann.Das könntest du mal probieren.
-
Das sieht vielversprechend aus!
http://stackoverflow.com/questions/133122/how-to-change-a-window-owner-using-its-handleSetWindowLongPtr( win32window, GWL_HWNDPARENT, formhandle );
Problem ist nur: laut MSDN ist die Funktion wie folgt deklariert:
LONG_PTR WINAPI SetWindowLongPtr( _In_ HWND hWnd, _In_ int nIndex, _In_ LONG_PTR dwNewLong );
Der dritte Parameter (dwNewLong) sollte laut Beispiel das Handle des Formulars (formhandle) sein. Natürlich kann ich als long kein HWND übergeben.
[C++ Fehler]: E2034 Konvertierung von 'void *' nach 'long' nicht möglich
Wie kann ich trotzdem das Handle des Formulars übergeben?
-
Einfach casten.
reinterpret_cast<LONG_PTR>(deinHwndWert)
Der
reinterpret_cast
ist in dem Fall auch kein Hack, sondern vom MS ganz klar so vorgesehen.Wichtig ist nur dass du die "
...Ptr
" Funktion verwendest und auchLONG_PTR
beim Casten verwendest, sonst bekommst du ein Problem wenn du mal für 64 Bit kompilierst.
-
ps:
Wichtig:
GWL
**P
**_HWNDPARENT
stattGWL_HWNDPARENT
verwenden wenn duSetWindowLong
**Ptr
**verwendest.Sonst wird das mit 64 Bit vermutlich wieder net richtig funktionieren
-
Vielen Dank!! Funktioniert herrlich!!!
Nur noch eine Kleinigkeit:
Das andere Fenster sitzt im Vordergrund und minimiert sich auch mit. Man kann aber trotzdem noch das Parent-Formular bedienen. Muss man wirklich einen Timer oder Thread erstellen, der ein MessageBeep ausführt und den Fokus auf das Formular setzt, sobald man auf das Hauptformular klickt, oder kann man da auch mit der WinAPI arbeiten?Trotzdem: Schön dass es funktioniert!!
-
Welches Parent-Formular?
Verstehe grad nicht was du meinst.
Das Parent-Formular in deiner Applikation? Oder in der Fremden?Mach vielleicht mal Screenshots die das ganze verdeutlichen.
Bzw. falls es um deine Applikation geht, kannst du natürlich auch hier Window-Ownership verwenden. Und/oder modale Dialoge.
ps: Das ist immer noch ein Hack, und ich würde es nur begrenzt empfehlen. Es kann durchaus Applikationen geben die ... anfangen komische Dinge zu tun wenn man an ihren Fenstern in dieser Art rumpfuscht - also Owner-Window ändert oder dergleichen.
pps: Das "ist in dem Fall auch kein Hack" oben bezieht sich auf den
reinterpret_cast
, nicht auf das Ändern des Owner-Windows.
-
Hier sind die Links zu den Filmen, die hoffentlich das Problem näher führen.
Film1 (meine Anwendung):
http://www.noctua-development.de-info.de/downloads/Meine_Anwendung.wmvFilm2 (MessageBox Anwendung -> wie es sein sollte)
http://www.noctua-development.de-info.de/downloads/MessageBox_Beispiel.wmvNatürlich könnte man diesen Effekt selber erzielen, aber ich habe die Hoffnung noch nicht aufgegeben, dass es etwas Hübsches aus der WinAPI gibt.
-
OK, cool, ich denke jetzt hab' ich verstanden was du willst
Du willst bloss dass dein Dialog "gesperrt" ist, so lange das andere Programm läuft, korrekt?Das sollte doch einfach sein:
Mach eine kleine Dialog-Klasse, die nen Mini-Dialog ala "[...warte auf externe Anwendung...]" oder so anzeigt (theoretisch könner man den Dialog, falls gewünscht, auch komplett unsichtbar bekommen).Dieser Dialog sollte vom Benutzer nicht schliessbar sein, also die entsprechenden Handler-Funktionen überschreiben (bei MFC wären das z.B. OnCancel und OnClose).
Einfacherweise würde ich diesem Dialog dann auch die Aufgabe übertragen das externe Programm zu starten, und zu überwachen wann das externe Programm fertig wird (z.B. einfach nen Timer und dann mit
WaitForSingleObject(hProcess, 0)
periodisch checken ob der Prozess noch läuft). Und wenn der externe Prozess fertig ist, schliesst sich der Dialog von selbst.Und diesen Dialog rufst du dann einfach modal auf. Wodurch genau das selbe passiert wie bei einer MessageBox, nämlich dass das Fenster darunter blockiert wird.
Wobei du dir überlegen solltest ob es nicht besser wäre einfach nur alle Controls (inklusive dem Fenster-schliess-"X") zu disablen während das externe Programm läuft. Ich persönlich finde das nämlich immer nervig dass ich, wenn so ein modales Gedöns offen ist, das darunterliegende Fenster nichtmal verschieben kann.
-
ps: Du kannst natürlich auch mal probieren was passiert wenn du
EnableWindow(myDialog, false)
aufrufst.
Oder sonst ein wenig googeln ob es nen einfachen Mechanismus gibt den Effekt eines modalen Dialogs zu erreichen ohne eben einen modalen Dialog anzuzeigen.
-
Habe mich für SetParent entscheiden.
Meiner Meinung nach sauberer als modaler Dialog vor Anwendung (der nicht sichtbar wäre). Danach mit SetWindowLong und SetWindowPos in meinem Fenster positioniert.
Vielen Dank für eure HilfeVideo zur fertigen Lösung:
http://www.noctua-development.de-info.de/downloads/L%C3%B6sung.wmv
-
Waaaaaaaaah
Das ist jetzt der schlimmste Hack.
Dir ist klar dass es sein kann dass das mit der nächsten 7-zip Version nimmer funktioniert?
OK, unwahrscheinlich dass es überhaupt nimmer geht, aber ... sowas macht man halt normalerweise nicht, und daher wird von Programmen auch nicht erwartet dass sie mit sowas klarkommen.