[C++]Simple nativated timer class


從.NET跨足到C++筆者還是不太習慣C++的寫作方式,比較習慣於用.NET的寫法來寫C++程式,既然C++也開始具備屬性跟事件,C++也能寫的跟.NET程式很像。這邊筆者試寫了一個簡單的C++ Nativated Timer,希望使用上會比較接近.NET的寫作習慣,這邊將之稍做整理。





程式的部分主要有EventArgs與Timer兩個類別,程式碼如下:





EventArgs.h




#pragma once
class EventArgs
{
#pragma region Constructor & DeConstructor
public:
EventArgs(void);
virtual ~EventArgs(void);
#pragma endregion

};





EventArgs.Cpp






#include “stdafx.h”
#include “EventArgs.h”


#pragma region Constructor & DeConstructor
EventArgs::EventArgs(void)
{
}


EventArgs::~EventArgs(void)
{
}
#pragma endregion







Timer.h






#pragma once
#include “EventArgs.h”
#include <Windows.h>

[event_source]
[event_receiver]
class Timer
{
#pragma region Var
private:
int _nTimerID;
int _nInterval;
bool _bIsEnabled;
#pragma endregion


#pragma region Private Property
private:
declspec(property(get=Get_nTimerID,put=Set_nTimerID))
int m_nTimerID;
#pragma endregion


#pragma region Public Property
public:
declspec(property(get=Get_nInterval,put=Set_nInterval))
int m_nInterval;

declspec(property(get=Get_bIsEnabled,put=Set_bIsEnabled))
bool m_bIsEnabled;
#pragma endregion


#pragma region Event
public:
event void IntervalChanging(void sender, EventArgs e);
event void IntervalChanged(void sender, EventArgs e); event void IsEnabledChanging(void sender, EventArgs e);
event void IsEnabledChanged(void sender, EventArgs e); event void Tick(void sender, EventArgs e);
#pragma endregion


#pragma region Constructor & DeConstructor
public:
Timer(int nInterval = 0);
Timer(bool bIsEnabled, int nInterval = 0);
virtual ~Timer(void);
#pragma endregion


#pragma region Property Process Method
private:
inline int Get_nTimerID()
{
return _nTimerID;
}

inline void Set_nTimerID(int value)
{
if(_nTimerID == value)
return;

_nTimerID = value;
}

public:
inline int Get_nInterval()
{
return _nInterval;
}

inline void Set_nInterval(int value)
{
if(_nInterval == value)
return;

EventArgs e;
OnIntervalChanging(&e);

_nInterval = value;

OnIntervalChanged(&e);
}

inline bool Get_bIsEnabled()
{
return _bIsEnabled;
}

inline void Set_bIsEnabled(bool value)
{
if(_bIsEnabled == value)
return;

EventArgs e;
OnIsEnabledChanging(&e);

_bIsEnabled = value;

OnIsEnabledChanged(&e);
}
#pragma endregion


#pragma region Private Method
private:
void Init(bool bIsEnabled = false, int nInterval = 0);
void UnBindingEvent();
void BindingEvent();
void KillTimer();
void SetTimer();

static void CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
#pragma endregion


#pragma region Protected Method
protected:
virtual void Reset(bool bIsInit = false);

void OnIntervalChanging(EventArgs e)
{
__raise IntervalChanging(this, e);
}

void OnIntervalChanged(EventArgs
e)
{
raise IntervalChanged(this, e);
}

void OnIsEnabledChanging(EventArgs* e)
{
raise IsEnabledChanging(this, e);
}

void OnIsEnabledChanged(EventArgs e)
{
__raise IsEnabledChanged(this, e);
}

void OnTick(EventArgs
e)
{
raise Tick(this, e);
}
#pragma endregion


#pragma region Public Method
public:
void Start();
void Stop();
#pragma endregion


#pragma region Event Process
private:
void Timer_IsEnabledChanged(void sender, EventArgs e);
void Timer_IntervalChanged(void sender, EventArgs e);
#pragma endregion
};







Timer.Cpp




#include “stdafx.h”
#include “Timer.h”
#include <map>

using namespace std;

map<int, Timer*> g_TimerPool;

#pragma region Constructor & DeConstructor
Timer::Timer(int nInterval)
{
Init(false, nInterval);
}

Timer::Timer(bool bIsEnabled, int nInterval)
{
Init(bIsEnabled, nInterval);
}

Timer::~Timer(void)
{
Reset();
}
#pragma endregion


#pragma region Private Method
void Timer::Init(bool bIsEnabled, int nInterval)
{
Reset(true);
m_bIsEnabled = bIsEnabled;
m_nInterval = nInterval;
BindingEvent();
}

void Timer::UnBindingEvent()
{ unhook(&Timer::IsEnabledChanged, this, &Timer::Timer_IsEnabledChanged);
unhook(&Timer::IntervalChanged, this, &Timer::Timer_IntervalChanged);
}

void Timer::BindingEvent()
{
UnBindingEvent();
hook(&Timer::IsEnabledChanged, this, &Timer::Timer_IsEnabledChanged);
hook(&Timer::IntervalChanged, this, &Timer::Timer_IntervalChanged);
}

void Timer::KillTimer()
{
if(!m_nTimerID)
return;
::KillTimer(NULL, m_nTimerID);
g_TimerPool[m_nTimerID] = NULL;
m_nTimerID = 0;
}

void Timer::SetTimer()
{
KillTimer();

if(!m_bIsEnabled)
return;

if(m_nTimerID)
return;

m_nTimerID = ::SetTimer(NULL, NULL, m_nInterval, TimerProc);
g_TimerPool[m_nTimerID] = this;
}

void CALLBACK Timer::TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
if(g_TimerPool.find(idEvent) == g_TimerPool.end())
return;

Timer* pTimer = g_TimerPool[idEvent];

if(!pTimer)
return;

EventArgs eventArgs;
pTimer->OnTick(&eventArgs);
}
#pragma endregion


#pragma region Protected Method
void Timer::Reset(bool bIsInit)
{
if(bIsInit)
{
_nTimerID = 0;
}
unhook(this);

UnBindingEvent();

_bIsEnabled = false;
_nInterval = 0;

if(_nTimerID)
{
KillTimer();
_nTimerID = 0;
}
}
#pragma endregion


#pragma region Public Method
void Timer::Start()
{
m_bIsEnabled = true;
}

void Timer::Stop()
{
m_bIsEnabled = false;
}
#pragma endregion


#pragma region Event Process
void Timer::Timer_IsEnabledChanged(void sender, EventArgs e)
{
SetTimer();
}

void Timer::Timer_IntervalChanged(void sender, EventArgs e)
{
SetTimer();
}
#pragma endregion





使用上會像下面這樣,設定Timer的週期與是否啟用,並繫結事件處理常式做對應的處理。




// ConsoleApplication9.cpp : Defines the entry point for the console application.
//
#include “stdafx.h”
#include <Windows.h>
#include “Timer.h”

class TestClass
{
public:
Timer m_Timer;
int m_nTickCount;

TestClass()
{
m_nTickCount = 0;
__hook(&Timer::Tick, &m_Timer, &TestClass::Timer_Tick);
m_Timer.m_nInterval = 1000;
m_Timer.m_bIsEnabled = true;
}

void Timer_Tick(void sender, EventArgs e)
{
++m_nTickCount;
printf(“Timer_Tick\r\n”);
}
};

int _tmain(int argc, _TCHAR* argv[])
{
MSG msg;
TestClass testObj;

while (testObj.m_nTickCount < 10)
{
GetMessage(&msg, NULL, 0, 0);
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}





運行後可每秒寫出一個Timer_Tick的字串,運行十秒後結束。



image