Windows学习心得【计时器1】

本文通过一个具体的Windows应用程序示例,介绍了如何使用Windows API中的定时器功能。包括定时器的创建、使用及销毁等关键步骤。
#include<windows.h>

#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.cbClsExtra=0;//窗口扩展,此处为0 
	wndclass.cbWndExtra=0;//窗口实例扩展,此处为0
	wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);//窗口背景颜色的设置,此处设置为白色
	wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);//鼠标的显示方式,此处设置为标准型
	wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);//窗口的显示方式,此处设置为应用程序型   
	wndclass.hInstance=hInstance;//窗口的实例句柄
	wndclass.lpfnWndProc=WndProc;//窗口回调函数
	wndclass.lpszClassName=szAppName;//窗口类名
	wndclass.lpszMenuName=NULL;//窗口菜单,此处没菜单设为NULL 

	if(!RegisterClass(&wndclass))//注册窗口,若注册失败,产生如下的信息
	{
		MessageBox(NULL,TEXT("Program requires Windows NT!"),
			szAppName,MB_ICONERROR);
		return 0;
	}

	////创建窗口,如果函数成功,返回值为新窗口的句柄:如果函数失败,返回值为NULL。
	hwnd=CreateWindow(szAppName,
		TEXT("Beerer1 Timer Demo"),//窗口的名字 
		WS_OVERLAPPEDWINDOW,//指定创建窗口的风格
		CW_USEDEFAULT,//指定窗口的初始水平位置,如果该参数被设为CW_USEDEFAULT则系统为窗口选择缺省的左上角坐标并忽略Y参数
		CW_USEDEFAULT,//指定窗口的初始垂直位置 
		CW_USEDEFAULT,//以设备单元指明窗口的宽度。若是CW_USEDEFAULT,则系统为窗口选择一个缺省的宽度
		CW_USEDEFAULT,//以设备单元指明窗口的高度。若被设为CW_USEDEFAULT,则系统忽略nHeight参数。
		NULL,//指向被创建窗口的父窗口或所有者窗口的句柄,此处为NULL 
		NULL,//菜单句柄,或依据窗口风格指明一个子窗口标识,此处为NULL
		hInstance,//与窗口相关联的模块实例的句柄。  
		NULL);//指向一个值的指针,该值传递给窗口WM_CREATE消息  

	ShowWindow(hwnd,iCmdShow);//显示窗口,hWnd:指窗口句柄。iCmdShow:指定窗口如何显示。  
	UpdateWindow(hwnd);//更新窗口,hWnd:指窗口句柄。  

	while(GetMessage(&msg,NULL,0,0))//消息循环
	{
		TranslateMessage(&msg);//该函数将虚拟键消息转换为字符消息  
		DispatchMessage(&msg);//该函数分发一个消息给窗口程序。
	}
	return msg.wParam;//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参数为非0,则返回一个非零的整数,可以把这个非零的整数传递给KillTimer来销毁时钟.
		//hwnd是一个窗口句柄,它指向接收WM_TIMER消息的窗口过程
		//第二个参数是一个计时器的ID,它不能为0
		//第三个参数是一个32位的无符号整数,它指定以毫秒为单位的时间间隔
		//第四个参数一般为NULL,系统将会向消息队列中放入一个WM_TIMER消息
		SetTimer(hwnd,ID_TIMER,1000,NULL);
		return 0;
	case WM_TIMER:
		MessageBeep(-1);//essageBeep函数用来播放一个波形声音,
		//上面的-1其实就是0xFFFFFFFF表示从扬声器中播放出一段蜂鸣声。详细参数参考MSDN
		fFlipFlop=!fFlipFlop;
		InvalidateRect(hwnd,NULL,FALSE);//该函数向指定的窗体更新区域添加一个矩形,然后窗口客户区域的这一部分将被重新绘制
		//第一个参数为要更新的客户区所在的窗体的句柄
		//第二个参数为无效区域的矩形代表,它是一个结构体指针,存放着矩形的大小。如果为NULL,全部的窗口客户区域将被增加到更新区域中。
		//第三个参数指出无效矩形被标记为有效后,是否重画该区域,重画时用预先定义好的画刷。当指定TRUE时需要重画。
		return 0;
	case WM_PAINT:
		hdc=BeginPaint(hwnd,&ps);//获取句柄

		GetClientRect(hwnd,&rc);//该函数获取窗口客户区的坐标

		hBrush=CreateSolidBrush(fFlipFlop?RGB(255,0,0):RGB(0,0,255));
		//CreateSolidBrush函数创建一个具有指定颜色的逻辑刷子。
		//如果该函数执行成功,那么返回值标识一个逻辑实心刷子;如果函数失败,那么返回值为NULL
		//参数为指定刷子的颜色
		FillRect(hdc,&rc,hBrush);
		//FillRect函数用指定的画刷填充矩形
		//hdc:设备环境句柄。
		//第二个参数为指向含有将填充矩形的逻辑坐标的RECT结构的指针
		//第三个参数用来填充矩形的画刷的句柄

		EndPaint(hwnd,&ps);//释放句柄
		DeleteObject(hBrush);//函数功能:释放画刷句柄
		return 0;
	case WM_DESTROY:
		KillTimer(hwnd,ID_TIMER);//移除定时器函数的声明:移除先前用SetTimer设置的定时器。在定时器使用完毕后移除定时器时使用
		//第一个参数与定时器相关联的窗口句柄
		//第二个参数为定时器标识符
		PostQuitMessage(0);//该函数向系统表明有个线程有终止请求。通常用来响应WM_DESTROY消息
		return 0;
	}
	return DefWindowProc(hwnd,message,wParam,lParam);//该函数调用缺省的窗口过程来为应用程序没有处理的任何窗口消息提供缺省的处理
}
下面传张图片记录一下
在ClassWizard中响应ID为~Dlg中的WM_TIMER消息。 使用SetTimer(nIDEvent,time,NULL)来建立一个定时器,关闭定时器用KillTimer(nIDEvent)函数。 然后可以响应ON_WM_TIMER消息来响应一个定时器完成一次记时后的程序。 响应方式如下: void CTimeDlg::OnTimer(UINT nIDEvent) { if(nIDEvent==1000)//间隔为5秒 { //处理事件 } elseif(nIDEvent==1001)//间隔为10秒 { //处理事件 } CDialog::OnTimer(nIDEvent); } 以下是给出一个串口通信定时检查接收数据的部分代码 void CMyDlg::OnOpenCom() { // TODO: Add your control notification handler code here if( f_open_com==true ) { f_open_com = false; GetDlgItem(IDC_OPEN_COM)->SetWindowText("打开通信端口"); CloseHandle(hComm); KillTimer(1000); /// 关闭定时器 return ; } SetTimer(1000, 1000, NULL); ///nIDEvent==1000,time=5000ms const char *ComNo; DCB dcb; string temp("COM1"); ComNo = temp.c_str(); hComm = CreateFile( ComNo , GENERIC_READ|GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , 0 , 0); if( hComm==INVALID_HANDLE_VALUE ) /// 如果端口未打开 { MessageBox("打开通信端口出错!" , "Comm Error" , MB_OK); return ; } /// 将dcb地址传入,以取得通信参数 GetCommState(hComm,&dcb); /// 得知目前通信状态 dcb.BaudRate = CBR_9600; dcb.ByteSize = 8; /// 字节为8 dcb.Parity = NOPARITY; /// Parity为None dcb.StopBits = ONESTOPBIT; /// 1个停止位 if( !SetCommState( hComm , &dcb)){ MessageBox("通信端口设置出错!" , "Set Error" , MB_OK ); CloseHandle(hComm); return; } GetDlgItem(IDC_OPEN_COM)->SetWindowText("关闭通信端口"); f_open_com = true; } void CMyDlg::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default char inbuff[1024]; DWORD nBytesRead , dwError; COMSTAT cs; /// 取得状态 ClearCommError( hComm , &dwError , &cs); /// 数据是否大于所准备的缓冲区 if( cs.cbInQue > sizeof(inbuff) ) { PurgeComm(hComm , PURGE_RXCLEAR ); /// 清除通信端口数据 return ; } ReadFile(hComm , inbuff , cs.cbInQue , &nBytesRead , NULL ); //接收通信端口的数据 inbuff[cs.cbInQue] = '\0'; MessageBox("打开通信端口出错!" , "Comm Error" , MB_OK); m_Receive.Format("%s",inbuff); UpdateData(false); CDialog::OnTimer(nIDEvent); } 李杨: for(int i=0; ;i++ ) { ... Sleep(5); if(i>...) {AfxMessageBox("错误XXX"); return;} }//跳出后记得停止一些机器动作
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值