zoukankan      html  css  js  c++  java
  • <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);
    }


     

    运行效果还是很漂亮的:

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

  • 相关阅读:
    初探深度学习
    第二次作业:卷积神经网络 part 1
    随笔小记
    Typora实用小工具(AHK)
    第一次作业:深度学习基础
    Nginx HTTPS 部署实战
    win10系统中如何解决cmd中的路径和现在电脑的用户名不一致
    Centos7.5.1804永久生效修改主机名
    centos6.9NAT网络模式
    linux 系统中用root切换到普通用户时显示的异常如bash4.1$
  • 原文地址:https://www.cnblogs.com/aukle/p/3220286.html
Copyright © 2011-2022 走看看