【逐梦旅程】二、Windows窗体

窗口

我们看到的应用程序就是窗口,Windows就是源于此。窗口分为客户区和非客户区,客户区是我们控制的程序内容,非客户区是Windows管理的,比如最小化,最大化等等。

句柄

句柄(Handle)是资源的标识号。窗口是通过窗口句柄(HWND)来标识的。似乎句柄类似于指针,但是不能理解为指针。书中说的很好,就是Windows资源的身份证。

消息队列

Windows操作系统是通过消息来进行程序与系统之间的通信的。这里引出了窗口过程函数。
消息投放到消息队列中,程序从消息队列中取出消息并响应。
消息的结构体是MSG。
每个程序启动后,系统都会为程序创建一个消息队列。Windows系统创建一个又一个消息,程序则从程序的消息队列中不断地消耗消息,这就是Windows程序的运行机制。

窗口创建四部曲

设计-注册-创建-显示与更新

设计

我们使用Winclassex结构体来创建窗口。

typedef struct tagWNDCLASSEXW {
  UINT      cbSize;
  UINT      style;
  WNDPROC   lpfnWndProc;
  int       cbClsExtra;
  int       cbWndExtra;
  HINSTANCE hInstance;
  HICON     hIcon;
  HCURSOR   hCursor;
  HBRUSH    hbrBackground;
  LPCWSTR   lpszMenuName;
  LPCWSTR   lpszClassName;
  HICON     hIconSm;
} WNDCLASSEXW, *PWNDCLASSEXW, *NPWNDCLASSEXW, *LPWNDCLASSEXW;

开始定义窗口

WNDCLASSEX wndClass = { 0 };

这行代码是用来初始化一个 WNDCLASSEX 结构体实例,wndClass。{ 0 } 将结构体的所有成员都设置为零,以确保它的初始状态是干净的。这样做可以避免使用未初始化的成员,减少潜在的错误。
WNDPROC lpfnWndProc 是一个指向窗口过程函数的回调函数,回调函数是不是有该函数的实现方调用的函数,是当某个事件发生后由另一方调用的的,用于对该事件进行响应。

#include <Windows.h>
#pragma comment(lib,"winmm.lib")
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
  //【1】窗口创建四步曲之一:开始设计一个完整的窗口类
  WNDCLASSEX wndClass = { 0 };							//用WINDCLASSEX定义了一个窗口类
  wndClass.cbSize = sizeof(WNDCLASSEX);			//设置结构体的字节数大小
  wndClass.style = CS_HREDRAW | CS_VREDRAW;	//设置窗口的样式
  wndClass.lpfnWndProc = WndProc;					//设置指向窗口过程函数的指针,现在还没有定义。
  wndClass.cbClsExtra = 0;								//窗口类的附加内存,取0就可以了
  wndClass.cbWndExtra = 0;							//窗口的附加内存,依然取0就行了
  wndClass.hInstance = hInstance;						//指定包含窗口过程的程序的实例句柄。
  wndClass.hIcon = (HICON)::LoadImage(NULL, L"icon.ico", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE);  //本地加载自定义ico图标
  wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);    //指定窗口类的光标句柄。
  wndClass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);  //为hbrBackground成员指定一个灰色画刷句柄	
  wndClass.lpszMenuName = NULL;						//用一个以空终止的字符串,指定菜单资源的名字。
  wndClass.lpszClassName = L"ForTheDreamOfGameDevelop";		//用一个以空终止的字符串,指定窗口类的名字。
}

窗口类的注册

	RegisterClassEx(&wndClass);

窗口的创建

//【3】窗口创建四步曲之三:正式创建窗口
HWND hwnd = CreateWindow(L"ForTheDreamOfGameDevelop", WINDOW_TITLE,		//喜闻乐见的创建窗口函数CreateWindow
	WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH,
	WINDOW_HEIGHT, NULL, NULL, hInstance, NULL);

窗口的更新

//【4】窗口创建四步曲之四:窗口的移动、显示与更新
MoveWindow(hwnd, 250, 80, WINDOW_WIDTH, WINDOW_HEIGHT, true);		//调整窗口显示时的位置,使窗口左上角位于(250,80)处
ShowWindow(hwnd, nShowCmd);    //调用ShowWindow函数来显示窗口
UpdateWindow(hwnd);						//对窗口进行更新,就像我们买了新房子要装修一样

CreateWindow 是用于创建新窗口并指定初始尺寸,而 MoveWindow 则是用于调整已存在窗口的尺寸和位置。我试验的是,我们看到的是MoveWindow 后的结果。

消息的循环

//【5】消息循环过程
MSG msg = { 0 };		//定义并初始化msg
while (msg.message != WM_QUIT)			//使用while循环,如果消息不是WM_QUIT消息,就继续循环
{
	if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))   //查看应用程序消息队列,有消息时将队列中的消息派发出去。
	{
		TranslateMessage(&msg);		//将虚拟键消息转换为字符消息
		DispatchMessage(&msg);			//分发一个消息给窗口程序。
	}
}

有两种消息处理机制,游戏开发利用的是这种非阻塞式的。

窗口过程函数


//-----------------------------------【WndProc( )函数】--------------------------------------
//	描述:窗口过程函数WndProc,对窗口消息进行处理
//------------------------------------------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)						//switch语句开始
	{
	case WM_PAINT:						// 若是客户区重绘消息
		ValidateRect(hwnd, NULL);		// 更新客户区的显示
		break;									//跳出该switch语句

	case WM_KEYDOWN:                // 若是键盘按下消息
		if (wParam == VK_ESCAPE)    // 如果被按下的键是ESC
			DestroyWindow(hwnd);		// 销毁窗口, 并发送一条WM_DESTROY消息
		break;									//跳出该switch语句

	case WM_DESTROY:				//若是窗口销毁消息
		PostQuitMessage(0);		//向系统表明有个线程有终止请求。用来响应WM_DESTROY消息
		break;								//跳出该switch语句

	default:									//若上述case条件都不符合,则执行该default语句
		return DefWindowProc(hwnd, message, wParam, lParam);		//调用缺省的窗口过程
	}

	return 0;			//正常退出
}

总结

在这里插入图片描述

这些都是些固定的套路,Windows开发最基本的知道有这么些东西就好了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值