《Windows API每日一练》7.2 计时器的三种使用方法

如果程序在整个运行过程中需要一个计时器,在WinMain函数中或窗口过程处理WM_CREATE 消息时,调用SetTimer函数创建一个计时器。在离开WinMain函数时或是处理WM_DESTROY消息时,调用KillTimer函数销毁计时器。基于调用SetTimer参数的不同,可采取三种不同的方法使用计时器。

本节必须掌握的知识点:

        第43练:使用计时器方法一

        第44练:使用计时器方法二

        使用计时器方法三

7.2.1 第43练:使用计时器方法一

/*------------------------------------------------------------------

043  WIN32 API 每日一练

     第43个例子BEEPER1.C:使用计时器方法一

     WM_TIMER消息

     SetTimer函数:WM_CREATE时创建计时器

     KillTimer函数:WM_DESTORY时销毁

(c) www.bcdaren.com, 2020

----------------------------------------------------------------*/

#include <windows.h>

#define ID_TIMER 1

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,

 PSTR szCmdLine, int iCmdShow)

{

     static TCHAR szAppName[] = TEXT("Beeper1");

    (略)

     return msg.wParam;

}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam)

{

     static BOOL fFlipFlop = FALSE;//标记值

     HBRUSH hBrush;

     PAINTSTRUCT ps;

     RECT rect;

     HDC hdc;

     switch (message)

     {

     case WM_CREATE:

          //创建计时器,间隔1秒发送一次WM_TIMER

          SetTimer(hwnd,ID_TIMER,1000,NULL);

          return 0;

     case WM_TIMER:

          MessageBeep(-1);//响铃

          fFlipFlop = !fFlipFlop;//标记值取反

          InvalidateRect(hwnd,NULL,FALSE);//重绘窗口

          return 0;

     case WM_PAINT:

          hdc = BeginPaint(hwnd,&ps);

          //选择画刷

          hBrush = CreateSolidBrush(fFlipFlop ? RGB(0,0,255) : RGB(255,0,0));

          GetClientRect(hwnd,&rect);

          //绘制并填充矩形

          FillRect(hdc,&rect,hBrush);

          EndPaint(hwnd,&ps);

          DeleteObject(hBrush);

          return 0;

     case WM_DESTROY:

          //销毁计时器

          KillTimer(hwnd,ID_TIMER);

          PostQuitMessage(0);

          return 0;

     }

     return DefWindowProc(hwnd,message,wParam,lParam);

}

/******************************************************************************

WM_TIMER消息:计时器到期时,将其发布到安装线程的消息队列中

wParam [输入]计时器标识符。

lParam [输入]指向应用程序定义的回调函数的指针,该指针在安装计时器时传递给SetTimer函数。

*******************************************************************************

SetTimer函数:用指定的超时值创建一个计时器

UINT_PTR SetTimer(

  HWND      hWnd,   //与计时器关联的窗口的句柄

  UINT_PTR  nIDEvent,//非零计时器标识符

  UINT      uElapse,//超时值--间隔时间,以毫秒为单位。

  TIMERPROC lpTimerFunc//当超时值过去时,指向要通知的回调函数指针

);

*******************************************************************************

KillTimer函数:销毁指定的计时器

BOOL KillTimer(

  HWND     hWnd,

  UINT_PTR uIDEvent//计时器ID

);

*/

       运行结果:

图7-1 使用计时器方法一

 

总结

  1. 实例BEEPER1.C的实现非常简单。首先窗口过程在处理WM_CREATE消息时,调用SetTimer函数创建了一个计时器:

SetTimer(hwnd,ID_TIMER,1000,NULL);

参数ID_TIMER为计时器ID。参数1000以毫秒为单位,1000毫秒等于1秒,即每间隔1秒向窗口消息队列发送一次WM_TIMER消息。最后一个参数为计时器回调函数,NULL表示未设置回调函数。这是使用计时器方法一的典型特征,通过处理WM_TIMER消息响应计时器,而不是使用计时器回调函数。

       2.接着处理WM_TIMER消息时,响铃的同时,将标志值fFlipFlop取反,然后调用InvalidateRect函数重绘窗口客户区。

       3.处理WM_PAINT消息时,创建一个蓝红不断切换的画刷(每接收到一次WM_TIMER消息切换一次,即大约每秒切换一次),填充矩形。

       4.处理WM_DESTROY消息时,调用KillTimer函数销毁计时器:

KillTimer(hwnd,ID_TIMER);

7.2.2 第44练:使用计时器方法二

/*------------------------------------------------------------------

044.C -- A daily practice

     第44个例子BEEPER2.C:使用计时器方法二

     CALLBACK TimerProc 回调函数

(c) www.bcdaren.com, 2020

----------------------------------------------------------------*/

#include <windows.h>

#define ID_TIMER 1

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

void CALLBACK TimerProc (HWND, UINT, UINT, DWORD) ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,

 PSTR szCmdLine, int iCmdShow)

{

     static TCHAR szAppName[] = TEXT("Beeper2");

    (略)

     return msg.wParam;

}

//计时器回调函数

void CALLBACK TimerProc (HWND hwnd, UINT message, UINT iTimerID,DWORD dwTime)

{

     static BOOL fFlipFlop = FALSE;

     HBRUSH hBrush;

     RECT rect;

     HDC hdc;

     MessageBeep(-1);//响铃

     fFlipFlop = !fFlipFlop;//取反

     GetClientRect(hwnd, &rect);//获取客户区矩形参数

     hdc = GetDC(hwnd);

     //创建红色或蓝色画刷

     hBrush = CreateSolidBrush(fFlipFlop ? RGB(0, 0, 255) : RGB(255, 0, 0));

     FillRect(hdc, &rect, hBrush);//填充矩形框

     ReleaseDC(hwnd,hdc);//释放DC

     DeleteObject(hBrush);//删除画刷

}

//窗口过程

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam)

{

     switch (message)

     {

     case WM_CREATE:

          //创建计时器,TimerProc为计时器回调函数

          SetTimer(hwnd,ID_TIMER,1000,TimerProc);

          return 0;

     case WM_DESTROY:

          //销毁计时器

          KillTimer(hwnd,ID_TIMER);

          PostQuitMessage(0);

          return 0;

     }

     return DefWindowProc(hwnd,message,wParam,lParam);

}

/******************************************************************************

CALLBACK TimerProc 回调函数

函数定义

void CALLBACK TimerProc (HWND hwnd, UINT message, UINT iTimerID,DWORD dwTime)

hwnd参数:调用SetTimer时指定的窗口句柄。

UINT message参数:Windows只发送 WM_TIMER消息到TimeerProc,所以消息参数总是WM_TIMER。

UINT iTimerID参数:计时器的 ID。

DWORD dwTime:从GetTickCount函数返回的值,它记录了自从Windows启动到现在所逝去的毫秒数,最长为49.7天。

函数调用

SetTimer(hwnd,ID_TIMER,1000,TimerProc);//创建计时器

SetTimer函数的第四个参数必须设定为回调函数的地址

*/

       运行结果:

图7-2 使用计时器方法二

 

总结

计时器回调函数是在计时器事件发生时被调用的函数,用于执行特定的操作或触发相应的事件。

实例BEEPER2.C的窗口过程在处理WM_CREATE消息时,调用SetTimer函数创建计时器的前三个参数与实例BEEPER1.C完全相同,只是最后一个参数计时器的回调函数不再是NULL,而是TimerProc。

SetTimer(hwnd,ID_TIMER,1000,TimerProc);

与此相应,窗口过程不再需要处理WM_TIMER消息。窗口过程对WM_TIMER消息和WM_PAINT消息的处理放到了计时器回调函数TimerProc中,仅此而已。

7.2.3 使用计时器方法三

第三种设置计时器的方法与第二种方法相似,只不过SetTimer的hwnd参数被设置为 NULL,而且第二个参数(正常情况下是计时器的ID)也被忽略了。此外,这个函数会返回计时器的ID:

iTimerlD = SetTimer (NULL, 0, wMsecInterval, TimerProc);

如果SetTimer函数返回的iTimerlD为0,表示没有可用的计时器,这样的情况是极罕见的。

传给KillTimer的第一个参数(通常是窗口的句柄)也必须是NULL。计时器的ID必须是从SetTimer返回的值:

KillTimer (NULL, iTimerlD);

传给TimerProc计时器函数的hwnd参数也将是NULL。这种设置计时器的方法很少用 到。如果在程序中,需要在不同的时刻调用很多次SetTimer,但又不想记录哪些计时器ID 已经被使用过,那么这种方法可能会派上用场。

  • 17
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值