Konsolenanwendung <-> Threads



  • ...That's all very well, but how do you intercept a window's message function? This is what window subclassing is all about - using SetWindowLong on a window's GWL_WNDPROC does the job. Figure 5 shows how the new procedure is attached and detached. There are a number of things worth noting about this code...

    Also gehts wieder nicht, da wir wie bereits bemerkt SetWindowLong() nicht benützen können.

    MfG SideWinder



  • Das mit alles verbieten was WM_PAINT auslösen könnte, hätte dir eh nichts gebracht, da ja z.B. auch ein Fenster, was über die Konsole geschoben wird und nachher wieder weggeschoben WM_PAINT auslöst. Das mit dem verschwinden des Inhalts bei deinem eigenen Child-Window könntest du aber so machen, dass du entweder alles in einen memDC zeichnest und diesen in WM_PAINT einfach draufblitten. Oder du "merkst" dir einfach die Zeilen deiner Konsole und blittest immer alles (am Besten du kombinierst 1 & 2, dann kannst du z.B. auch scrollen einbauen)



  • flenders schrieb:

    Das mit alles verbieten was WM_PAINT auslösen könnte, hätte dir eh nichts gebracht, da ja z.B. auch ein Fenster, was über die Konsole geschoben wird und nachher wieder weggeschoben WM_PAINT auslöst. Das mit dem verschwinden des Inhalts bei deinem eigenen Child-Window könntest du aber so machen, dass du entweder alles in einen memDC zeichnest und diesen in WM_PAINT einfach draufblitten. Oder du "merkst" dir einfach die Zeilen deiner Konsole und blittest immer alles (am Besten du kombinierst 1 & 2, dann kannst du z.B. auch scrollen einbauen)

    Nein, egal. Ich erstelle nun ein Child-Window in der Konsole in welches gezeichnet wird (fällt dem User nicht auf, da es keine Titelleiste, keinen Rahmen, etc. hat). Ich speichere bei Ausgaben die derzeitigen Formatierungsdaten und den Text selbst in einem std::vector. Sobald mein Child-Fenster WM_PAINT bekommt zeichne ich diese Daten wieder (in der richtigen Reihenfolge versteht sich).

    Damit ich die Nachrichten des Childs abfangen kann muss ich natürlich die Messageschleife gleichzeitig mit der main-Funktion machen. Dazu habe ich folgende WinMain bereits in der Libary definiert:

    int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int nShowCmd)
    {
    /* Damals bei CreateThread() benötigt, jetzt nicht mehr
    	SECURITY_ATTRIBUTES sa;
    	sa.nLength = sizeof(sa);
    	sa.lpSecurityDescriptor = NULL;
    	sa.bInheritHandle = con::FALSE;
    */
    
    	_beginthreadex(NULL,0,RealMain,NULL,0,NULL);
    
    	MSG msg;
    	while(GetMessage(&msg,con::Console.itsConHWnd,0,0))
    	{
    		TranslateMessage(&msg);
    		DispatchMessage(&msg);
    	}
    
    	return(0);
    }
    

    RealMain ruft dann je nachdem main() bzw. wmain() auf. Die Unterstützung für Parameter kommt erst - wird aber höchstwahrscheinlich mit 2 globalen Variablen gelöst werden. Damit muss der User nur die 2 Schritte die ich im anderen Thread beschrieben habe durchführen und kann schon mit meiner Libary arbeiten.

    Auf welche Nachrichten muss ich nun eigentlich alles reagieren?

    WM_PAINT und WM_DESTROY habe ich bis jetzt - mehr aber auch noch nicht. WM_SIZE wird zur Sicherheit auch noch reinkommen und setzt die Größe des Fensters auf die Konsolengröße - damit passt das Fenster immer schön in die Konsole! Da man ja die Konsolengröße jederzeit abfragen kann ist es auch kein Problem in der GetMessage()-Schleife eine Abfrage einzubauen - wenn ja gleich noch ein SendMessage() mit WM_SIZE hinterher.

    Gibts da sonst noch etwas zu beachten?

    MfG SideWinder



  • Funktioniert - soweit so gut. Doch wie kann ich bei GetMessage() die Messages eines Child-Fensters bekommen? Muss ich bei "hwnd" das HWND des Child-Fensters übergeben?

    Das funktioniert noch nicht so recht :(.

    MfG SideWinder



  • Nimm doch einfach NULL - dann holt er sich alle Nachrichten 🙄



  • flenders schrieb:

    Nimm doch einfach NULL - dann holt er sich alle Nachrichten 🙄

    Habe ich - aber das Problem ist ich weiß nicht in welchen Thread meine Variable Console gehört.

    Das erste Mal benützt wird sie schließlich in main() alsow gehört sie wohl auch zu diesem Thread. Das heißt, dass dieses Fenster in diesem Thread erstellt wird, was wiederrum heißt ich kann in WinMain() gar nicht die richtigen Nachrichten bekommen, weil GetMessage() nur Nachrichten des jetzigen Threads abholen kann.

    Oder habe ich da wiedermal etwas übersehen? 😞

    MfG SideWinder



  • Bitte vergiss dein Vorhaben - das wird nichts.



  • === schrieb:

    Bitte vergiss dein Vorhaben - das wird nichts.

    Danke wie aufmunternd. Ich hoffe dennoch, dass dieses Projekt etwas wird. Sobald es nun endlich funktioniert kann ich es optimieren. Immerhin ist es nur noch ein kleiner Schritt zum funktionsfähgien Programm ;).

    MfG SideWinder



  • Durch Logging habe ich nun herausgefunden, das er meine WinMain() erst gar nicht aufruft 😮 Statt dessen ruft er als erstes die Funktion wmain() im vom User definierten Hauptprogramm auf - es ist aber sicher eine Win32-Applikation und keine Konsolenapplikation.

    Was habe ich da schon wieder falsch gemacht? 😞

    MfG SideWinder



  • Dein main-Überschreiben-Vorhaben ist auch irgendwie daneben. Mach einfach eine Funktion InitSidewindersConsole() die der Benutzer dann einmal nach dem Eintritt in main aufruft und gut.

    Und wieso du SetWindowLong nicht verwenden kannst versteh ich nicht.. Du solltest es, wie gesagt, besser mit Hooks machen.. aber wie du meinst.



  • DrGreenthumb schrieb:

    Dein main-Überschreiben-Vorhaben ist auch irgendwie daneben. Mach einfach eine Funktion InitSidewindersConsole() die der Benutzer dann einmal nach dem Eintritt in main aufruft und gut.

    Und wieso du SetWindowLong nicht verwenden kannst versteh ich nicht.. Du solltest es, wie gesagt, besser mit Hooks machen.. aber wie du meinst.

    Das Hauptfenster der Anwendung ist und bleibt die Konsole, zuerst wird eine Konsole alloziert und danach ein Fenster als Child - Grund: Ich muss mich nicht um so Dinge wie Umleiten des Konsolenpuffers, Größe der Konsole, Aussehen der Konsole, etc. kümmern. Doch in der Konsole habe ich keinen Zugriff auf SetWindowLong() - gibt jedesmal einen Error - siehe anderer Thread von mir "Wnd: ..."

    InitConsole() als Funktion klingt spannend, ich muss dort einfach die Message-Schleife als Thread starten. *Versuchen geh*

    MfG SideWinder



  • Ich raffs nicht, obwohl ich folgendes stehen habe:

    con::console& Console = con::console::get_instance();
    

    Wird get_instance() NIE aufgerufen! Ich logge in der get_instance() wieder mit meiner Log-Klasse mit, und: Sie wird nicht mit aufgerufen.

    Warum denn das?

    MfG SideWinder



  • Hier mal meine Dateien:

    [url=http://www.sidewindershome.net\cache\curproject\console2.h.html]console2.h[/url]
    [url=http://www.sidewindershome.net\cache\curproject\console2.cpp.html]console2.cpp[/url]

    Wahrscheinlich habe ich wieder irgendwo einen Idiotenfehler :(.

    MfG SideWinder





  • Was habe ich falsch verlinkt? Bei mir funktionieren meine Links einwandfrei.

    MfG SideWinder


Anmelden zum Antworten