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


     

    运行效果还是很漂亮的:

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

  • 相关阅读:
    Python 爬虫js加密破解(一) 爬取今日头条as cp 算法 解密
    Python 爬虫实例(2)—— 爬取今日头条
    Python 爬虫实例(1)—— 爬取百度图片
    python 操作redis之——HyperLogLog (八)
    python 操作redis之——有序集合(sorted set) (七)
    Python操作redis系列之 列表(list) (五)
    Python操作redis系列以 哈希(Hash)命令详解(四)
    Python操作redis字符串(String)详解 (三)
    How to Install MySQL on CentOS 7
    Linux SSH远程文件/目录 传输
  • 原文地址:https://www.cnblogs.com/aukle/p/3220286.html
Copyright © 2011-2022 走看看