当前位置: 首页 > news >正文

Win32_4深入浅出Win32的计时器

说起时间,对于我们搞IT的人来说,那是要多重要有多重要。我觉得有价值的时间是给有抱负和有才能的人准备的,因为他们会充分利用,不会让时间失望……

呵呵,有点儿说远了,还是回归主题吧

Win32的计时器其实就是用以下两个函数控制的一个控件:

设置计时器

UINT_PTRSetTimer(
HWNDhWnd,
UINT_PTRnIDEvent,
UINTuElapse,
TIMERPROClpTimerFunc
);

关闭计时器

BOOLKillTimer(

HWNDhWnd,
UINT_PTRuIDEvent
);

函数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);
}


运行效果还是很漂亮的:

可以看见,无边矩形、椭圆、圆角矩形交错绘制,呵呵……

相关文章:

  • response.IsClientConnected参考
  • 参数化SQL小认识
  • Win32_5程序员求爱的创意程序^_^
  • cisco单臂路由
  • VC2010中 调用DLL的方法
  • Win32_6Win32的验证码程序
  • iOS Xcode, 解决“Could not insert new outlet connection”的问题。
  • Win32_7由浅入深——滚动条
  • 简单实现web服务器负载均衡
  • Android编程之ActivityManager: Segmentation fault
  • C# 网络编程之网页简单下载实现
  • mac 下对 iterm 终端 设置代理
  • 如何理解c和c++的复杂类型声明
  • silverlight中datagrid数据到处excel
  • Android编程之如何取得View的当前位置
  • 9月CHINA-PUB-OPENDAY技术沙龙——IPHONE
  • (ckeditor+ckfinder用法)Jquery,js获取ckeditor值
  • 《用数据讲故事》作者Cole N. Knaflic:消除一切无效的图表
  • 【每日笔记】【Go学习笔记】2019-01-10 codis proxy处理流程
  • 2019年如何成为全栈工程师?
  • Android单元测试 - 几个重要问题
  • Angular Elements 及其运作原理
  • exports和module.exports
  • JS+CSS实现数字滚动
  • MySQL常见的两种存储引擎:MyISAM与InnoDB的爱恨情仇
  • orm2 中文文档 3.1 模型属性
  • Python利用正则抓取网页内容保存到本地
  • v-if和v-for连用出现的问题
  • 翻译 | 老司机带你秒懂内存管理 - 第一部(共三部)
  • 基于HAProxy的高性能缓存服务器nuster
  • 微信端页面使用-webkit-box和绝对定位时,元素上移的问题
  • media数据库操作,可以进行增删改查,实现回收站,隐私照片功能 SharedPreferences存储地址:
  • 专访Pony.ai 楼天城:自动驾驶已经走过了“从0到1”,“规模”是行业的分水岭| 自动驾驶这十年 ...
  • ​草莓熊python turtle绘图代码(玫瑰花版)附源代码
  • ​批处理文件中的errorlevel用法
  • !!Dom4j 学习笔记
  • #git 撤消对文件的更改
  • #快捷键# 大学四年我常用的软件快捷键大全,教你成为电脑高手!!
  • (10)Linux冯诺依曼结构操作系统的再次理解
  • (a /b)*c的值
  • (Arcgis)Python编程批量将HDF5文件转换为TIFF格式并应用地理转换和投影信息
  • (HAL)STM32F103C6T8——软件模拟I2C驱动0.96寸OLED屏幕
  • (转)大型网站的系统架构
  • *_zh_CN.properties 国际化资源文件 struts 防乱码等
  • .net core 6 使用注解自动注入实例,无需构造注入 autowrite4net
  • .NET Framework 4.6.2改进了WPF和安全性
  • .NET 跨平台图形库 SkiaSharp 基础应用
  • .NET/C# 编译期能确定的字符串会在字符串暂存池中不会被 GC 垃圾回收掉
  • .net打印*三角形
  • .net使用excel的cells对象没有value方法——学习.net的Excel工作表问题
  • .NET中的Event与Delegates,从Publisher到Subscriber的衔接!
  • /dev/sda2 is mounted; will not make a filesystem here!
  • [ web基础篇 ] Burp Suite 爆破 Basic 认证密码
  • [ASP.NET MVC]Ajax与CustomErrors的尴尬
  • [BZOJ 3531][Sdoi2014]旅行(树链剖分+线段树)