while-Schleife: GUI wird nicht freigegeben



  • net schrieb:

    wenn's mfc ist: AfxGetApp()->PumpMessage();

    Genau das muss es sein 🙂 Ich hab nochmal nachgedacht und mir ist aufgefallen, dass ein Thread zuviel des Guten wäre, zumal ich ja nur wie bei Delphi Messages forcieren muss, dieses PumpMessages tut dies hoffentlich, muss ich gleich mal testen.

    Wie baue ich so einen Timer? Zur Zeit benutze ich die Clock-Funktion gepaart mit einer wait-Routine, was ja eigentlich dasselbe macht oder?



  • Timer geht ganz einfach, schau dir diese Funktionen mal an:
    SetTimer
    WM_TIMER
    KillTimer

    Oder guck da mal: http://www.se.fh-heilbronn.de/usefulstuff/VCPLUS6/inhalt.htm Tag 4



  • Du musst künstlich dafür sorgen, das die Nachrichten weitergeleitet und verarbeitet werden.

    Müsste etwa so aussehen:

    MSG msg;
    while (PeekMessage(&msg, NULL, 0,0, PM_NOREMOVE))
    {
        AfxGetApp()->PumpMessage();
    }
    

    (ungetestet, einfach mal probieren 😉 )


  • Mod

    @JPSelter

    Ich kann nur davon abraten den Anstz zu verwenden der hier mehrfach empfolhlen wurde, AfxGetApp()->PumpMessage(), zu verwenden.

    Dein Programm wird dadurch reentrant! D.h. während der Ausführung steht Deine komplette GUI wieder zur Verfügung und man kann theoretisch alle möglichen Operationen durchführen. Du müsstest vorher alle entsprechenden GUI Elemente disablen.

    Nehmen wir mal an Du hättest Button1 und Button2 in Deinem Diaoh. Button1 löst die lange Berechnung aus, und dort wird AfxGetApp()->PumpMessage() aufgerifen.
    Der User kann nun Button2 klicken, was evtl. auch wieder was auslöst. Oder er klickt nocohmal Button1 und die Berechnung wird zum zweiten mal gestartet.

    Evtl. langt es ja, wenn Du mit UpdateWindow die UI mal refreshst!



  • estartu schrieb:

    Oder du machst nen Timer. 🙂

    Das wird wohl nix, da der Timer auch nur eine Nachricht sendet. Diese wird aber in der OnStart() auch nicht verarbeitet.

    Ich empfehle ebenfalls eine Lösung mit Threads.



  • Martin Richter schrieb:

    @JPSelter

    ...
    Dein Programm wird dadurch reentrant! D.h. während der Ausführung steht Deine komplette GUI wieder zur Verfügung und man kann theoretisch alle möglichen Operationen durchführen. Du müsstest vorher alle entsprechenden GUI Elemente disablen....

    Naja, in der MSG Struktur steht ja der hwnd des Fensters an das die Nachricht geht sowie der Nachrichtentyp. Dadurch lassen sich diese gezielt rausfiltern.

    Evtl. langt es ja, wenn Du mit UpdateWindow die UI mal refreshst!

    Nö, auch dies löst eine Nachricht aus und zeigt erst wieder Wirkung wenn das Programm die while Schleife verlässt und seine Nachrichtenschleife wieder aufnimmt.



  • Gill Bates schrieb:

    estartu schrieb:

    Oder du machst nen Timer. 🙂

    Das wird wohl nix, da der Timer auch nur eine Nachricht sendet. Diese wird aber in der OnStart() auch nicht verarbeitet.

    Das kommt ganz darauf an, was die OnTimer()-Methode macht 😉

    Im einfachsten Fall setzt die OnStart() lediglich den Timer und beendet sich dann wieder. Und in der OnTimer()-Verarbeitung fragst du erst ab, ob die Endebedingungen erfüllt wurden, wenn ja, verarbeitest du ein Bild, setzt den Timer neu und beendest die Methode.
    (auf die Weise wird die Methode immer zyklisch wieder aufgerufen, aber deine Anwendung hat zwischendurch Zeit, andere Nachrichten zu bearbeiten)

    Bei der Alternativlösung mit dem Thread behältst due deine normale while()-Schleife bei - da diese aber in einem eigenen Thread läuft, stört sie die GUI-Verarbeitung des Programms nicht weiter (die OnStart() schupst lediglich den Thread an (eventuell nach etwas Vorarbeit), merkt sich sein Handle und kehrt zur Nachrichtenschleife zurück).



  • Ich hätte fast den Weg von CStoll genommen:
    OnStart: SetTimer, sonst nix.
    OnEnde: KillTimer, sonst nix.
    OnTimer: Bild abholen und anzeigen

    Aber nachdem ich über das von CStoll nachgedacht habe... wenn das Bild abholen lange dauert, sollte man es so abändern:
    OnTimer: KillTimer, Bild abholen und anzeigen, SetTimer


  • Mod

    Cpp_Junky schrieb:

    Nö, auch dies löst eine Nachricht aus und zeigt erst wieder Wirkung wenn das Programm die while Schleife verlässt und seine Nachrichtenschleife wieder aufnimmt.

    Unsinn. Der Button wird geklickt. Die Mausnachricht wird an den Button aufgrund der des message pumps abgeholt und ausgeführt und die WM_COMMAND Nachricht wird sofort versendet und der Handler dann ein zweites mal aufgerufen!

    Eigene Message Pumps sind nur in extrem wenigen Fällen sinnreich. In diesem in jedem Falle nicht! Just my 2 cents!



  • Danke für die vielen Vorschläge. Ich probiere einfach mal alles nacheinander aus. Das Bildholen dauert übrigens nicht lange und zudem liefert die Kamera eh nur mit maximal 5fps. Zu dem PumpMessages: Ein disablen der GUI Komponenten ist selbstverständlich 😉



  • EDIT: Hat sich erledigt 😉



  • Willst du kein Anfängerprogramm dann verwende Threads.
    Leite eine Klasse von CWinThreads ab.
    Wie du dann noch auf die GUI zugreifen kannst steht in der FAQ. (this an Threadklasse übergeben)
    Threads sind nur dann komplexer wenn du sie syncronisieren musst.


Anmelden zum Antworten