Timerinterrupt, Funktionsaufruf daraus



  • Folgendes Problem:

    Ich habe einen Timer- Interrupt, der z. B. alle 2 Sekunden angesprungen wird

    Siehe hier:

    void CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
    {
    int i=0;

    Cson1Dlg::aktualisieren();

    i = i + 1;
    }

    void timerinit()
    {
    TimerId = SetTimer(NULL, 0, 2000, (TIMERPROC)TimerProc);
    }

    Jetzt will ich aus der Timerroutine heraus die Funktion "aktualisieren" aufrufen, was aber nicht funtioniert. Definiert ist sie im Header. Ich kann diese Routine aber zu Testzwecken zum Beispiel aufrufen, wenn ich diesen Aufruf in einer Funktion eines "Button" einbaue. Da kann ich sie dann einfach mit "aktualisieren()" aufrufen. Was mache ich verkehrt?

    schon mal schönen Dank..... und noch mal die Frage nach entsprechender Literatur. Irgendwie scheint es so zu sein, dass immer das, was man gerade braucht, nicht beantwortet wird. Gibt es da "die Bibel", besonders in Hinblick auf MFC?



  • Du meinst, du möchtest eine Methode aufrufen? Dafür brauchst du natürlich ein entsprechendes Objekt, auf das du die Methode anwendest. Du kannst beispielsweise einen Zeiger auf ein solches als ID des Timers verwenden, die du im Timerhandler wieder zu einem Zeiger castest. Aber nur aus Interesse: Du verwendest tatsächlich heutzutage die MFC?



  • Äh, ja..... hatte vorher im Netz ein wenig rumgesucht und MFC wurde von vielen über den grünen Klee gelobt. C++ habe ich vorher noch nie programmiert, deshalb wollte ich es mir mit so einer verbreiteten Sache etwas vereinfachen, in der Hoffnung, da viele Codeschnipsel im Netzt zu finden, ist aber ne ziemlich Sucherei... ich ahne, was Du meinst.... was ich nur nicht verstehe.... ich habe in meinem "Hauptprogramm" diverse ...ja... Funtionen, Callbacks, was auch immer, die von dem Programm, dem Assistenten generiert wurden. Also z. B. "Button 1", "Edit Box 1" usw. Wenn ich jetzt eine ganz normale Funktion in diesem Bereich schreibe, die auch brav im Header deklariere...... (also z. B. dieses void aktualisieren()), dann kann ich diese Funktion z. B. nach der Betätigung eines button aufrufen, alles gut.... aber nicht, wenn ich das aus dem Timer heraus mache. Das verwirrt mich ein wenig.....


  • Mod

    1. Ein Timer ist kein Interrupt. Er unterbricht also in keiner Weise Dein Programm.
    2. Ein Timer wird nur aufgerufen, wenn auch die Message-Pump läuft...



  • Nun ja.... das wirst Du besser wissen als ich... anyway.... es ist natürlich so, dass mein Timer alle x- Sekunden angesprungen wird. So weit, so gut. Nur, dass ich aus diesem "Interrupt" heraus eben nicht die "Funktion" aktualisieren() aufrufen kann, die ich aber eben z. B. aus so einer "ich habe einen Button gedrückt"- Funktion heraus aufrufen kann. Da verstehe ich den Unterschied nicht....

    Also vom Prinzip her:

    void aktualisieren()
    {

    // Hier sind ein paar Funktionen, wie z. B. Uhrzeit aktualisieren
    // die ich aber eigentlich zyklisch aufrufen möchte, nicht über einen Button,
    // das diente nur dem Test

    }

    void Cson1Dlg::OnBnClickedButton1() // ------> das geht!
    {
    aktualisieren();

    }

    void timerinit()
    {
    TimerId = SetTimer(NULL, 0, 3000, (TIMERPROC)TimerProc);
    }

    void CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
    {

    aktualisieren(); // und das geht nicht!
    // da ist der Bezeichner nicht definiert,
    // aber warum hier nicht, bei Clicked Button schon
    // und, was das wichtigste ist: wie kriege ich es
    // hin?

    }



  • Ob man ne Callback-Funktion innerhalb des MFC-Gerüst brauch weiß ich gar nicht. Du solltest erst mal eine Nachricht definieren.

    #define ID_YOURMESSAGE	WM_USER+1
    

    Dann musst du auf diese Nachricht innerhalb deiner Dialogklasse reagieren können. Du brauchst dafür eine Methode:

    // Eintrag in der Massage-Map nicht vergessen
    BEGIN_MESSAGE_MAP(Cson1Dlg, CDialogEx)
    	ON_WM_TIMER()
    END_MESSAGE_MAP()
    
    // WM-Timer-Methode kannste über den Klassenassistenten generieren
    void Cson1Dlg::OnTimer(UINT_PTR nIDEvent)
    {
    if (nIDEvent == ID_YOURMESSAGE)
    	{
    		aktualisieren();
    	}
    
    	CDialogEx::OnTimer(nIDEvent);
    }
    

    Dann musst du nur noch irgendwo

    SetTimer(ID_YOURMESSAGE, 3000, NULL);
    

    aufrufen. Natürlich solltest du das Ding auch wieder mit

    KillTimer(ID_YOURMESSAGE);
    

    beenden.



  • Hallo nochmal..... schönen Dank für die Mühe, so ganz langsam fange ich an, zu verstehen 😉 Na ja, oder auch nicht....."Er" kennt mittlerweile die Funktion aktualisieren auch in "OnTimer, dafür meckert er aber bzgl. OnTimer "Ein vererbter Member ist nicht zulässig".... hmmm..... ich suche auch schon wie wild....



  • Nachtrag..... nochmal ne Frage zu dem Aufruf von SetTimer.... wenn ich mittels #define eine ID festlege, ist di evom Type "int" oder so. SetTimer will aber als Parameter was anderes...?

    SetTimer(
    _In_opt_ HWND hWnd,
    _In_ UINT_PTR nIDEvent,
    _In_ UINT uElapse,
    _In_opt_ TIMERPROC lpTimerFunc);



  • Verstehe ich jetzt nicht ganz.Mit dem Klassenassistenten einfach eine Methode zur Behandlung von WM_TIMER einfügen. Dann werden die Einträge auch in der Message-Map automatisch generiert. SetTimer hat 3 Parameter:

    MSDN schrieb:

    Parameter

    nIDEvent
    Gibt einen Zeitgeberbezeichner ungleich 0 (null) an. Wenn der Zeitgeberbezeichner eindeutig ist, wird von SetTimer der gleiche Wert zurückgegeben. Andernfalls wird von SetTimer ein neuer eindeutiger Wert festgelegt und zurückgegeben. Bei einem Fensterzeitgeber (der eine NULL-Rückruffunktion besitzt), muss der Wert nur für andere Fensterzeitgeber eindeutig sein, die dem aktiven Fenster zugeordnet sind. Für einen Rückrufzeitgeber muss der Wert für alle Zeitgeber in allen Prozessen eindeutig sein. Beim Erstellen eines Rückrufzeitgebers ist es daher wahrscheinlicher, dass der zurückgegebene Wert von dem von Ihnen angegebenen Wert abweicht.

    nElapse
    Gibt den Timeoutwert oder Intervall in Millisekunden an.

    lpfnTimer
    Gibt die Adresse der von der Anwendung bereitgestellten TimerProc-Rückruffunktion an, von der die WM_TIMER-Meldungen verarbeitet werden. Wenn dieser Parameter NULL ist, werden die WM_TIMER - Meldungen in der Meldungswarteschlange der Anwendung platziert und vom CWnd-Objekt behandelt.

    Wenn Du das Beispiel so abarbeitest wie ich es beschrieben habe müsste es funktionieren. Was meinst du denn genau mit:

    emmamenden schrieb:

    ... "Er" kennt mittlerweile die Funktion aktualisieren auch in "OnTimer, dafür meckert er aber bzgl. OnTimer "Ein vererbter Member ist nicht zulässig"....



  • ich probier das noch mal.....danke erst mal!


Log in to reply