<Win32_5>深入浅出Win32的计时器
说起时间,对于我们搞IT的人来说,那是要多重要有多重要。我觉得有价值的时间是给有抱负和有才能的人准备的,因为他们会充分利用,不会让时间失望……
呵呵,有点儿说远了,还是回归主题吧
Win32的计时器其实就是用以下两个函数控制的一个控件:
设置计时器
UINT_PTR SetTimer(
HWND hWnd,
UINT_PTR nIDEvent,
UINT uElapse,
TIMERPROC lpTimerFunc
);
关闭计时器
BOOL KillTimer( HWND hWnd,
UINT_PTR uIDEvent
);
函数KillTimer我不打算多说,只是对于多个计时器的时候,注意通过uIDEvent来关闭,不要关闭错误了
下面我讲一下个人认为比较重要的两点:
(1)实现计时器有两种主要的方式:
a)在窗口回调函数中响应WM_TIMER消息(SetTimer的第四个参数就应该设为NULL,表示不使用计时器回调函数)
b)自行写一个计时器回调函数,每一次就自动调用这个计时器回调函数(SetTimer的第四个参数就应该设为改函数的名称,TimerProc)
(2)如果是使用计时器回调函数,并用VC++6.0编译的,可能会遇到以下情况:
刚刚写计时器程序的时候,我就是按照API中给的TimerProc函数原型来调用:
#define ID_TIMER 1//计时器ID
SetTimer(hwnd, ID_TIMER, 1000, TimerProc);
VOID CALLBACK TimerProc(HWND, UINT, UINT_PTR, DWORD);
VOID CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
结果发现编译有错误:(我是用VC++6.0编译的)
error C2664: 'SetTimer' : cannot convert parameter 4 from 'void (struct HWND__ *,unsigned int,unsigned long,unsigned long)' to 'void (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,unsigned long)' , None of the functions with this name in scope match the target type
从给的提示上可以知道错误出现在类型转换上,unsigned long不能转换为unsigned int
其实就是SetTimer的第二个参数在作怪,我们先来看看这第二个参数是什么样的类型:
typedef unsigned long UINT_PTR
然而我自行定义的ID_TIMER就是一个int,但是从c语言类型规范来讲,int是可以转换成unsigned int或unsigned long的,在win32中都是32位,只是在这里VC++6.0不支持它们的转换。这个可以用一个简单的方法证明是编译器的问题:
就是如果你用vs2008来编译,没有点儿问题……
解决方法有两种:
a)一是上面讲的,用vs2008或是更高的版本来编译
b)二是依然用vc++6.0编译,但是需要将WndProc的第三个参数的类型改为UINT
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
以上就是个人觉得需要注意的地方,下面开始讲我今儿编的程序,就是利用计时器来绘制五彩缤纷的图形(我设定了三种:无边框的矩形、椭圆、圆角矩形)
算法还是比较简单,应该不需要多说,代码也有注释^_^:
//TimerDemo(定时器实例--随机大小的图形)
#include<windows.h>
#include<stdio.h>
//定义定时器ID
#define ID_TIMER 0
//图形种类
#define G_RECT 0
#define G_ELLIPSE 1
#define G_ROUNDRECT 2 //客户区大小
int cxClient, cyClient; //计数变量(控制每次绘制的图形)
int gCount = 0; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
VOID CALLBACK TimerProc(HWND, UINT, UINT_PTR, DWORD); //计时器回调函数(由于我现在改用vs2008了,所以就不需要将UINT_PTR改为UINT) int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
PSTR szCmdLine,
int iCmdShow)
{
static TCHAR szAppName[] = TEXT("RandomRect");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
int cxSystem, cySystem;//系统屏幕分辨率(也就是长宽) 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("This program requires Windows NT!"),
szAppName, MB_ICONERROR);
return 0;
} //获取屏幕大小
cxSystem = GetSystemMetrics(SM_CXSCREEN);
cySystem = GetSystemMetrics(SM_CYSCREEN);
hwnd = CreateWindow(szAppName,
TEXT("RandomRect Demo"),
WS_OVERLAPPEDWINDOW,
cxSystem / 4,//居中显示窗口
cySystem / 8,
cxSystem / 2,
cySystem * 3 / 4,
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, 100, TimerProc); //启动计时器
return 0 ; case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam); return 0; case WM_DESTROY:
KillTimer(hwnd, ID_TIMER);//别忘了关闭计时器
PostQuitMessage(0);
return 0;
} return DefWindowProc(hwnd, message, wParam, lParam);
} VOID CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
RECT rect;
HDC hdc;
HBRUSH hBrush; hdc = GetDC(hwnd); hBrush = CreateSolidBrush(RGB(rand()%255, rand()%255, rand()%255)); switch(gCount)
{
//无边框矩形
case G_RECT:
SetRect(&rect, rand()%cxClient, rand()%cyClient, rand()%cxClient, rand()%cyClient);
FillRect(hdc, &rect, hBrush);
break; //彩色椭圆
case G_ELLIPSE:
SelectObject(hdc, hBrush);
Ellipse(hdc, rand()%cxClient, rand()%cyClient, rand()%cxClient, rand()%cyClient);
break; //圆角矩形
case G_ROUNDRECT:
SelectObject(hdc, hBrush);
RoundRect(hdc, rand()%cxClient, rand()%cyClient, rand()%cxClient, rand()%cyClient, rand()%100, rand()%100);
break;
}
gCount = (gCount + 1) % 3;//继续计数,以控制下一次的图形绘制
DeleteObject(hBrush);
ReleaseDC(hwnd, hdc);
}
运行效果还是很漂亮的:
可以看见,无边矩形、椭圆、圆角矩形交错绘制,呵呵……
<Win32_5>深入浅出Win32的计时器的更多相关文章
- 深入浅出Win32多线程程序设计之基本概念
一.深入浅出Win32多线程程序设计之基本概念[转] 引言 从单进程单线程到多进程多线程是操作系统发展的一种必然趋势,当年的DOS系统属于单任务操作系统,最优秀的程序员也只能通过驻留内存的方式实现所谓 ...
- 深入浅出Win32多线程设计之MFC的多线程-线程与消息队列(经典)
1.创建和终止线程 在MFC程序中创建一个线程,宜调用AfxBeginThread函数.该函数因参数不同而具有两种重载版本,分别对应工作者线程和用户接口(UI)线程. 工作者线程 CWinThread ...
- Win32多线程编程(1) — 基础概念篇
内核对象的基本概念 Windows系统是非开源的,它提供给我们的接口是用户模式的,即User-Mode API.当我们调用某个API时,需要从用户模式切换到内核模式的I/O System Serv ...
- 多线程学习:win32多线程编程基本概念(转)
一.定义: 1.进程和线程的区别 进程:是程序的执行过程,具有动态性,即运行的程序就叫进程,不运行就叫程序 ,每个进程包含一到多个线程.线程:系统中的最小执行单元,同一进程中有多个线程,线程可以共享资 ...
- Linux下c开发 之 线程通信(转)
Linux下c开发 之 线程通信(转) 1.Linux“线程” 进程与线程之间是有区别的,不过Linux内核只提供了轻量进程的支持,未实现线程模型.Linux是一种“多进程单线程”的操作系统.Linu ...
- Linux下的C编程实战
Linux下的C编程实战(一) ――开发平台搭建 1.引言 Linux操作系统在服务器领域的应用和普及已经有较长的历史,这源于它的开源特点以及其超越Windows的安全性和稳定性.而近年来, Linu ...
- linux多线程编程(转)
原文地址:http://www.cnblogs.com/BiffoLee/archive/2011/11/18/2254540.html 1.Linux“线程” 进程与线程之间是有区别的,不过Linu ...
- 笔记整理--Linux多线程
Unix高级环境编程系列笔记 (2013/11/17 14:26:38) Unix高级环境编程系列笔记 出处信息 通过这篇文字,您将能够解答如下问题: 如何来标识一个线程? 如何创建一个新线程? 如何 ...
- Linux下的编程实战【转】
一篇比较不错的文章, 降到了 makefile make , gcc编译器,GDB调试器, Linux文件系统,Linux文件API,.C语言库函数(C库函数的文件操作实际上是独立于具体的操作系统平台 ...
随机推荐
- [Mugeda HTML5技术教程之5] 创建新作品
前一节,我们介绍了Mugeda Studio.这一节我们讲一下怎么通过Studio创建新作品.首先登陆网站,如果还没有登陆账号,你可以登录 www.mugeda.com 免费注册一个.登录网站后,点击 ...
- C程序设计语言练习题1-9
练习1-9 编写一个将输入复制到输出的程序,并将其中连续的多个空格用一个空格代替. 代码如下: #include <stdio.h> // 包含标准库的信息. int main() // ...
- RF学习过程中遇到的问题
1.写了一个打开浏览器的用例,执行用例时报需要对应的浏览器驱动,此时应下载对应的浏览器驱动,把该执行文件放到python的安装根目录下,再执行用例就成功了 2.日志不见的问题:需要杀进程
- [LeetCode 122] - 买入与卖出股票的最佳时机II(Best Time to Buy and Sell Stock II)
问题 假设你有一个数组,其中的第i个元素表示一只股票在第i天的价格. 设计一个算法找出最大的利润值.你可以进行任意多次的交易(即多次的卖出并买入一份股票).你不能在同一时间进行多次交易(即你必须在再次 ...
- 如何用VS2010打开VS2012编辑的项目
找到打开项目的开始图标:,右键点击,选择有文本编辑器打开,用下面的语句将文件里面的前两句替换掉.Microsoft Visual Studio Solution File, Format Versi ...
- Android获取当前时间与星期几
public class DataString { private static String mYear; private static String mMonth; private static ...
- smarty 内置函数if 等判断
{if},{elseif},{else} Smarty的{if}条件判断和PHP的if 非常相似,只是增加了一些特性. 每个{if}必须有一个配对的{/if}. 也可以使用{else} 和 {else ...
- Linux企业级项目实践之网络爬虫(3)——设计自己的网络爬虫
网络抓取系统分为核心和扩展组件两部分.核心部分是一个精简的.模块化的爬虫实现,而扩展部分则包括一些便利的.实用性的功能.目标是尽量的模块化,并体现爬虫的功能特点.这部分提供简单.灵活的API,在基本不 ...
- bzoj4005[JLOI2015]骗我呢
http://www.lydsy.com/JudgeOnline/problem.php?id=4005 神题~远距离orz 膜拜PoPoQQQ大神 #include<cstdio> #i ...
- struct2(六) 为表单添加验证
简介 为表单添加验证 添加校验的方法: 1. first name 不能为null 2. Email address 不能为null 3. age 必须大于18岁 为了在用户提交的时候,能够校验这个表 ...