SetTimer(NULL,NULL,UINT,NULL)
Posted
技术标签:
【中文标题】SetTimer(NULL,NULL,UINT,NULL)【英文标题】:SetTimer(NULL, NULL, UINT, NULL) 【发布时间】:2021-08-25 13:48:36 【问题描述】:我正在审查具有以下代码行的 MFC 应用程序:
SetTimer(NULL, NULL, 50, NULL);
来自 WinAPI 文档:
UINT_PTR SetTimer(
HWND hWnd,
UINT_PTR nIDEvent,
UINT uElapse,
TIMERPROC lpTimerFunc
);
参数
hWnd
类型:HWND
要与计时器关联的窗口句柄。这个窗口 必须由调用线程拥有。如果 hWnd 的 NULL 值为 与现有计时器的 nIDEvent 一起传入,该计时器将 以与现有非 NULL hWnd 计时器相同的方式替换 是。
nIDEvent
类型:UINT_PTR
一个非零的计时器标识符。如果 hWnd 参数为 NULL,并且 nIDEvent 与现有计时器不匹配,然后将其忽略并新建一个 生成定时器 ID。如果 hWnd 参数不为 NULL 并且 hWnd 指定的窗口已经有一个值为 nIDEvent 的计时器, 然后现有的计时器被新的计时器替换。当设置定时器 替换定时器,定时器被重置。因此,将出现一条消息 在当前超时值过去后发送,但之前设置的 超时值被忽略。 如果调用不打算替换 现有计时器,如果 hWnd 为 NULL,则 nIDEvent 应为 0。
我相信这行代码是为了创建一个50ms的计时器(不是替换一些现有的计时器),但是我不明白hWnd参数为NULL的效果。
当我使用 NULL 的 hWnd 参数和 NULL 的 nIDEvent 参数调用 SetTimer 时,文档并没有向我说明会发生什么。
问题:
hWnd == NULL 在 SetTimer 中有什么作用?
nIDEvent == NULL 是否总是暗示我要创建一个新计时器(调用将返回其 ID),而不是“替换”现有计时器?
我们是否应该从 SetTimer 捕获返回值,并在我们退出该线程时拥有相应的KillTimer(return_value)
?
【问题讨论】:
if the nIDEvent does not match an existing timer then it is ignored and a new timer ID is generated
有什么不清楚的地方?
ID 传递NULL
实际上是错误的;它是一个整数,而不是一个指针。 UINT_PTR
是一个整数,其宽度足以存储一个指针。
@Alan Birtles - 文件的那一部分很清楚。当两个参数都为 NULL 时,不清楚(无论如何对我来说)的意图是什么。
Amolbdnilo - 虽然在代码中使用 NULL 可能会混淆意图,但在代码的上下文中,NULL 是一个 #define,它正在将文本替换为 0。作为审查此代码的一部分我将其更改为 0。(这是非常旧的代码)
我真的不确定任何人可以添加到您引用的文档中以使该功能的操作更清晰。我想我们只会引用那个文件。
【参考方案1】:
hWnd == NULL 在 SetTimer 中有什么作用?
当hWnd
为NULL
时,计时器不与窗口关联。将其视为线程或应用程序中的全局独立计时器。
nIDEvent == NULL 是否总是暗示我要创建一个新的计时器 (其 ID 将通过调用返回),而不是“替换”现有的 计时器?
是的。请看这一行:
如果调用不打算替换现有计时器,nIDEvent 如果 hWnd 为 NULL,则应为 0。
我们是否应该从 SetTimer 捕获返回值,并在我们退出该线程时有一个对应的 KillTimer(return_value)?
是的。请看这部分:
如果函数成功并且hWnd参数为NULL,则返回 value 是标识新计时器的整数。一个应用程序可以通过 将此值传递给 KillTimer 函数以销毁计时器。
正确的代码是:
UINT_PTR timerId = SetTimer(NULL, 0, 50, NULL);
// some code
KillTimer(NULL, timerId);
【讨论】:
您几乎肯定不想在“一些代码”之后立即终止计时器,直到您返回事件循环,它才有机会触发。将该计时器 ID 保存在您以后可以检索的地方。 @mar 代码说明了如何正确使用 API。它并不意味着有意义或有用。 @IInspectable 太多人从字面上理解。我不希望 OP 的下一个问题是“为什么我的计时器没有触发?” @mar 不清楚你为什么不想要这个问题。如果它构图得当、研究得当、写得好,那真的没有错。这个问题是关于 API 的语义的,无论代码是否做了有意义的事情,这个答案中的代码都很好地解释了它们。 @IInspectable 哦,我不介意另一个问题,我只是认为这是一个不应该被掩盖的重要点。我们不希望我们的建议扼杀完美的工作代码。以上是关于SetTimer(NULL,NULL,UINT,NULL)的主要内容,如果未能解决你的问题,请参考以下文章
将 SetTimer() 和 KillTimer() 移植到 C#?