计时器(1)之3种方法

来源:互联网 发布:首创证券软件下载 编辑:程序博客网 时间:2024/04/29 09:07

你可以使用SetTimer函数为自己的Windows程序分配一个计时器,SetTimer包含一个无符号的整形参数,该参数指定了时间间隔的长短,单位是毫秒。

该函数的功能是在指定时间间隔内向你的程序发送一条WM_TIMER消息;

计时器消息不是异步的。

因为计时器是基于硬件计时器的中断,程序员有时候会被误导,认为他们的程序可能会被异步中断打断后被迫去处理wm_timer消息,事实上,Windows处理WM_TIMER消息和处理WM_PAINT消息很类似,这两种消息都是低优先级的,只有当消息队列中没有其他消息时,程序才会收到它们。

 

使用计时器的三种方法:

方法一:

#define TIMER_SEC 1#define TIMER_MIN 2//通过两个SetTimer函数分别设置两个计时器SetTimer(hwnd,TIMER_SEC,1000,NULL);SetTimer(hwnd,TIMER_MIN,60000,NULL);//WM_TIMER的处理逻辑如下:case WM_TIMER:       switch(wParam)        {              case TIMER_SEC:                  每秒处理一次;                  break;;              case TIMER_MIN:                  每分钟处理一次            break;;        }return 0;


 

下面看看一个简单的例子,在一秒时间间隔内,改变客户区的背景颜色,发出系统声音。

#include<windows.h>#define ID_TIMER 1LRESULT CALLBACK WindowProc(  HWND hwnd,      // handle to window  UINT uMsg,      // message identifier  WPARAM wParam,  // first message parameter  LPARAM lParam   // second message parameter);int WINAPI WinMain(  HINSTANCE hInstance,      // handle to current instance  HINSTANCE hPrevInstance,  // handle to previous instance  LPSTR lpCmdLine,          // command line  int nCmdShow              // show state){static TCHAR szAppName[]=TEXT("leidemingzi");HWND hwnd;MSG msg;WNDCLASS wndclass;wndclass.cbClsExtra=0;wndclass.cbWndExtra=0;wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);wndclass.hIcon=LoadIcon(NULL,IDI_ERROR);wndclass.hInstance=hInstance;wndclass.lpfnWndProc=WindowProc;wndclass.lpszClassName=szAppName;wndclass.lpszMenuName=NULL;wndclass.style=CS_HREDRAW|CS_VREDRAW;if(!RegisterClass(&wndclass)){MessageBox(NULL,TEXT("the program require window nt!"),TEXT("xiao tips"),MB_ICONERROR);return 0;}hwnd=CreateWindow(  szAppName,  // registered class name  TEXT("this is title"), // window name  WS_OVERLAPPEDWINDOW,        // window style  CW_USEDEFAULT,                // horizontal position of window  CW_USEDEFAULT,                // vertical position of window  CW_USEDEFAULT,           // window width  CW_USEDEFAULT,          // window height  NULL,      // handle to parent or owner window  NULL,          // menu handle or child identifier  hInstance,  // handle to application instance  NULL        // window-creation data);ShowWindow(hwnd,nCmdShow);UpdateWindow(hwnd);while(GetMessage(&msg,NULL,0,0)){TranslateMessage(&msg);DispatchMessage(&msg);}return msg.wParam;}LRESULT CALLBACK WindowProc(  HWND hwnd,      // handle to window  UINT uMsg,      // message identifier  WPARAM wParam,  // first message parameter  LPARAM lParam   // second message parameter){static BOOL fFlipFlop=FALSE;HBRUSH hbrush;HDC hdc;PAINTSTRUCT ps;RECT rect;switch(uMsg){case WM_CREATE:SetTimer(hwnd,ID_TIMER,1000,NULL);//设置一个计时器,时间间隔为1秒return 0;case WM_TIMER:MessageBeep(MB_ICONASTERISK);//发出系统声音fFlipFlop=!fFlipFlop;//取反InvalidateRect(hwnd,NULL,FALSE);//触发WM_PAINT事件return 0;case WM_PAINT:hdc=BeginPaint(hwnd,&ps);GetClientRect(hwnd,&rect);//获取客户区大小hbrush=CreateSolidBrush(fFlipFlop?RGB(255,0,0):RGB(0,0,255));//判断填充红色还是蓝色FillRect(hdc,&rect,hbrush);EndPaint(hwnd,&ps);DeleteObject(hbrush);//删除画刷return 0;case WM_DESTROY:KillTimer(hwnd,ID_TIMER);//把Timer删掉PostQuitMessage(0);return 0;}return DefWindowProc(hwnd,uMsg,wParam,lParam);}


程序虽小,“五脏”俱全。

 

方法二:

让你只会Windows把计时器消息发送到程序中的另一个函数

收到计时器消息的函数被称为“回调”函数,这是程序中被Windows调用的函数,你告诉Windows这个函数的地址,Windows以后就会调用这个函数。

SetTimer不是以为使用回调功能的Windows函数,CreateDialog,DialogBox都会使用回调函数处理对话框的消息,有几个Windows函数(EnumChildWindow,EnumFont,EnumObject,EnumProps,EnumWindow)会传递枚举信息到回调函数,还有几个不常用的函数GrayString,LineDDA,SetWindowHookEx也要求使用回调函数功能。

//我们给回调函数起名为TimerProc,(你可以取其他名字,函数名不重叠就行)VOID CALLBACK TimerProc(HWND hwnd,UNIT uMsg,UINT iTimerID,DWORD dwTime){     处理TIMER消息}


 

下面看看第二种方法和第一种方法的对比,功能完全一样

#include<windows.h>#define ID_TIMER 1LRESULT CALLBACK WindowProc(  HWND hwnd,      // handle to window  UINT uMsg,      // message identifier  WPARAM wParam,  // first message parameter  LPARAM lParam   // second message parameter);VOID CALLBACK TimerProc(  HWND hwnd,      // handle to window  UINT uMsg,      // message identifier  UINT iTimerID , // first message parameter  DWORD dwTime   // second message parameter);int WINAPI WinMain(  HINSTANCE hInstance,      // handle to current instance  HINSTANCE hPrevInstance,  // handle to previous instance  LPSTR lpCmdLine,          // command line  int nCmdShow              // show state){static TCHAR szAppName[]=TEXT("leidemingzi");HWND hwnd;MSG msg;WNDCLASS wndclass;wndclass.cbClsExtra=0;wndclass.cbWndExtra=0;wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);wndclass.hIcon=LoadIcon(NULL,IDI_ERROR);wndclass.hInstance=hInstance;wndclass.lpfnWndProc=WindowProc;wndclass.lpszClassName=szAppName;wndclass.lpszMenuName=NULL;wndclass.style=CS_HREDRAW|CS_VREDRAW;if(!RegisterClass(&wndclass)){MessageBox(NULL,TEXT("the program require window nt!"),TEXT("xiao tips"),MB_ICONERROR);return 0;}hwnd=CreateWindow(  szAppName,  // registered class name  TEXT("this is title"), // window name  WS_OVERLAPPEDWINDOW,        // window style  CW_USEDEFAULT,                // horizontal position of window  CW_USEDEFAULT,                // vertical position of window  CW_USEDEFAULT,           // window width  CW_USEDEFAULT,          // window height  NULL,      // handle to parent or owner window  NULL,          // menu handle or child identifier  hInstance,  // handle to application instance  NULL        // window-creation data);ShowWindow(hwnd,nCmdShow);UpdateWindow(hwnd);while(GetMessage(&msg,NULL,0,0)){TranslateMessage(&msg);DispatchMessage(&msg);}return msg.wParam;}LRESULT CALLBACK WindowProc(  HWND hwnd,      // handle to window  UINT uMsg,      // message identifier  WPARAM wParam,  // first message parameter  LPARAM lParam   // second message parameter){switch(uMsg){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,uMsg,wParam,lParam);}VOID CALLBACK TimerProc(  HWND hwnd,      // handle to window  UINT uMsg,      // message identifier  UINT iTimerID,  // first message parameter  DWORD dwTime   // second message parameter){static BOOL fFlipFlop=FALSE;HBRUSH hbrush;HDC hdc;RECT rect;MessageBeep(MB_ICONASTERISK);fFlipFlop=!fFlipFlop;GetClientRect(hwnd,&rect);hdc=GetDC(hwnd);hbrush=CreateSolidBrush(fFlipFlop?RGB(255,0,0):RGB(0,0,255));FillRect(hdc,&rect,hbrush);ReleaseDC(hwnd,hdc);DeleteObject(hbrush);}



方法三:

第三种设置计时器的方法和第二种方法相似,只不过SetTimer的hwnd参数被设置成为NULL,而且第二个方法被忽略了,此外这个函数会返回计时器的ID

itimerId=SetTimer(NULL,0,wMsecInterval,TimerProc);KillTimer(NULL,iTimerID);


这种计时器比较少用,如果在程序中,需要不同的时候调用很多次SetTimer,但又不想记录哪些计时器ID已经被使用过,那么这种方法可能会派上用场

在此,不举例子了。

(关注计时器(X),有更精彩的例子)

 

 

原创粉丝点击