• We’re currently investigating an issue related to the forum theme and styling that is impacting page layout and visual formatting. The problem has been identified, and we are actively working on a resolution. There is no impact to user data or functionality, this is strictly a front-end display issue. We’ll post an update once the fix has been deployed. Thanks for your patience while we get this sorted.

C/C++: timers (non graphical)

Does anyone know how to do timers in either MFC (preferred) or STL when you are not using them with graphics objecects like CDialog or CFrame?

I jsut want to use a CWnd object since that has CWnd::SetTimer(). I did all the code 100% perfectly. From what I understand i need to call CWnd::Create() in order to get an HWND pointer initialized within CWnd but I couldn't figure it out.

Here is the thing. I want to encapsulate a callback method within a class. Preferably use the OnTimer() method in conjunction with SetTimer() but I can not figure it out.

Also, I do not want a C style function. And I do not want a static method in C++.

So, what am I to do? All I want is for the OS to regularly call a method (typically referred to as a callback method) ever 500 ms. I want this method to be non-static and defined as part of a method within a class (no C style functions).

EDIT:
A good google search (finally):
http://www.google.com/search?h...hod&btnG=Google+Search
 
Callbacks have to go to a static function/fixed address.

From the static function, you can call a public member of a class to handle the timer.

You can try to get the actual physical address of your OnTimer handler and pass that into your SetTimer.
 
I read up more on this. This is going to get ugly. I need to keep a static structure around that maps ids (integers) to pointers to the class I want to call. When the callback occurs, I will get an ID passed into the callback. Based on that id I will call pointer->OnTimer().

I'll consider a change on Monday.


BTW: OnTimer is a default for MFC when you call setTimer with a null argument for the function pointer. The beauty is that SetTiemr does not need to be static and it can be a per instance of hte class type of timer.
 
Why not just create a thread and user the performance counter to trigger a callback? That way you can do it in raw Win32 without having to depend on MFC. Each instance of the class can then have it's very own timer thread and associated callback function.

Sure you start dealing with thread safety and stuff, but in this case it's all pretty trivial.
 
Originally posted by: SunnyD
Why not just create a thread and user the performance counter to trigger a callback? That way you can do it in raw Win32 without having to depend on MFC. Each instance of the class can then have it's very own timer thread and associated callback function.

Sure you start dealing with thread safety and stuff, but in this case it's all pretty trivial.

A problem with MFC and all the other wrapper stuff for C# and .NET is that the internals of Win32 (which they are all built off of) becomes so hidden that anyone that was not initially exposed to the raw APIs makes it difficult to fully understand how things operate.

For about 95% of the work, it makes life easier, but the extra 5% of work becomes a PITA without understanding the underlying pinnings of the APIs

 
If you want to use CWnd, just create a message window:

CreateEx(0, WC_STATIC, 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0);

Then add a WM_TIMER handler to the message map.

If you don't want to be tied to CWnd, you could do something like this:

class Timer
{
protected:
....Timer()
....{
........hWnd = ::CreateWindow(WC_STATIC, 0, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, 0);
........if(!hWnd)
............throw std::runtime_error("Could not create message window.");
....}

....~Timer()
....{
........KillTimer();

........:😀estroyWindow(hWnd);
....}

....void SetTimer(UINT uElapse)
....{
........::SetTimer(hWnd, reinterpret_cast<UINT_PTR>(this), uElapse, TimerProc);
....}

....virtual void OnTimer()
....{
....}

....void KillTimer()
....{
........::KillTimer(hWnd, reinterpret_cast<UINT_PTR>(this));
....}

private:
....static VOID CALLBACK TimerProc(HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
....{
........reinterpret_cast<Timer*>(idEvent)->OnTimer();
....}

....//Noncopyable
....Timer(const Timer&) {}
....Timer& operator=(const Timer&) { return *this; }

private:
....HWND hWnd;
};

Subclass and override OnTimer().

You could also use a thunk for the TIMERPROC parameter of SetTimer. Then you could pass any object/method combination to SetTimer.
 
Venix,

I abandoned MFC/CWnd in favor of C functions.

I have a question though.

What does the :: in the code below do?

....void SetTimer(UINT uElapse)
....{
........::SetTimer(hWnd, reinterpret_cast<UINT_PTR>(this), uElapse, TimerProc);
....}


The code is working great by the way 🙂
 
Originally posted by: IHateMyJob2004
Venix,

I abandoned MFC/CWnd in favor of C functions.

I have a question though.

What does the :: in the code below do?

....void SetTimer(UINT uElapse)
....{
........::SetTimer(hWnd, reinterpret_cast<UINT_PTR>(this), uElapse, TimerProc);
....}


The code is working great by the way 🙂

:: is a scoping operator. It's basically telling the compiler to use the SetTimer function in the global scope of the application (and API's).

This will probably help you immensely.

A question for Venix...

I assume you're using "reinterpret_cast<UINT_PTR>(this)" to create a unique timer ID for each instance of the class, correct?
 
That's right. Since the parameter is a UINT_PTR, a cast to and from a pointer type is guaranteed to work.
 
Back
Top