计时器(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),有更精彩的例子)
- 计时器(1)之3种方法
- VS之实现计时器的几种方法
- 计时器的两种方法
- 《Windows程序设计》之计时器1
- Cocos2dx 3.1.1 之 计时器
- Unity3D开发学习之路--两种在Unity3D中创建倒计时器的方法
- Android计时器的三种实现方法
- IOS添加计时器的两种方法
- 8.2 使用计时器的三种方法
- 8.2 使用计时器的三种方法
- C#计时器的三种实现方法
- android之计时器(Chronometer)的使用以及常用的方法
- android之计时器(Chronometer)的使用以及常用的方法
- 实现一个方法计时器
- Javascript技巧之计时器和倒计时器
- Javascript案例之计时器和倒计时器
- Windows编程之计时器
- Windows程序设计之计时器
- 三分法(Ternary Search)求解凸(凹)函数的极值问题<题目篇>
- SQL时间函数
- Android UI设计中的三种特效
- 四川车牌知识
- vector.resize 与 vector.reserve的区别
- 计时器(1)之3种方法
- webservice学习之AXIS初学笔记--环境配置
- 多库俄罗斯方块之十(Qt)
- 横看成领侧成峰——代码调试
- 如何成为一个编程高手
- 用点阵显示一个爱心
- VIM查找操作
- 用javascript正则表达式验证网址格式是否正确
- 解决Ubuntu11.10 TXT文档中文乱码的问题