windows游戏编程(三) 创建菜单资源

windows游戏编程大师技巧第二版也是很老的书了,内容有些变化。

使用vs2019创建菜单资源:

 

资源名称修改为MainMenu.rc,

查看菜单ID:

方法一:

双击进入:

 

 

菜单ID为IDR_MENU1 

双击打开resource.h文件

 

 这里的ID_FILE_OPEN,ID_FILE_CLOSE就是菜单栏按钮的id,后面代码中还需要使用。

 

代码记得#include "resource.h"

#define WIN32_LEAN_AND_MEAN //预编译指令 指示编译器不要包含MFC的内容

#include <Windows.h>
#include <windowsx.h>
#include "resource.h"

//我们创建的窗口和其他应用程序窗口都会产生事件和消息,所有消息都进入一个队列,并且我们的窗口消息发送到我们的窗口专用队列中,
//然后,主事件循环检索这些消息,并且把他们我们的窗口WindowProc中处理
/*
hwnd:窗口句柄,当我们使用同一个类建立多个窗口时才会用到,hwnd是表明消息来自哪个窗口的唯一途径
*/
LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
	PAINTSTRUCT ps;
	HDC hdc;
	switch (msg) {
		case WM_ACTIVATE: //当窗口第一次创建
			return 0;
			break;
		case WM_COMMAND: 
			switch (LOWORD(wParam)) {
				case ID_FILE_OPEN:
					break;
				case ID_FILE_CLOSE:
					break;
				case ID_FILE_SAVE:
					break;
				case ID_FILE_EXIT:
					break;
				case ID_HELP_ABOUT:
					break;
				default:
					break;
			}
		break;
		case WM_PAINT: {//当窗口需要重画
			hdc = BeginPaint(hwnd, &ps); //BeginPaint()EndPaint()这一对调用将激活窗口,并使用存储在Windows类中变量hbrBackground填充背景
			EndPaint(hwnd, &ps);
			return 0;
		} break;
		case WM_DESTROY: {//用户关闭窗口时调用,而不是应用程序,应用程序继续运行
			PostQuitMessage(0);//通知windows终止应用程序
			return 0;
		} break;
		default:
			break;
	}
	return DefWindowProc(hwnd, msg, wParam, lParam);
}

/*
#define WINAPI __stdcall
#define CALLBACK __stdcall
__stdcall: 函数参数按照从右到左的顺序入栈,被调用的函数在返回前清理传送参数的栈,函数参数个数固定。
__cdecl: C/C++和MFC程序默认使用的调用约定,也可以在函数声明时加上__cdecl关键字来手工指定。采用__cdecl约定时,函数参数按照从右到左的顺序入栈,并且由调用函数者把参数弹出栈以清理堆栈。
WINAPI声明符: 一般用于修饰动态链接库中导出函数 3. CALLBACK仅用于修饰回调函数
*/
int WINAPI WinMain(HINSTANCE hinstance, /*windows为应用程序生成的实例句柄。实例是一个指针或一个数。 本例中hinstance用来跟踪应用程序*/
	HINSTANCE hprevinstance,/*用来跟踪应用程序以前的实例,目前不再使用,微软要去除它*/
	LPSTR lpcmdline,//空值终止字符串
	int ncmdshow) {//启动过程中被传递给应用程序,带有如何打开主应用程序窗口的信息。这样用户可以有些控制程序如何启动的能力,可以在函数ShowWindow()中使用

	WNDCLASSEX winclass = { 0 };
	winclass.cbSize = sizeof(winclass);
	winclass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
	winclass.lpfnWndProc = WindowProc;
	winclass.cbClsExtra = 0;
	winclass.cbWndExtra = 0;
	winclass.hInstance = hinstance;
	winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	winclass.hCursor = LoadCursorA(NULL, IDC_ARROW);
	winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	winclass.lpszMenuName = NULL;
	winclass.lpszClassName = "WINCLASS1";//每个window类代表我们的应用程序所创建的不同的窗口类型,windows需要一些途径跟踪识别它们,lpszClassName就是用于此目的,
	winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

	if (!RegisterClassEx(&winclass)) {//注册一个拓展的窗口类,将新类通知给windows
		return 0;
	};

	HWND hwnd;
	//返回新建窗口句柄,失败了返回null
	if (!(hwnd = CreateWindowEx(NULL, "WINCLASS1", "My First Window",
		WS_OVERLAPPEDWINDOW | WS_VISIBLE,//WS_VISIBLE 自动显示的类型标识符
		0, 0,//窗口左上角位置
		400, 400,
		NULL,//假如存在父窗口,指向父窗口句柄
		LoadMenu(hinstance, MAKEINTRESOURCE(IDR_MENU1)),//指向附属该窗口菜单的句柄
		hinstance,//应用程序实例
		NULL))
		) {
		return 0;
	}

	ShowWindow(hwnd, ncmdshow);//如果没有添加WS_VISIBLE标识符,手动显示
	UpdateWindow(hwnd);//更新窗口内容,并且产生一个WM_PAINT信息

	MSG msg;
	//while (GetMessage(&msg, NULL, 0, 0)) {
	//	TranslateMessage(&msg);
	//	DispatchMessage(&msg);//指出所有操作发生的位置,调用WinProc进一步处理
	//}

	while (TRUE) {
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
			if (msg.message == WM_QUIT) {
				break;
			}

			TranslateMessage(&msg);
			DispatchMessage(&msg);//消息发送给Window Procedure
		}
	}

	return 0;
}

参考:https://blog.csdn.net/nullccc/article/details/81352470

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值