win32-带你一步一步编写绘画板(1) by小黄

一、写在前面

查遍了很多资料,没能找到一个完整的编写绘画板的博客,而且很多代码都是需要用积分下载的,这对新手是真的不够友好啊。我目前也还在学习,用此方法记录和巩固一下,并且为新手指个路,希望不要像我一样全靠自己摸索。下面进入正题。

二、Win32程序入口函数

Win32程序的入口函数是 WinMain , 和控制台程序的入口函数main类似。如下:

#include <windows.h>


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
	return 0;
}

Windows程序入口函数:
WINAPI 代表_stdcall(一个宏) 参数的传递顺序:从右到左 依次入栈,并且在函数返回前 清空堆栈
hInstance 代表当前应用程序实例句柄
hPrevInstance 代表上一个应用程序句柄,在win32 环境下,参数一般为NULL
lpCmdLine 即 char* argv[]
nShowCmd 显示方式,例如最大化,最小化,正常

三、创建窗口步骤

创建窗口总共分为六步,依次是:
1、设计窗口
2、注册窗口
3、创建窗口
4、显示和更新
5、通过循环取消息
6、处理消息(窗口过程)
我在代码中标注了一下注释,对照着看帮助理解。代码块是分开解释,直接按照顺序整合到WinMain函数中即可。在总结中,有完整的代码。每次更新都会将完整的代码附在后面。

1、设计窗口

//1、设计窗口
	2 wnc;//窗口类
	wnc.cbClsExtra = 0;//类 额外内存
	wnc.cbWndExtra = 0;//窗口 额外内存
	wnc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//背景
	wnc.hCursor = LoadCursor(NULL, IDC_ARROW); //光标。第一个参数为NULL,代表使用系统提供的光标
	wnc.hIcon = LoadIcon(NULL, IDI_APPLICATION); //图标
	wnc.hInstance = hInstance;//应用程序的实例句柄,传入WinMain中的形参
	wnc.lpfnWndProc = WindowProc; //窗口过程函数,回调函数
	wnc.lpszClassName = TEXT("WIN");//窗口的类名称
	wnc.lpszMenuName = NULL;//菜单名
	wnc.style = CS_HREDRAW | CS_VREDRAW;//横向重绘和纵向重绘,设置之后才会出现WM_PAINT消息

2、注册窗口

//2、注册窗口
	RegisterClass(&wnc);

3、创建窗口

//3、创建窗口
	/*
	lpClassName		类名,和上面保持一致
	lpWindowName	窗口标题名称
	dwStyle			风格  WS_OVERLAPPEDWINDOW混合风格
	x				坐标 CW_USEDEFAULT默认值
	y				坐标
	nWidth			宽
	nHeight			高
	hWndParent		父窗口
	hMenu			菜单
	hInstance		当前实例句柄
	lpParam			附加值 鼠标附加值
	*/
	HWND hwnd = CreateWindow(wnc.lpszClassName, TEXT("绘画板-Win32 by 小黄"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, wnc.hInstance, NULL);
	

4、显示与更新

	//4、显示和更新
	ShowWindow(hwnd, SW_SHOWNORMAL);
	UpdateWindow(hwnd);

5、通过循环取消息

//5、通过循环取消息
	/*   
	MSG 结构体
	HWND        hwnd;		主窗口句柄
	UINT        message;	具体的消息
	WPARAM      wParam;		附加消息,通常是键盘消息
	LPARAM      lParam;		附加消息,通过是鼠标消息
	DWORD       time;		消息产生的时间
	POINT       pt;			附加消息,鼠标坐标信息
	*/
	MSG msg;
	while (GetMessage(&msg, NULL, 0, 0)) //循环获取消息
	{
		/*
		LPMSG lpMsg,         // address of structure with message
		HWND hWnd,           // handle of window,为NULL时,代表接收所有的窗口的消息
		UINT wMsgFilterMin,  // first message ,最大和最小的过滤的消息,一般填入0
		UINT wMsgFilterMax   // last message. 填0代表接收所有的消息

		*/
		
		//翻译消息
		//有的消息不能直接执行,
		//比如ctrl+C是复制消息,因此需要翻译,并且重新进入消息队列排队
		TranslateMessage(&msg);
		//分发消息
		DispatchMessage(&msg);
	}

6、回调函数

在设计窗口时,在下面这句代码中传递进去的便是窗口回调函数。

wnc.lpfnWndProc = WindowProc; //窗口过程函数,回调函数

接下来编写该函数



//6、窗口过程
/*
HWND hwnd,		消息所属的窗口句柄
UINT uMsg,		具体消息名称 WM_xxxxxxxx 消息名
WPARAM wParam,	键盘附加消息
LPARAM lParam	鼠标附加消息
*/
// #define CALLBACK    __stdcall  
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	
	switch (uMsg)
	{
	case WM_CLOSE:
		//所有xxxWindow结尾的消息,不会进入消息队列,而是直接执行
		DestroyWindow(hwnd);	//DestroyWindow 发送另一个消息 WM_DESTROY
		break;
	case WM_DESTROY:
		PostQuitMessage(NULL);
		break; 
	default:
		break;
	}
	//返回值默认处理方式
	return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

四、总结

这次是先创建窗口,接下来会在此次创建的窗口的基础上编写绘画板。持续更新中。。。
本次完整代码如下:

#include <windows.h>//底层实现窗口的头文件


//6、窗口过程
/*
HWND hwnd,		消息所属的窗口句柄
UINT uMsg,		具体消息名称 WM_xxxxxxxx 消息名
WPARAM wParam,	键盘附加消息
LPARAM lParam	鼠标附加消息
*/
// #define CALLBACK    __stdcall  
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	
	switch (uMsg)
	{
	case WM_CLOSE:
		//所有xxxWindow结尾的消息,不会进入消息队列,而是直接执行
		DestroyWindow(hwnd);	//DestroyWindow 发送另一个消息 WM_DESTROY
		break;
	case WM_DESTROY:
		PostQuitMessage(NULL);
		break; 
	default:
		break;
	}
	//返回值默认处理方式
	return DefWindowProc(hwnd, uMsg, wParam, lParam);
}



//Windows程序入口函数
//WINAPI代表_stdcall(一个宏) 参数的传递顺序:从右到左 依次入栈,并且在函数返回前 清空堆栈
//hInstance 当前应用程序实例句柄
//hPrevInstance 上一个应用程序句柄,在哪win32 环境下,参数一般为NULL
//lpCmdLine 即 char* argv[]
//nShowCmd 显示方式,例如最大化,最小化,正常
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
	//1、设计窗口
	//2、注册窗口
	//3、创建窗口
	//4、显示和更新
	//5、通过循环取消息
	//6、处理消息(窗口过程)

	//1、设计窗口
	WNDCLASS wnc;//窗口类
	wnc.cbClsExtra = 0;//类 额外内存
	wnc.cbWndExtra = 0;//窗口 额外内存
	wnc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//背景
	wnc.hCursor = LoadCursor(NULL, IDC_HAND); //光标。第一个参数为NULL,代表使用系统提供的光标
	wnc.hIcon = LoadIcon(NULL, IDI_ERROR); //图标
	wnc.hInstance = hInstance;//应用程序的实例句柄,传入WinMain中的形参
	wnc.lpfnWndProc = WindowProc; //窗口过程函数,回调函数
	wnc.lpszClassName = TEXT("WIN");//窗口的类名称
	wnc.lpszMenuName = NULL;//菜单名
	wnc.style = CS_HREDRAW | CS_VREDRAW;//横向重绘和纵向重绘,设置之后才会出现WM_PAINT消息
	//2、注册窗口
	RegisterClass(&wnc);
	//3、创建窗口
	/*
	lpClassName		类名,和上面保持一致
	lpWindowName	窗口标题名称
	dwStyle			风格  WS_OVERLAPPEDWINDOW混合风格
	x				坐标 CW_USEDEFAULT默认值
	y				坐标
	nWidth			宽
	nHeight			高
	hWndParent		父窗口
	hMenu			菜单
	hInstance		当前实例句柄
	lpParam			附加值 鼠标附加值
	*/
	HWND hwnd = CreateWindow(wnc.lpszClassName, TEXT("绘画板-Win32 by 小黄"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, wnc.hInstance, NULL);
	//4、显示和更新
	ShowWindow(hwnd, SW_SHOWNORMAL);
	UpdateWindow(hwnd);
	//5、通过循环取消息
	/*   
	MSG 结构体
	HWND        hwnd;		主窗口句柄
	UINT        message;	具体的消息
	WPARAM      wParam;		附加消息,通常是键盘消息
	LPARAM      lParam;		附加消息,通过是鼠标消息
	DWORD       time;		消息产生的时间
	POINT       pt;			附加消息,鼠标坐标信息
	*/
	MSG msg;
	while (GetMessage(&msg, NULL, 0, 0)) //循环获取消息
	{
		/*
		LPMSG lpMsg,         // address of structure with message
		HWND hWnd,           // handle of window,为NULL时,代表接收所有的窗口的消息
		UINT wMsgFilterMin,  // first message ,最大和最小的过滤的消息,一般填入0
		UINT wMsgFilterMax   // last message. 填0代表接收所有的消息
		*/
		
		//翻译消息
		//有的消息不能直接执行,
		//比如ctrl+C是复制消息,因此需要翻译,并且重新进入消息队列排队
		TranslateMessage(&msg);
		//分发消息
		DispatchMessage(&msg);
	}
	//6、窗口过程
	//对回调函数的编写


	return 0;
}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值