在QTimer源碼分析(以Windows下實現為例)
一文中,我們看到了Qt在windows下對計時器的使用:
- 對於間隔為零的情況,Qt並沒有動用系統的計時器
- 對於間隔非零的情況
- 間隔小於20ms 且系統支援多媒體計時器,則使用多媒體計時器
- 否則,使用普通計時器
Qt 的這種策略應該能很好地滿足我們的需求了,但qtcn上一個網友還是比較期待自己直接調用系統的多媒體計時器。既然這樣,自己還是嘗試寫寫吧,寫一個自己的Timer類
代碼
- 代碼還是比較簡單的,標頭檔 mmtimer.h 如下:
#ifndef MMTIMER_H#define MMTIMER_H#include <qt_windows.h>#include <QtCore/QObject>class MMTimer : public QObject{ Q_OBJECTpublic: explicit MMTimer(int interval, QObject *parent = 0); ~MMTimer();signals: void timeout();public slots: void start(); void stop();friend void WINAPI CALLBACK mmtimer_proc(uint, uint, DWORD_PTR, DWORD_PTR, DWORD_PTR);private: int m_interval; int m_id;};#endif // MMTIMER_H
#include "mmtimer.h"#include <MMSystem.h>#ifdef __MINGW32__ //w32api bug#define TIME_KILL_SYNCHRONOUS 0x0100#endifvoid WINAPI CALLBACK mmtimer_proc(uint timerId, uint, DWORD_PTR user, DWORD_PTR, DWORD_PTR){ MMTimer *t = reinterpret_cast<MMTimer*>(user); emit t->timeout();}MMTimer::MMTimer(int interval, QObject *parent) : QObject(parent),m_interval(interval),m_id(0){}MMTimer::~MMTimer(){ stop();}void MMTimer::start(){ m_id = timeSetEvent(m_interval, 1, mmtimer_proc, (DWORD_PTR)this, TIME_CALLBACK_FUNCTION | TIME_PERIODIC | TIME_KILL_SYNCHRONOUS);}void MMTimer::stop(){ if (m_id){ timeKillEvent(m_id); m_id = 0; }}
說明
上面的代碼應該不需要什麼解釋了:
- timeSetEvent 和 timeKillEvent 可直接查閱 MSDN
- 另外,MinGW的win32api包,對TIME_KILL_SYNCHRONOUS沒有定義,代碼中做了一點修正
請確保正確連結所需要的庫
LIBS += -lwinmm
注意:MSDN 對timeSetEvent的介紹中這麼說的(對此不做評論)
Note This function is obsolete. New applications should use CreateTimerQueueTimer to create a timer-queue timer.