首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

多媒體定時器實戰:C++ Builder 高精度週期性回調範例

     編輯:VC 教學

為什麼需要多媒體定時器?

標準 TTimer 依賴 Windows 訊息隊列(WM_TIMER),精度約 10~15ms,且在 UI 忙碌時會丟失/延遲。timeSetEvent (winmm.lib) 由系統專用執行緒在內核級觸發回調,**精度可達 1ms**,適合音訊播放、數據採集、遊戲迴路等硬實時場景。

完整最小化範例

頭文件 (Unit1.h)

#ifndef Unit1H
#define Unit1H
#include 
#include 
#include 
#include 
#include  // 關鍵頭文件

class TForm1 : public TForm {
__published:
    TButton *BtnStart;
    TLabel *LblTime;
    void __fastcall BtnStartClick(TObject *Sender);
    void __fastcall FormCloseQuery(TObject *Sender, bool &CanClose);
private:
    static void CALLBACK TimerProc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2);
    UINT TimerID;
public:
    __fastcall TForm1(TComponent* Owner);
};
extern PACKAGE TForm1 *Form1;
#endif

實現文件 (Unit1.cpp)

#include 
#pragma hdrstop
#include "Unit1.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;

__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) {
    TimerID = 0;
}

void CALLBACK TForm1::TimerProc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) {
    // 注意:此回調運行在系統定時器執行緒,**不可直接操作 VCL 控件**
    // 必須用 PostMessage / Synchronize / TThread::Queue 轉發到主執行緒
    PostMessage(Form1->Handle, WM_USER + 1, 0, 0); // 自定義訊息通知主執行緒更新 UI
}

void __fastcall TForm1::BtnStartClick(TObject *Sender) {
    // 週期 1000ms,回調函數,用戶數據 0,週期性+函數回調模式
    TimerID = timeSetEvent(1000, 0, (LPTIMECALLBACK)TimerProc, 0,
                           TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
    if (TimerID == 0) ShowMessage("創建失敗,請檢查 winmm.lib 是否鏈接");
}

void __fastcall TForm1::FormCloseQuery(TObject *Sender, bool &CanClose) {
    if (TimerID != 0) {
        timeKillEvent(TimerID); // 必須釋放,否則資源洩漏
        TimerID = 0;
    }
}

// 在表單類中添加訊息處理更新 UI
BEGIN_MESSAGE_MAP
    MESSAGE_HANDLER(WM_USER + 1, TMessage, OnTimerUpdate)
END_MESSAGE_MAP(TForm)

void __fastcall TForm1::OnTimerUpdate(TMessage &Msg) {
    LblTime->Caption = TimeToStr(Now()); // 安全更新 UI
}

專案設置關鍵點

  • **鏈接 winmm.lib**:Project → Options → Linker → "Additional library path" 加入 $(BDSLIB)\win32\release 或直接在代碼 #pragma comment(lib, "winmm.lib")。
  • **包含 mmsystem.h**:#include 。
  • **回調約定**:必須聲明為 CALLBACK (即 __stdcall),參數固定 5 個 DWORD。

進階用法與避坑

需求實現方式
亞毫秒精度 (1ms)timeBeginPeriod(1) 提升系統定時器分辨率,結束時 timeEndPeriod(1)
單次觸發flags = TIME_ONESHOT | TIME_CALLBACK_FUNCTION
回調傳遞上下文dwUser 傳 this 指針,回調中 static_cast(dwUser)->... (需確保對象存活)
高頻回調中做耗時運算**嚴禁**!回調必須極快返回,耗時任務 PostMessage 到工作執行緒/佇列
多媒體定時器 vs Waitable Timer後者 (CreateWaitableTimer) 精度更高、可關聯 I/O 完成埠,適合更復雜同步場景

總結

timeSetEvent + PostMessage 組合是 BCB/VCL 中實現高精度週期性任務的標準模式:定時器執行緒只負責「打招呼」,主執行緒負責「幹活」,既保證精度又保證 VCL 線程安全。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved