利用VS创建一个游戏(1)窗口框架(代码+注释)

#include "stdafx.h"  
#include "MyGameFrame.h" //源cpp文件引申出的头文件 也可以用resource.h代替  

// 全局变量:   
HINSTANCE hInst;   // 当前实例
HWND      hWnd;    //窗口句柄



// 此代码模块中包含的函数的前向声明:   
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitWindow(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);


int APIENTRY WinMain(
	/*
	APIENTRY     是Windows SDK函数调用的入口
	WinMain      函数功能:1)创建游戏主窗口;2)获得游戏玩家输入的消息;3)分配玩家输入消息并响应消息。
	HINSTANCE    是Windows里的一种数据类型(句柄型),其实就是一个无符号的长整形,是32位的,是用于标示(记录)一个程序的实例,是识别游戏程序的句柄
	hPrevInstance用于跟踪应用程序的前一个实例。
	LPSTR        一个32位指向字符串的指针
	lpCmdLine    是一个以NULL结尾的字符串。
	nCmdShow     是程序启动期间传递给游戏程序的一个整数,指定游戏窗口的显示方式
	*/
	HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPSTR    lpCmdLine,
	int       nCmdShow)
{    

	// 初始化全局字符串  
	MyRegisterClass(hInstance);

	// 执行应用程序初始化:   
	if (!InitWindow(hInstance, nCmdShow))//初始化窗口  
	{
		return FALSE;//如果不成功则返回FALSE,并退出程序  
	}

	/*
	MSG类型见 https://blog.csdn.net/wanghaofeng/article/details/6632165
	*/
	MSG msg; //创建消息类对象  

	// TODO: 在此放置运行代码。

    // 主消息循环:   
	PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);//赋初值  
	/*
	前面的四个参数(一个指向MSG结构的指针、一个窗口句柄、两个值指示消息范围)与GetMessage的参数相同。将第二、三、四个参数设定为NULL或0时,
	表明我们想让PeekMessage传回程序中所有窗口的所有消息。如果要将消息从消息队列中删除,则将PeekMessage的最后一个参数设定为PM_REMOVE。
	如果您不希望删除消息,那么您可以将这个参数设定为PM_NOREMOVE。这就是为什么Peek_Message是「偷看」而不是「取得」的原因,
	它使得程序可以检查程序的队列中的下一个消息,而不实际删除它。
	*/
	while (msg.message != WM_QUIT)         //进入游戏消息循环:  
	{
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg); //获得游戏玩家输入的消息;  
			DispatchMessage(&msg);//分配玩家消息并响应用户消息。  
		}
	}
	//如果你不喜欢上面从初始化到结束的写法,也可以这样写,这样可以不用初始化PeekMessage()  

	/*while (PeekMessage(&msg, nullptr, 0, 0,PM_REMOVE))
	{
	if (msg.message == WM_QUIT) break;//WM_QUIT 用来结束程序运行进入游戏消息循环


	TranslateMessage(&msg);  //获得游戏玩家输入的消息
	DispatchMessage(&msg);   //分配玩家消息并响应用户消息
	}*/
	return (int)msg.wParam;
}



//  
//  函数: MyRegisterClass()  
//  
//  注册Windows类,一款游戏有且仅有一个主窗口,与游戏程序唯一对应。创建游戏窗口前要填写窗口类结构体WNDCLASSEX  
//  
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex =
	{
		wcex.cbSize = sizeof(WNDCLASSEX),

		/*
		窗口类的风格标志。
		运用“或”操作(操作符“|”)将一些基本风格的标识符组合,就可以实现游戏窗口风格的多重性
		设定窗口进行绘图,可通过CS_OWNDC得到设备描述表
		例:wcex.style = CS_VERDRAW | CS_HREDRAW;
		*/
		CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW,

		/*
		WndProc  //窗口消息处理函数的指针,接收一个指向窗口函数的指针,将执行所有的窗口任务。
		int cbClsExtra;                 //分配给窗口类结构之后的额外字节数
		int cbWndExtra;                 //分配给窗口实例之后的额外字节数
		ps:cbClsExtra和cbWndExtra用来指示Windows类中保留一些额外空间,如保存附加的运行时间信息,一般都为0。
		*/
		WndProc,0,0,

		/*
		窗口所对应的应用程序的句柄,表示窗口所对应程序的句柄,在启动时传递给WinMain( )函数的句柄实例。
		wcex.hInstance = hinstance;
		*/
		hInstance,

		/*
		重点:此处的IDI_MYGAMEFRAME(PPT中为IDI_GAMEFRAME)应当替换为IDI_(项目名),IDI_(项目名)位于resource.h文件中!!
		MAKEINTRESOURCE用来将数字类型转化为指针类型
		HICON LoadIcon(HINSTANCE hInstance, LPCTSTR LpIconName)函数获得指向通用系统图标的句柄
		参数hInstance是从应用程序装载图标资源实例,为NULL表示装载标准图标。LpIconName:被装载图标资源名称。
		例:wcex.hIcon = loadIcon (NULL, IDI_APPLICATION);
		*/
		LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYGAMEFRAME)),

		/*
		HCURSOR LoadCursor(HINSTANCE hInstance, LPCTSTR  lpCursorName)
		函数得到资源或预定义的系统光标。资源是编译到游戏程序中的数据,如位图、图标、声音等
		hInstance:是从应用程序装载光标资源的实例,默认为NULL。lpCursorName则标识了资源名字符串或资源句柄。
		例:wcex.hCursor = LoadCursor (NULL, IDC_ARROW);
		*/
		LoadCursor(NULL, IDC_ARROW),


		(HBRUSH)(COLOR_WINDOW + 1),NULL,

		/*
		窗口菜单名
		窗口类的名称,给游戏窗口类名一个独一无二名称。
		重点:调用CreateWindow( )函数将用到这个名称,游戏窗口名称常常与程序名称完全一致
		_T将ASCII字符串转化为Unicode字符
		或者将项目属性-字符集调整为“使用多字符集”!!!
		*/
		_T("GameFrame"),

		/*
		应用程序小图标,是应用程序小图标。指向窗口的标题栏和Windows桌面任务栏显示的图标。
		*/
		LoadIcon(NULL,MAKEINTRESOURCE(IDI_SMALL))
	};
	return RegisterClassEx(&wcex);
}

//  
//   函数: InitInstance(HINSTANCE, int)  
//  
//   目的: 保存实例句柄并创建主窗口  
//  
//   注释:   
//  
//        在此函数中,我们在全局变量中保存实例句柄并  
//        创建和显示主程序窗口。  
//  
BOOL InitWindow(HINSTANCE hInstance, int nCmdShow)
{
	hInst = hInstance; // 将实例句柄存储在全局变量中  

					   /*
					   HWND CreateWindow
					   (
					   LPCTSTR   lpClassName,        //类名指针
					   LPCTSTR   lpWindowName,       //窗口名指针
					   DWORD     dwStyle,            //窗口样式
					   int       x,                  //窗口的水平坐标
					   int       y,                  //窗口的竖直坐标
					   int       nWidth,             //窗口宽度
					   int       nHeight,            //窗口高度
					   HWND      hWndParent,         //父窗口句柄
					   HMENU     hMenu,              //菜单句柄或子窗口标识符
					   HINSTANCE hInstance,          //应用程序实例句柄
					   LPVOID    lpParam             //指向窗口创建数据的指针
					   );
					   */
	 hWnd = CreateWindow
	(
		_T("GameFrame"),
		_T("游戏框架"),
		WS_OVERLAPPEDWINDOW^WS_THICKFRAME^WS_MAXIMIZEBOX,//普通样式,不能改变大小,不能最大化  
		CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, nullptr, nullptr, hInstance, nullptr
	);

	if (!hWnd)
	{
		return FALSE;
	}
	/*
	显示和刷新窗口
	BOOL ShowWindow( HWND hWnd, int nCmdShow )
	*/
	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);

	return TRUE;
}

//  
//  函数: WndProc(HWND, UINT, WPARAM, LPARAM)  
//  
//  目的:    处理主窗口的消息。  
//  
//  WM_COMMAND  - 处理应用程序菜单  
//  WM_PAINT    - 绘制主窗口  
//  WM_DESTROY  - 发送退出消息并返回  
//  
//  
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
	PAINTSTRUCT ps;                     //用于WM_PAINT  
	HDC hdc;                            //设备场景句柄  
	switch (msg)                        //判断消息  
	{
	case WM_CREATE:
		//执行初始化代码                
		return(0);
		break;
	case WM_PAINT:
		//确定窗口是否有效  
		hdc = BeginPaint(hwnd, &ps);
		//TODO:添加执行绘制代码  

		//结束代码  
		EndPaint(hwnd, &ps);
		return(0);
		break;
	case WM_DESTROY:
		//关闭程序,发送WM_QUIT消息  
		PostQuitMessage(0);
		return(0);
		break;
	default:
		break;
	}
	return (DefWindowProc(hwnd, msg, wparam, lparam));
}

猜你喜欢

转载自blog.csdn.net/hao5119266/article/details/79921512