windows程序设计——计时器

那年仲夏 提交于 2019-11-27 18:40:07

可能不是很直观,但计时器确实算的上一个输入设备。当设置了一个定时器是,系统设置一个计时数,由windows系统接收到硬件的tick信号将计时数减去一定值,当减少到0时,系统在程序的消息队列中加入一条WM_TIMER消息。因此timer消息是个同步消息,与鼠标与键盘的输入一样通过getmesssage获取到消息之后在dispatch到对应的窗口中。定时器还是一种系统资源,若不再需要需要释放。故一下两个API成对使用,调用KillTimer时会清除掉消息队列里边的所有对应的WM_TIMER消息。

//设置定时器
UINT SetTimer(
    HWND hWnd ,   //目标窗口句柄,或者lpTimerFunc的参数
    UINT nIDEvent, //定时器的ID,自己定义,当为0时不指定id,由系统返回一个id,通过id管理(kill)定时器
    UINT uElapse,  //定时时间
    TIMERPROC lpTimerFunc //回调处理函数
    );
//释放定时器
BOOL KillTimer(
    HWND hWnd,   //目标窗口句柄
    UINT uIDEvent //定时器的ID,自己定义
    );
使用定时器通常要么通过窗口的消息处理函数处理定时器消息(方法一),要么通过设置的回调函数处理(方法二、方法三)。

方法一:

/*-----------------------------------------
   BEEPER1.C  -- Timer Demo Program No. 1
                 (c) Charles Petzold, 1998
  -----------------------------------------*/

#include <windows.h>

//用宏定义定时器id
#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") ;
     HWND         hwnd ;
     MSG          msg ;
     WNDCLASS     wndclass ;
     
     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = szAppName ;
     
     if (!RegisterClass (&wndclass))
     {
          MessageBox (NULL, TEXT ("Program requires Windows NT!"), 
                      szAppName, MB_ICONERROR) ;
          return 0 ;
     }
     
     hwnd = CreateWindow (szAppName, TEXT ("Beeper1 Timer Demo"),
                          WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          NULL, NULL, hInstance, NULL) ;
          
     ShowWindow (hwnd, iCmdShow) ;
     UpdateWindow (hwnd) ;
          
     while (GetMessage (&msg, NULL, 0, 0))
     {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }
     return msg.wParam ;
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     static BOOL fFlipFlop = FALSE ;
     HBRUSH      hBrush ;
     HDC         hdc ;
     PAINTSTRUCT ps ;
     RECT        rc ;
     
     switch (message)
     {
     case WM_CREATE: //窗口建立时创建一个定时器
          SetTimer (hwnd, ID_TIMER, 1000, NULL) ;
          return 0 ;

     case WM_TIMER : //收到定时器消息
          MessageBeep (-1) ; //发声          
          fFlipFlop = !fFlipFlop ; //置反
          InvalidateRect (hwnd, NULL, FALSE) ; //刷新界面
          return 0 ;
          
     case WM_PAINT : //根据fFlipFlop来选择用蓝色或者红色填充客户区
          hdc = BeginPaint (hwnd, &ps) ;
          
          GetClientRect (hwnd, &rc) ;
          hBrush = CreateSolidBrush (fFlipFlop ? RGB(255,0,0) : RGB(0,0,255)) ;
          FillRect (hdc, &rc, 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) ;
}
方法二:

/*----------------------------------------
   BEEPER2.C -- Timer Demo Program No. 2
                (c) Charles Petzold, 1998
  ----------------------------------------*/

#include <windows.h>
//用宏定义定时器id
#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") ;
     HWND         hwnd ;
     MSG          msg ;
     WNDCLASS     wndclass ;
     
     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = szAppName ;
     
     if (!RegisterClass (&wndclass))
     {
          MessageBox (NULL, TEXT ("Program requires Windows NT!"), 
                      szAppName, MB_ICONERROR) ;
          return 0 ;
     }
     
     hwnd = CreateWindow (szAppName, TEXT ("Beeper2 Timer Demo"),
                          WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          NULL, NULL, hInstance, NULL) ;
     
     ShowWindow (hwnd, iCmdShow) ;
     UpdateWindow (hwnd) ;
          
     while (GetMessage (&msg, NULL, 0, 0))
     {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }
     return msg.wParam ;
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     switch (message)
     {
     case WM_CREATE: //窗口建立的时候也建立定时器,并设置处理函数
          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) ;
}

//hwnd为settimer时的hwnd message总是为WM_TIMER,iTimerID为定时器id,dwTime为GetTickCount值
VOID CALLBACK TimerProc (HWND hwnd, UINT message, UINT iTimerID, DWORD dwTime)
{
     static BOOL fFlipFlop = FALSE ;
     HBRUSH      hBrush ;
     HDC         hdc ;
     RECT        rc ;
     //发声
     MessageBeep (-1) ;
	 //取反
     fFlipFlop = !fFlipFlop ;
     //获取客户区
     GetClientRect (hwnd, &rc) ;
     //根据fFlipFlop分别在客户区中填入红色和蓝色
     hdc = GetDC (hwnd) ;
     hBrush = CreateSolidBrush (fFlipFlop ? RGB(255,0,0) : RGB(0,0,255)) ;
     
     FillRect (hdc, &rc, hBrush) ;
     ReleaseDC (hwnd, hdc) ;
     DeleteObject (hBrush) ;
}




易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!