当前位置:C++技术网 > 精选软件 > 计时器使用的一个坑,忽视后容易中招

计时器使用的一个坑,忽视后容易中招

更新时间:2016-06-03 19:04:55浏览次数:1+次

    在MFC环境下,如果直接调用SetTimer函数,默认的就是CWnd窗口的计时器。计时器和窗口相关,尽管两个计时器ID相同,但是如果不是同一个窗口的,是没有相关性的。
    我们先看看SetTimer函数的原型声明:
UINT_PTR SetTimer(HWND hWnd,UINT_PTR nIDEvent,UINT uElapse,TIMERPROC lpTimerFunc);
    可以看到,SetTimer函数的第一个参数就是窗口句柄,也就表示,计时器是与窗口相关的。实际上,计时器会产生WM_TIMER消息,发送到窗口的消息队列中的。
    我们在MFC开发环境下,直接输入SetTimer函数,我们实际上写的是CWnd类的成员函数SetTimer,而不是API函数SetTimer,这也就表示,我们写的SetTimer设置的计时器关联的是CWnd窗口相关的窗口。所以,如果我们要设定特定的窗口的计时器,就需要用那个窗口的类如CmyWnd(继承于CWnd)来调用SetTimer,这样这个类会用关联的窗口句柄去调用API函数SetTimer,这样就设置了CmyWnd关联的窗口的计时器。你也可以直接调用调用API函数SetTimer,然后直接传入窗口的句柄。
    你千万别想着用不同的计时器ID来区分不同的窗口的多个计时器,因为计时器是窗口相关的。两个窗口可以拥有相同ID的计时器。
    这个技术点,其实在专门去说计时器的时候,似乎不值得一提,但是当我们忽略后,容易引发一些很难找到的Bug。今天我就碰到了,然后一步步跟踪,发现SetTimer调用成功,我也是用对应的ID去调用的。谁知MFC环境下默认的是CWnd窗口类的SetTimer,这样自然就无法设置成功。如果要在MFC中直接调用API版的SetTimer,请在SetTimer前加上::,代码如下所示:
::SetTimer(hwnd,1,1000,NULL);
    我要设置的是主窗口的计时器,而写代码的位置是一个非窗口类。所以我要先获取主窗口类指针,然后调用成员函数SetTiemr,然后指定ID,就可以设置这个窗口对应的ID的计时器了。代码如下:
AfxGetMainWnd()->SetTimer(1025,1000,CMyDlg::Timer1);
    使用AfxGetMainWnd()获取主窗口的类指针,然后设置计时器。最后一个参数是主窗口类的一个计时器函数,这里添加了主窗口类的类作用域符号::,这样就可以直接将主窗口类的计时器函数设置上。如果不加::的话,所指的函数就是本类或者全局静态函数了。
    说了这么多,主要就是说明计时器与窗口相关,不能仅靠计时器ID分辨,在窗口句柄确定后,然后再通过计时器ID来区分同一个窗口的多个计时器。同时,在MFC环境下,SetTimer默认是CWnd的成员函数,而不是API函数,API函数要写成::SetTimer(...)。API函数第一个参数要指定窗口句柄。
    以上就是今天遇见的一个坑,总结一下,防止再犯,也分享给大家,一起防雷。