爱悠闲 > WIndows学习心得【设计一个矩形】

WIndows学习心得【设计一个矩形】

分类: Windows学习日记  |  标签: winapi,windows,源码,测试  |  作者: u013517637 相关  |  发布日期 : 2015-06-02  |  热度 : 139°
#include<windows.h>

LRESULT CALLBACK WndProc(HWND,UINT ,WPARAM, LPARAM);//回调函数的声明

int WINAPI WinMain(HINSTANCE hInstance,//当前实例的句柄
				   HINSTANCE hPrevInstance,//先前实例的句柄
				   PSTR szCmdLine,//指向应用程序命令行的字符串的指针
				   int iCmdShow)//指明窗口如何显示
{
	static TCHAR szAppName[]=TEXT("BlockOut1");
	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。若想获得更多错误信息,请调用GetLastError函数。
	hwnd=CreateWindow(szAppName,TEXT("Mouse Button 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是消息携带的参数,可以是个值,也可以是个地址
}

void DrawBoxOutline(HWND hwnd,POINT ptBeg,POINT ptEnd)
{
	HDC hdc;//句柄
	hdc=GetDC(hwnd);//获取环境句柄
	
	//用于设定当前前景色的混合模式
	//R2_NOT就是取反的意思,即前景色为背景色的反色,经常用R2_NOT来画橡皮线,因为两次取反可以还原背景色
	SetROP2(hdc,R2_NOT);
	//GetStockObject该函数检索预定义的备用笔、刷子、字体或者调色板的句柄
	//NULL_BRUSH的意思是空刷(相当于HOLLOW_BRUSH)。
	SelectObject(hdc,GetStockObject(NULL_BRUSH));
	//使用该函数画一个矩形,可以用当前的画笔画矩形轮廓,用当前画刷进行填充。
	Rectangle(hdc,ptBeg.x,ptBeg.y,ptEnd.x,ptEnd.y);
	ReleaseDC(hwnd,hdc);//释放句柄
}

LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
	static BOOL fBlocking,fValidBox;
	static POINT ptBeg,ptEnd,ptBoxBeg,ptBoxEnd;
	HDC hdc;//句柄
	PAINTSTRUCT ps;//包含窗口需要绘制的信息  

	switch(message)
	{
	case WM_LBUTTONDOWN:
		ptBeg.x=ptEnd.x=LOWORD(lParam);//获取当前鼠标的坐标
		ptBeg.y=ptEnd.y=HIWORD(lParam);

		DrawBoxOutline(hwnd,ptBeg,ptEnd);

		//该函数在属于当前线程的指定窗口里设置鼠标捕获。
		//一旦窗口捕获了鼠标,所有鼠标输入都针对该窗口,无论光标是否在窗口的边界内。
		SetCapture(hwnd);
		//设置光标为IDC_CROSS,表示正在画矩形 
		SetCursor(LoadCursor(NULL,IDC_CROSS));
		//TRUE表示正在画矩形
		fBlocking=TRUE;
		return 0;
	case WM_MOUSEMOVE:
		if(fBlocking)
		{
			SetCursor(LoadCursor(NULL,IDC_CROSS));//设置光标为IDC_CROSS,表示正在画矩形 

			DrawBoxOutline(hwnd,ptBeg,ptEnd);
			ptEnd.x=LOWORD(lParam);//获取当前鼠标的坐标
			ptEnd.y=HIWORD(lParam);

			DrawBoxOutline(hwnd,ptBeg,ptEnd);//画出当前的矩形
		}
		return 0;
	case WM_LBUTTONUP:
		if(fBlocking)
		{
			DrawBoxOutline(hwnd,ptBeg,ptEnd);
			//用来保存最终的矩形
			ptBoxBeg=ptBeg;
			ptBoxEnd.x=LOWORD(lParam);//获取当前鼠标的坐标
			ptBoxEnd.y=HIWORD(lParam);

			//该函数从当前线程中的窗口释放鼠标捕获,并恢复通常的鼠标输入处理。
			ReleaseCapture();

			SetCursor(LoadCursor(NULL,IDC_ARROW));//设置鼠标的显示方式
			
			fBlocking=FALSE;//表示画图停止
			fValidBox=TRUE;
			//下面后调用WM_PAINT 
			InvalidateRect(hwnd,NULL,TRUE);//该函数向指定的窗体更新区域添加一个矩形,然后窗口客户区域的这一部分将被重新绘制
		}
		return 0;
	case WM_CHAR:
		 //x1b是esc,实现效果,当正在画时,点一个esc会取消
		if(fBlocking&(wParam=='\x1B'))
		{
			DrawBoxOutline(hwnd,ptBeg,ptEnd);

			SetCursor(LoadCursor(NULL,IDC_ARROW));

			fBlocking=FALSE;
		}
		return 0;
	case WM_PAINT:
		hdc=BeginPaint(hwnd,&ps);//获取环境句柄

		if(fValidBox)
		{
			SelectObject(hdc,GetStockObject(BLACK_BRUSH));//设置画刷为黑色
			Rectangle(hdc,ptBoxBeg.x,ptBoxBeg.y,
				ptBoxEnd.x,ptBoxEnd.y);//画出黑色矩形
		}
		if(fBlocking)
		{
			SetROP2(hdc,R2_NOT);
			SelectObject(hdc,GetStockObject(NULL_BRUSH));
			Rectangle(hdc,ptBeg.x,ptBeg.y,ptEnd.x,ptEnd.y);
		}
		EndPaint(hwnd,&ps);//释放环境句柄
		return 0;
	case WM_DESTROY://关闭窗口
		PostQuitMessage(0);//该函数向系统表明有个线程有终止请求。通常用来响应WM_DESTROY消息。
		return 0;
	}
	return DefWindowProc(hwnd,message,wParam,lParam);//该函数调用缺省的窗口过程来为应用程序没有处理的任何窗口消息提供缺省的处理 
}
附加一张图片,加油继续!