Multimedia Timer --> Implementierungsprobleme



  • Hi.

    Ich versuche in einem Thread einen Multimedia Timer zu bauen, der eine Message an diesen Thread schickt, wenn er abgelaufen ist. Allerdings scheitere ich gerade an der Implementierung.

    Hier die momentan laufende Version:

    .h

    #include <Classes.hpp>
    #include <windows.h>
    #include <mmSystem.h>
    
    class smDoor;
    void CALLBACK TimerFunc(unsigned int timerID,unsigned int msg, DWORD dwUser, DWORD dw1, DWORD dw2);
    
    class smDoor : public TThread
    {
    private:
    protected:
      void __fastcall Execute();
    public:
      __fastcall smDoor(bool CreateSuspended, Interfac* pinterf);
    };
    

    .CPP

    #include <vcl.h>
    #include "Interface.h"
    #include "smDoor.h"
    
    void __fastcall smDoor::Execute()
    {
    	timeSetEvent(5000,0, &TimerFunc,(DWORD) this ,TIME_ONESHOT);
    }
    
    void CALLBACK TimerFunc(unsigned int timerID,unsigned int msg, DWORD dwUser, DWORD dw1, DWORD dw2)
    {
    	smDoor* door = (smDoor*) dwUser;
    	PostThreadMessage(door->ThreadID,MSG_CLOSE,0,0);
    
    }
    

    Wie man sieht ist das Ganze momentan mit Forward DEclarations gelöst. Ich habe den Rest vom Code mal rausgeworfen.

    Was ich möchte: Während der Ausführung des Threads soll irgendwann ein Timer angeworfen werden, der möglichst genau nach einer gewissen Zeit eine Message an den Thread feuert. Der Thread ist ein Zustandsautomat, der mit einer Message Queue arbeitet.
    Wenn der Timer um ist soll er sich quasi selbst die Message schicken "Mach zu!". Diese Message kann auch von außen kommen.
    Kann ich diese Callback Funktion nicht auch als Elementfunktion der Klasse deklarieren und verwenden? Damit ich mir die this Übergabe und so spare... Also grob:

    .h

    #include <Classes.hpp>
    #include <windows.h>
    #include <mmSystem.h>
    
    class smDoor : public TThread
    {
    private:
      void CALLBACK TimerFunc(unsigned int timerID,unsigned int msg, DWORD dwUser, DWORD dw1, DWORD dw2);
    protected:
      void __fastcall Execute();
    public:
      __fastcall smDoor(bool CreateSuspended, Interfac* pinterf);
    };
    

    .CPP

    #include <vcl.h>
    #include "Interface.h"
    #include "smDoor.h"
    
    void __fastcall smDoor::Execute()
    {
    	timeSetEvent(5000,0, &TimerFunc,0,TIME_ONESHOT);
    }
    
    void CALLBACK smDoor::TimerFunc(unsigned int timerID,unsigned int msg, DWORD dwUser, DWORD dw1, DWORD dw2)
    {
    	PostThreadMessage(this->ThreadID,MSG_CLOSE,0,0);
    
    }
    

    Aber auf diese Art schreit mich der Compiler an.

    [C++ Fehler] smDoor.cpp(39): E2034 Konvertierung von 'void (__stdcall * (_closure )(unsigned int,unsigned int,unsigned long,unsigned long,unsigned long))(unsigned int,unsigned int,unsigned long,unsigned long,unsigned long)' nach 'void (__stdcall *)(unsigned int,unsigned int,unsigned long,unsigned long,unsigned long)' nicht möglich
    [C++ Fehler] smDoor.cpp(39): E2342 Keine Übereinstimmung des Typs beim Parameter 'fptc' ('void (__stdcall *)(unsigned int,unsigned int,unsigned long,unsigned long,unsigned long)' erwartet, 'void (__stdcall * (_closure )(unsigned int,unsigned int,unsigned long,unsigned long,unsigned long))(unsigned int,unsigned int,unsigned long,unsigned long,unsigned long)' erhalten)

    Leider hab ich mit Funktionszeigern und Callbacks NULL Übung....

    Ähm... hilfe?



  • Kann ich diese Callback Funktion nicht auch als Elementfunktion der Klasse deklarieren und verwenden?

    Ja, aber nur als static-Member-Function. Und damit klappt das auch nicht mit dem this.

    Du kannst aber eine statische TimerProc so implementieren:

    void CALLBACK smDoor::TimerProc(UINT uiTimerID, UINT uiMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
    {
       smDoor* pThis = reinterpret_cast<smDoor*>(dwUser);
       if(pThis != NULL)
          pThis->m_TimerProc(uiTimerID, uiMsg, dwUser, dw1, dw2);
    }
    

    Die private TimerProc sieht dann so aus:

    void smDoor::m_TimerProc(UINT uiTimerID, UINT uiMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
    {
       PostThreadMessage(/*this->*/ThreadID, MSG_CLOSE, 0, 0);
    }
    

    Und so würde dann die Klassen-Deklaration aussehen:

    class smDoor : public TThread
    {
       private:
          static void CALLBACK smDoor::TimerProc(UINT uiTimerID, UINT uiMsg, DWORD dwUser, DWORD dw1, DWORD dw2);
          void m_TimerProc(UINT uiTimerID, UINT uiMsg, DWORD dwUser, DWORD dw1, DWORD dw2); // oder beide protected.
       protected:
          void Execute(void);
       public:
          smDoor(bool CreateSuspended, Interfac* pinterf);
    };
    

    Das Aufrufen des Timer sähe das so aus:

    void smDoor::Execute(void)
    {
        timeSetEvent(5000, 0, smDoor::TimerProc, reinterpret_cast<DWORD>(this), TIME_ONESHOT);
    }
    

Anmelden zum Antworten