如何在不使用WM_TIMER时向SetTimer的Timer Proc传递自定义数据?
不用WM_TIMER也能给定时器回调传自定义数据的方法
当然不是只能用WM_TIMER的方式,有两种靠谱的方案可以实现你的需求:
方案1:把自定义数据指针转成Timer ID传递
SetTimer的第二个参数nIDEvent类型是UINT_PTR,这个类型的长度和系统指针宽度一致(32位系统4字节,64位系统8字节),所以可以把自定义数据的指针强制转换成UINT_PTR当作定时器ID传入,在回调函数里再转回来使用。
举个代码例子:
// 定义自定义数据结构体 typedef struct { const char* customStr; int numData; } TimerCustomData; // 分配自定义数据(用堆分配,确保生命周期覆盖定时器) TimerCustomData* data = malloc(sizeof(TimerCustomData)); data->customStr = "我的自定义字符串"; data->numData = 12345; // 把数据指针转成UINT_PTR作为Timer ID SetTimer(NULL, (UINT_PTR)data, 1000, App_TimerProc); // 定时器回调函数 VOID CALLBACK App_TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) { // 把ID转回自定义数据指针 TimerCustomData* customData = (TimerCustomData*)idEvent; // 使用自定义数据 printf("自定义字符串:%s,数字:%d\n", customData->customStr, customData->numData); // 如果定时器只触发一次,记得销毁定时器并释放内存 KillTimer(NULL, idEvent); free(customData); }
注意事项:
- 必须用堆分配(
malloc/new)或者全局/静态变量存储自定义数据,不能用局部变量的指针——局部变量会在函数退出后销毁,导致回调里访问野指针。 - 销毁定时器时要同步释放对应的自定义数据,避免内存泄漏。
方案2:使用Timer Queue Timer(更推荐)
Windows提供的CreateTimerQueueTimer API天生支持传递自定义参数给回调,不需要绕弯子,而且功能更强大(支持一次性/周期性定时器、可以取消定时器等),完全不需要依赖窗口。
代码示例:
// 自定义数据结构体 typedef struct { const char* customStr; int numData; } TimerCustomData; // 定时器回调函数(注意参数和SetTimer的回调不同) VOID CALLBACK App_TimerQueueProc(PVOID lpParameter, BOOLEAN TimerOrWaitFired) { // 直接获取自定义数据 TimerCustomData* customData = (TimerCustomData*)lpParameter; printf("自定义字符串:%s,数字:%d\n", customData->customStr, customData->numData); // 释放数据(如果是堆分配的话) free(customData); } // 创建定时器队列定时器 void CreateMyTimer() { TimerCustomData* data = malloc(sizeof(TimerCustomData)); data->customStr = "我的自定义字符串"; data->numData = 12345; HANDLE hTimer = NULL; CreateTimerQueueTimer(&hTimer, NULL, App_TimerQueueProc, data, 0/* 首次触发延迟 */, 1000/* 间隔 */, 0); }
这个方案不需要纠结ID的问题,直接把自定义数据指针传给CreateTimerQueueTimer的第4个参数,回调里直接取用即可,逻辑更清晰。
内容的提问来源于stack exchange,提问作者gene b.
相关产品推荐
相关产品推荐

