SetParent und Redraw



  • Hallo,

    ich benutze die Funktion SetParent um ein von mir erstelltes Fenster in eine andere, externe Applikation einzufügen. Ich will damit quasi eine andere Anwendung, deren Quellcode mir nicht zur Verfügung steht um Funktionalität erweitern.

    Das klappt auch soweit, aber leider wird mein Fenster (welches dann ja Child-Fenster des externen Fensters ist) nach dem Parent-Wechsel nicht mehr vernünftig neu gezeichnet. Also es ist erstmal gar nicht sichtbar (was es laut IsWindowVisible aber sein müsste). Wenn ich jetzt mit der Maus in das Fenster Klicke (es handelt sich dabei um ein Edit-Control) wird nur die angeklickte Zeile sichtbar. Erst wenn ich per ctrl-a den Ganzen Inhalt markiere wird dieser neugezeichnet, nicht aber die Scrollbalken.

    Sobald jetzt in dem externen Fenster etwas wie WM_SIZE ausgelöst wird, wird mein Fenster auch wieder direkt "unsichtbar". Dabei ist besonders seltsam dass mein Fenster auf keinerlei Befehle sich neuzuzeichnen reagiert - die folgenden Funktionen hab ich schon ausprobiert:

    UpdateWindow
    RedrawWindow
    SetWindowPos (auch mit HWND_TOP oder HWND_TOPMOST)
    SendMessage mit WM_SHOWWINDOW

    aber nichts funktioniert. Mittlerweile bin ich am Ende mit meinem Latein 😞

    Hat jemand eine Idee woran das liegen könnte?

    hs


  • Mod

    Wo liegt den die Nachrichtenschleife für Dein Programm?



  • Hallo,

    also die Nachrichtenschleife liegt in meinem Programm, welches sich in einer dll befindet. Die dll wird von der externen Anwendung beim Starten geladen. Der Einstiegspunkt meiner dll sieht ungefähr so aus:

    BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
    {
    
    	// Instanz handle speichern
    	hInstance = (HINSTANCE)hModule;
    
    	switch (ul_reason_for_call)
    	{
    		case DLL_PROCESS_ATTACH:
    			// Starte Programm in neuem Thread
    			_beginthreadex(NULL, 0, ProgramStarted, NULL, 0, NULL);
    			break;
    		case DLL_THREAD_ATTACH:
    		case DLL_THREAD_DETACH:
    		case DLL_PROCESS_DETACH:
    			break;
    	}
    
    	return TRUE;
    }
    

    In der Funktion ProgramStarted wird dann die Fenster-Klasse, die Fenster etc erstellt und dort liegt auch die Nachrichtenschleife für mein Programm.

    Ich bin mir hier auch nicht sicher ob ich das mit dem _beginthreadex überhaupt richtig mache... Also die DllMain muss halt TRUE zurückgeben, sonst started die externe Anwendung nicht bis das passiert ist, daher kann ich da ja keine Message-Loop einbauen. Ich hab deswegen einen neuen Thread gestartet, können die Probleme vielleicht damit zusammenhängen?



  • Hallo nochmal,

    konnte das Problem leider immer noch nicht lösen, aber vielleicht etwas eingrenzen...

    Also die Anwendung scheint mehrere WM_ERASEBKGND zu senden. Wenn ich als Reaktion auf jedes WM_ERASEBKGND direkt den Text von meinem EditControl neu setze (also neuerText = alterText) dann bleibt das Fenster sichtbar.

    Diese Lösung gefällt mir aber nicht, da das erstens ganz schön auf die Performance geht und zweitens nur für das EditControl, aber nicht andere Child-Windows funktioniert.

    Daher die Frage, kann ich WM_ERASEBKGND irgendwie "deaktivieren"? Hab schon versucht in der Nachrichtenschleife TRUE oder FALSE zurückzugeben, hat aber nichts gebracht...



  • Um nochmal auf die Frage zurück zu kommen: Weiß denn jemand vielleicht welche Window Messages ein solches Verhalten auslösen könnten? Potentielle Kandidaten sind ja

    WM_ERASEBKGND
    WM_CTLCOLOREDIT
    WM_STYLECHANGED
    WM_WINDOWPOSCHANGED
    WM_PAINT
    WM_NCPAINT

    das sind zumindest die Nachrichten die von der Anwendungen verschickt werden und was mit dem Zeichnen der Fenster zu tun haben...



  • Ich hatte mal die Aufgabe Fenster zu erzeugen, die einmal "toplevel" am Bildschirm verschiebbar sein sollten und danach wieder als Kind in ein anderes Fenster eingebettet werden sollten. Windows hat in Abhängigkeit von ein- und ausgeschalteten visuellen Effekten dabei auch diverse Redraw Fehler produziert.
    Ich glaube, dass SetParent daher gar nicht für solche Spielereien missbraucht werden sollte und das Verhalten oft undefiniert ist ...

    Wenn ich mich richtig erinnere, kann man ein Fenster, das mit WS_POPUP erzeugt wurde, per SetParent() einem anderen Fenster unterordnen und dann den Window-Style WS_POPUP löschen und durch WS_CHILD ersetzen. Das hat mir damals nach langem Herumprobieren das richtige Redraw-Verhalten gebracht. Umgekehrt (also mit WS_CHILD erzeugt) hat es nicht funktioniert.
    Dennoch würde ich es heute nicht nochmals so machen. Außerdem müssten solche Experimente immer auf allen Plattformen mit allen Grafikeinstellungen durchprobiert werden. ... unter Windows 2000 war alles viel einfacher 😃 😃



  • xor schrieb:

    Dennoch würde ich es heute nicht nochmals so machen. Außerdem müssten solche Experimente immer auf allen Plattformen mit allen Grafikeinstellungen durchprobiert werden. ... unter Windows 2000 war alles viel einfacher 😃 😃

    Hm, das klingt jetzt erstmal nicht so toll 😞

    Also was ich mich frage: Es muss doch eine Möglichkeit geben ein Fenster wirklich komplett neu zu zeichen, oder? Denn momentan sieht es einfach so aus als würde das Redraw nichts bewirken/verschluckt werden. Denn wenn ich Text in mein Edit-Control einfüge, wird der Bereich in dem der neue Text steht ja auch neu gezeichnet...

    Hier mal zwei Screenshots um das Problem mal zu verdeutlichen:

    Text passt

    Text passt nicht mehr



  • Schon InvalidateRect ausprobiert ?

    UpdateWindow function updates the client .. if the window's update region is not empty.



  • Hey,

    also InvalidateRect scheint theoretisch zu funktionieren, macht aber den Ganzen Hintergrund von meinem Parent Fenster (auf welchem das Edit-Control sitzt) Weiß und nicht Grau (es sollte eigentlich dieses für Windows typische Grau sein das alle Fenster haben).

    Woran könnte das liegen?

    EDIT:
    Die Borders werden auch nicht neu gezeichnet sondern sind auch komplett Weiß...



  • Ist wahrscheinlich die Farbe, die für die Fensterklasse registriert ist.



  • Lol, das wars tatsächlich!

    Hab den Background der Window Class zu COLOR_WINDOW geändert und jetzt funktioniert es!!

    So einfach und ich komm nicht drauf 😃

    Vielen Dank!


Anmelden zum Antworten