《WINDOWS游戏编程之从零开始》第三章学习笔记
2022/2/4 7:12:30
本文主要是介绍《WINDOWS游戏编程之从零开始》第三章学习笔记,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
个人整理的笔记,比较杂乱,可能并不是很适合阅读:)
-
MessageBox 函数
其四个参数分别为:
HWND 类型的 hWnd, 表示窗口句柄;
HWND 是什么类型?简单说就是给窗口分配的句柄。(废话啊啊啊)总之就用其代指一个窗口
LPCTSTR 类型的 lpText,表示消息内容;
LPCTSTR 类型的 lpCaption,表示消息框标题内容;
UINT 类型的 uType,表示消息窗口的样式
-
PlaySound 函数
其三个参数分别为:
LPCTSTR 类型的 pszSound,指定声音源;
HMODULE 类型的 hmod,资源可执行文件的句柄(暂时不清楚是个什么句柄)
DOWRD 类型的 fdwSound,控制声音播放. 一些常用的标识:
模仿示例程序时的坑
注意 Visual Studio 中要改项目属性,保证链接器子系统设置为 Windows 不要设置为 Console,这样才是一个 Windows 文件。否则 WinMain 不会正确运行
(使用 Console 当然可以通过控制台加载出一样的效果,但是调试和运行都会多一个控制台,当然是客户端不能需要的东西)
例如,MessageBox 的 uType 设为 0,就会加载默认的窗口样式:
3.6
-
MSG结构体
消息用MSG表示.
-
消息队列.
3.7
窗口创建四部曲:
-
窗口类的设计
-
窗口类的注册
-
窗口类的正式创建
-
窗口的显示与更新
- 窗口设计
Windows 中控制窗口特征的结构体就两个, WNDCLASS 与 WNDCLASSEX,我们应当使用EX(更(geng第四声)新)。
所谓设计,其实就是在结构体里“做填空题”,定好参数。
- 窗口注册
在设计好窗口后,还需要调用 RegisterClassEx 对其进行注册。注册成功后才可以创建该类型的窗口。
不过这是啥原因?不知道注册这一步的意义是什么。应该是把固定参数列表的窗口对应到一个具体的窗口名吧
- 窗口创建
调用
AdujstWindowRect()
函数来根据尺寸和风格计算窗口尺寸。设计、注册都完成了之后,就可以调用
CreateWindow
函数来创建设计好的窗口了。一共11个参数(我的天):
(1)LPCTSTR 类的窗口类名称 lpClassName,填写我们设定并注册好的窗口类名。(2)LPCTSTR 类的窗口名字 lpWindowName,就是显示在窗口最上方的名字。
(3)DOWRD 类的窗口样式 dwStyle。有无标题栏、带系统菜单、最小化最大化这些等等…
(4)x. 一般设定为CW_USEDEFAULT
(5)y. 设定为CW_USEDEFAULT
(6)int 型的 nWidth,指定窗口宽度.
(7)int 型的 hHeight,指定窗口高度.
(8)HWND 类的 hWndParent,指定被创建窗口的父窗口句柄。一般设置为 NULL, 没有父窗口
(9)HMENU 类的 hMenu,指定窗口菜单的资源句柄。没有菜单时当然也可以设置为 NULL.
(10)HINSTANCE 类的 hInstance. 和 WinMain 一样。指定应用程序实例的句柄。
(11)lpParam,WM_CREATE 消息的附加参数 lParam 传入的数据指针(暂时不懂)。
- 窗口的显示与更新
(1)改变窗口大小
BOOL WINAPI MoveWindow()
等等,为什么这里的布尔类是大写的?
C++基础----C++ 布尔类型(bool)及BOOL和bool的区别_qiaoxinyu1989的博客-CSDN博客_bool类型
原来,BOOL 类是微软的 VC++ 自己写的宏定义:
typedef int BOOL
这个 BOOL 是三值逻辑,1 为 TRUE,0 为 FALSE,-1为 ERROR.
总之 BOOL 实际上是整型啦,其通过与0的比较来返回其三值逻辑。
(2)显示窗口
ShowWindow(HWND hWnd, int nCmdShow)
第一个就是要显示的窗口,第二个可以直接取 WinMain 中的 nCmdShow (指定窗口该如何显示).
(3)更新窗口
UpdateWindow(HWND hWnd)
发送一个 WM_PAINT 到消息队列,进入窗口过程函数, 对窗口进行更新。
貌似和重画操作不同?肯定不同吧。是窗口的更新。
3.8 消息循环体系
消息循环体系…是啥啊
-
GetMessage 消息循环体系
其实是一个函数,其作用是接收消息。
注意,GetMessage 函数是有返回值的。当收到非 WM_QUIT 消息时,其会返回1,如果出现错误,返回-1,收到 WM_QUIT 消息时返回0.
所以,核心其实就是:
MSG msg = ... while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); }
-
PeekMessage 消息循环体系
更常用一点.
其多了一个参数 wRemoveMsg. 这个参数指定消息的获取方式(这又是啥)
一个使用 PeekMessage 循环体系的案例:
MSG msg = { 0 }; while (msg.message != WM_QUIT) { if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { Direct3D_Update(hwnd); Direct3D_Render(hwnd); } }
二者区别: PeekMessage 体系在没有消息时会继续进行其他的渲染和更新,而 GetMessage 体系则会一直等到消息出现才会进行其他操作。
3.9 窗口过程函数
窗口过程函数,用于处理消息。
典型的过程函数是通过一个 switch 语句,switch 变量 message 的具体内容来进行相应的操作。
default 状态通常会调用一个默认的
DefWindowProc
过程函数。3.10 窗口类注销
已经迫不及待要制作一个完整的窗口程序了(这些内容也是附加的)
注销操作并不是必须的,但为了程序稳定最好加上(万一出现意料之外的问题呢)
原型:
BOOL WINAPI UnregisterClass( _In_ LPCSTR lpClassName, _In_opt_ HISTANCE hInstance );
参数分别是注销的类名称以及类的应用程序的实例句柄。
3.11
照着写的代码,贴出的与书中不同,有一些修改和自己的理解,注释中给出了.
//-------------------【程序说明】------------------- // 程序名称:GameCore // Learn from 浅墨 orz // 2022 年 2 月 Created by Eke // 描述:跟着浅墨一起学做一个最简单的Windows窗口程序! //-------------------------------------------------- //-----------------【头文件部分】--------------------- // 描述:程序依赖的头文件 //-------------------------------------------------- #include <Windows.h> //-----------------【宏定义部分】-------------------- // 描述:定义辅助宏 //-------------------------------------------------- #define WINDOW_WIDTH 800 #define WINDOW_HEIGHT 600 constexpr auto WINDOW_TITLE = L"准备好,我来帮你了朋友!"; // 新版本中使用constexpr比define更安全. //----------------【全局函数声明部分】---------------- // 描述:全局函数声明. // 上为窗口过程函数 //-------------------------------------------------- LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); //----------------【WinMain( )函数】----------------- // 描述:程序主入口 //-------------------------------------------------- int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow) // 需要将 _In_, _In_opt_ 依照函数原型加上,否则会报警告. 为啥呢? { // 四部曲 // 1. Design (Oh 11 paras!) WNDCLASSEX wndClass = { 0 }; // 定义一个窗口类 wndClass.cbSize = sizeof(WNDCLASSEX); wndClass.style = CS_HREDRAW | CS_VREDRAW; wndClass.lpfnWndProc = WndProc; wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hInstance = hInstance; wndClass.hIcon = (HICON)::LoadImage(NULL, L"favicon.ico", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE); wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); // 试了下没有RED\BLUE 的brush,qwq wndClass.lpszMenuName = NULL; wndClass.lpszClassName = L"ForTheDreamOfGameDevelop"; // 2. Register if (!RegisterClassEx(&wndClass)) return -1; // 3. Create HWND hwnd = CreateWindow(L"ForTheDreamOfGameDevelop", WINDOW_TITLE, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT, NULL, NULL, hInstance, NULL); // 4. Move, show and update MoveWindow(hwnd, 250, 80, WINDOW_WIDTH, WINDOW_HEIGHT, true); ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); // 5. msg loop MSG msg = { 0 }; while (msg.message != WM_QUIT); { if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } } // 6. unregister UnregisterClass(L"ForTheDreamOfGameDevelop", wndClass.hInstance); return 0; } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_PAINT: ValidateRect(hwnd, NULL); break; case WM_KEYDOWN: if (wParam == VK_ESCAPE) DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, message, wParam, lParam); } return 0; }
运行效果:
总之就是一个很简单的窗体啦!
总结
第一次以笔记的形式把学习的东西记录下来。之前学过一些东西,总因为后来很久没接触逐渐忘了,重新学又需要整理很多资料重新看,不妨将学习过程写成笔记,方便将很久没用的知识捡回来,也能更好地综合我的学习内容。
这篇关于《WINDOWS游戏编程之从零开始》第三章学习笔记的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-05-15鸿蒙生态设备数量超8亿台
- 2024-05-13TiDB + ES:转转业财系统亿级数据存储优化实践
- 2024-05-09“2024鸿蒙零基础快速实战-仿抖音App开发(ArkTS版)”实战课程已上线
- 2024-05-09聊聊如何通过arthas-tunnel-server来远程管理所有需要arthas监控的应用
- 2024-05-09log4j2这么配就对了
- 2024-05-09nginx修改Content-Type
- 2024-05-09Redis多数据源,看这篇就够了
- 2024-05-09Google Chrome驱动程序 124.0.6367.62(正式版本)去哪下载?
- 2024-05-09有没有大佬知道这种数据应该怎么抓取呀?
- 2024-05-09这种运行结果里的10.100000001,怎么能最快改成10.1?