Компонента реализует собственный класс таймера на основе выделенного потока. Вот процедура потока
DWORD WINAPI CTimer::TimerThread(LPVOID lpParameter)
{
DWORD LastTickCount = ::GetTickCount();
do
{
DWORD NewTickCount = ::GetTickCount();
if(abs(NewTickCount - LastTickCount) >= GLOBAL_TIMER_DELAY)
{
LastTickCount = NewTickCount;
if(CTimer::m_hMutex && ::WaitForSingleObject(CTimer::m_hMutex, MUTEX_DELAY) == WAIT_OBJECT_0)
{
::PostThreadMessage(m_ParentThreadId, WM_VXPTIMER, 0, NULL);
::ReleaseMutex(CTimer::m_hMutex);
}
}
Sleep(GLOBAL_TIMER_DELAY);
}
while(CTimer::m_hMutex && !CTimer::m_bTerminate);
CTimer::m_bTerminate = false;
return 0;
}
m_ParentThreadId - хедер основного потока
В основном потоке при загрузке компоненты делает так
hTimerHook = ::SetWindowsHookEx(WH_GETMESSAGE, TimerHook, NULL, ::GetCurrentThreadId());
Дальше реализуем процедуру перехвата
LRESULT CALLBACK TimerHook(int code, WPARAM wp, LPARAM lp)
{
MSG* wpstr = (MSG*)lp;
UINT uMsg = wpstr->message;
if(uMsg == WM_VXPTIMER)
{
// Обработчик таймера
}
return ::CallNextHookEx(hMenuHook, code, wp, lp);
}
В моем случае, обработчик таймера перебирает ссылки на экзепляры класса RToolTipsManager и для каждого вызывает метод OnTimer.
Решение, на мой взгляд, не очень красивое, потому что идет вразрез с общей идеологией MFC, обработкой очереди сообщений и пр. Но работает. Другого способа я не нашел.