Merkwürdiges verhalten der Statusanzeige



  • Hallo!

    Ich habe eine kleine MFC Anwendung, die auf der Basis zweier Parameter eine Zeitspanne ausrechnet. Den Ablauf dieser Zeitspanne möchte ich durch einen Fortschrittsbalken anzeigen lassen. Vom Grundprinzip funktioniert das soweit auch, doch passt der Verlauf des Balkens nicht mit dem Ablauf der Zeitspanne überein. Soll heißen mal ist die Zeitspanne um, aber der Balken nur zu 2/3 gefüllt, mal läuft der Balken drei mal komplett durch bis die Zeit abgelaufen ist. Ich steig nicht dahinter, warum das so ist.

    [...]
    
    //Breite und Schrittweite des Fortschrittsbalkens setzen
    m_progress.SetRange(0, m_duration);
    m_progress.SetStep(100);
    
    //Timer startet
    SetTimer(ID_COUNT_TIMER, m_duration, NULL);
    SetTimer(ID_PROGRESS_TIMER, 100, NULL);
    
    [...]
    
    void CMeinTestDlg::OnTimer(UINT nIDEvent) 
    {
    	//Welcher Timer hat das Ereignis ausgelöst?
    	switch (nIDEvent)
    	{
    	case ID_COUNT_TIMER:
    		//Fortschrittsbalken aktualisieren
    		m_progress.StepIt();
    
    		[...]
    
    		//Fortschrittsbalken zurücksetzen
    		m_progress.SetPos(0);
    	break;
    	case ID_PROGRESS_TIMER:
    		//Fortschrittsbalken aktualisieren
    		m_progress.StepIt();
    	break;
    	}
    
    	CDialog::OnTimer(nIDEvent);
    }
    

    Ein weiteres Problem, dass ich habe ist, dass ich ceil() nicht verwenden kann? Der Compiler meckert immer über einen unbekannten Bezeichner obwohl ich math.h einbinde. Muss ich etwas zusätzliches beachten um Funktionen wie ceil() innerhalb meiner MFC Anwendung verwenden zu können?



  • Weiß niemand eine Antwort, oder habe ich meine Frage so unglücklich gestellt, dass keiner antworten will? 🙂



  • Also wenn du mit #include <math.h> die Header richtig eingebunden hast dürfte es funktionieren. Allerdings steig ich nicht durch was du in der OnTimer machst. Wie groß ist denn bei dir üblicherweise m_duration? Was mach der Aufruf m_Progress.SetPos(0) in Zeile 22? Mit jedem Timerdurchlauf (abhängig von m_duration) wird der Balken wieder auf 0 gesetzt?
    Was machst du in der StepIt?


  • Mod

    Timer Nachrichten werden nicht mit 100% Sicherheit ausgeliefert.
    Macht Dein Programm für mehr als 100msec etwas also z.B. 150msec, dann wird erst beim nächsten Ausführen von GetMessage/PeekMessage eine Timer Nachricht ausgelöst. Der nächste TImer kommt dann aber wieder in 100msec! Du hast also schon 50msec Verzögerung.

    Mach es doch besser so, dass Du Dir die Startzeit merkst und dann einfach wenn der Timer fällt, den Wert des Progressbars entsprechend setzt. Dann verkraftet Dein System auch längere "Pausen".



  • AndyDD schrieb:

    Also wenn du mit #include <math.h> die Header richtig eingebunden hast dürfte es funktionieren.

    Ah ok, habe jetzt nochmal etwas herumgetestet. Wenn ich den Header als letztes einbinde dann gehts, binde ich ihn als ersten ein, meldet der Compiler einen Fehler.
    Kann mir das einer erklären? Bin noch nicht so fitt in C++ 😉

    AndyDD schrieb:

    Allerdings steig ich nicht durch was du in der OnTimer machst.

    Ich prüfe zuerst welcher Timer abgelaufen ist. ID_COUNT_TIMER ist für den gesamten Durchlauf und ID_PROGRESS_TIMER nur zum aktualisieren der Progressbar.

    AndyDD schrieb:

    Wie groß ist denn bei dir üblicherweise m_duration?

    Das schwankt recht stark. Mittelwert sind vielleicht ca. 80.000

    AndyDD schrieb:

    Was mach der Aufruf m_Progress.SetPos(0) in Zeile 22? Mit jedem Timerdurchlauf (abhängig von m_duration) wird der Balken wieder auf 0 gesetzt?
    Was machst du in der StepIt?

    Ja, SetPos() und StepIt() sind Methoden von CProgressCtrl. SetPos setzt die Position des Balkens (0 bewirkt hier einen Neustart) und StepIt() bewirkt ein Fortschreiten des Balkens um die durch SetStep festgelegte Weite.

    @Martin
    Ok, ich hätte nicht gedacht, dass sich diese Verzögerungen so gravierend bemerkbar machen. Ich werde mal schauen, ob ich deinen Vorschlag so umgesetzt bekomme. Danke 🙂



  • Thunderb0lt schrieb:

    Ah ok, habe jetzt nochmal etwas herumgetestet. Wenn ich den Header als letztes einbinde dann gehts, binde ich ihn als ersten ein, meldet der Compiler einen Fehler.
    Kann mir das einer erklären? Bin noch nicht so fitt in C++ 😉

    Welchen Fehler bringt er denn und wo hast du ihn denn eingebunden?
    Trotzdem verstehe ich noch nicht ganz das was deine OnTimer macht. Wenn m_duration ca. 80.000 beträgt, so kommt alle ca. alle 80 sek. (nehmen wir jetzt mal an, ist halt nicht garantiert, siehe Post von Martin) ein Timerereignis mit der ID ID_COUNT_TIMER. Der Balken hat dann auch ca. 80.000 Einheiten und mit StepIt kannst du ihn jeweils um 100 Einheiten weiterrücken. Anscheinend machst du da noch mehr, ich deute die [] da einfach mal so.
    Da ist doch klar das die Timerereignisse mit der ID ID_PROGRESS_TIMER dann nicht abgearbeitet werden können (Zeitintervall 100 ms). Dann tritt genau das auf was Martin sagte.


  • Mod

    Das hängt immer davon ab, was Du machst!
    Was ist das Problem mit meinem Vorschlag? Mit GetTickCount einfach die Startzeit merken. Auf den Timer hin, einfach die Differenz bilden und den Progressbar entsprechend setzen.



  • Ok, zunächst der Hinweis ich Arbeite mit Visual C++ 6 😃

    In der MeinTestDlg.cpp hat VC++ nun ja bereits automatisch einige Header eingebunden.

    #include "stdafx.h"
    #include "MeinTest.h"
    #include "MeinTestDlg.h"

    wenn ich hier jetzt das #include <math.h> noch vor das #include "stdafx.h" setze, dann schmeißt er mir den Fehler:
    error C2065: 'ceil' : nichtdeklarierter Bezeichner
    Fehler beim Ausführen von cl.exe.

    Binde ich math.h nach MeinTestDlg.h ein, dann compiliert er ohne zu meckern.

    In den [...] passiert nicht wirklich viel. Und ausschlaggebend können sie für die Verzögerung nicht wirklich sein, denn die ProgressBar ist schon vor dem ersten Durchlauf nicht mehr Synchron. Wie gesagt ich haette nicht damit gerechnet, dass sich diese Verzögerung so extrem zeigt.

    Hundertprozentig wird Martins Vorschlag denke ich dann auch nicht funktionieren, aber zumindest wird die Bar dann bei jedem Timerereignis wieder korrekt synchronisiert.
    Problem ist nur - so dumm das klingt - ich schaff es nicht eine entsprechende Variable zu basteln.
    Mit dem Klassen-Assistent von VC++ kann ich ja nur Steuerelementen eine Variable zuweisen. Das will ich hier ja aber nicht. Wenn ich versuche die Variable per Hand im Code zu deklarieren schmeißt er mir immer einen Fehler.
    Ich find aber auch die Stelle im Code nicht, wo die anderen Variablen, die ja Steuerelementen zugewiesen sind, deklariert werden!?

    Entweder ich bekomme ein 'Nur Funktionen koennen rein virtuell deklariert werden' wenn ich die Variable deklarieren will oder ein 'nichtdeklarierter Bezeichner' wenn ich der Variablen dann einen Wert zuweisen möchte.
    Je nachdem, wo ich die Variable deklariere. Ich habe schon so viele Stellen ausprobiert, und komme einfach nicht weiter.


  • Mod

    Mach Dich bitte mal vertraut mit "vorkompilierten Headern" alle Statements vor der Zeile #include "stdafx.h" werden vom Compiler ignoriert!



  • Ahso ist das ^^
    Ja, davon steht hier in meinem Büchlein nix xD
    Dann werde ich mich mal um ein Tutorial zu diesem Thema bemühen.
    Hast du noch einen Tipp zu der Variablengeschichte?


  • Mod

    Thunderb0lt schrieb:

    Hast du noch einen Tipp zu der Variablengeschichte?

    Was meinst Du?



  • Ich wollte deinen Vorschlag mit dem Timestamp umsetzen.
    Problem ist nur - so dumm das klingt - ich schaff es nicht eine entsprechende Variable zu basteln.
    Mit dem Klassen-Assistent von VC++ kann ich ja nur Steuerelementen eine Variable zuweisen. Das will ich hier ja aber nicht. Wenn ich versuche die Variable per Hand im Code zu deklarieren schmeißt er mir immer einen Fehler.
    Ich find aber auch die Stelle im Code nicht, wo die anderen Variablen, die ja Steuerelementen zugewiesen sind, deklariert werden!?

    Entweder ich bekomme ein 'Nur Funktionen koennen rein virtuell deklariert werden' wenn ich die Variable deklarieren will oder ein 'nichtdeklarierter Bezeichner' wenn ich der Variablen dann einen Wert zuweisen möchte.
    Je nachdem, wo ich die Variable deklariere. Ich habe schon so viele Stellen ausprobiert, und komme einfach nicht weiter.


Anmelden zum Antworten