当前位置: 首页 > article >正文

游戏引擎学习第二天

视频参考:https://www.bilibili.com/video/BV1C2miYPEQf/

WNDCLASSA

https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-wndclassa
在这里插入图片描述

在 C 语言中然后使用时,需要加上 struct 关键字:
为了让代码更加简洁,C 语言引入了 typedef,
允许我们为结构体类型定义一个别名,
这样就不需要每次都写 struct 关键字了:
// 使用时不再需要 struct 关键字
WNDCLASSA wc; // 直接使用别名

在这里插入图片描述

WNDCLASS WindowClass = {}; 是标准的 零初始化,将所有成员初始化为其类型的默认值(通常是 0 或 nullptr)。
WNDCLASS WindowClass = {0}; 将结构体的第一个成员初始化为 0,并且其他成员通常会被零初始化。

CS_CLASSDCCS_OWNDC 是 Windows API 中 WNDCLASS 结构体的 style 成员的两个标志位,用来指定窗口类的设备上下文 (DC) 行为。

标志描述设备上下文类型
CS_CLASSDC所有窗口共享一个设备上下文 (DC)共享 DC
CS_OWNDC每个窗口都有自己的设备上下文 (DC)独立 DC
  • CS_CLASSDC 适合需要共享设备上下文的情况。
  • CS_OWNDC 适合需要每个窗口独立绘制的情况。

MainWindowCallback 函数是一个 窗口过程函数(Window Procedure),在 Windows 程序中,它用于处理与窗口相关的消息。
每当窗口接收到消息时(如用户输入、窗口大小变化、系统事件等),该函数就会被调用来处理这些消息。
在这里插入图片描述

在这里插入图片描述

处理窗体消息

// game.cpp : Defines the entry point for the application.
//

#include <windows.h>
LRESULT CALLBACK
MainWindowCallback(HWND hwnd, // 窗口句柄,表示消息来源的窗口
                   UINT Message, // 消息标识符,表示当前接收到的消息类型
                   WPARAM wParam, // 与消息相关的附加信息,取决于消息类型
                   LPARAM LParam) { // 与消息相关的附加信息,取决于消息类型
  LRESULT Result; // 定义一个变量来存储消息处理的结果

  switch (Message) {                 // 根据消息类型进行不同的处理
  case WM_SIZE: {                    // 窗口大小发生变化时的消息
    OutputDebugStringA("WM_SIZE\n"); // 输出调试信息,表示窗口大小已改变
  } break;

  case WM_DESTROY: {                    // 窗口销毁时的消息
    OutputDebugStringA("WM_DESTROY\n"); // 输出调试信息,表示窗口正在销毁
  } break;

  case WM_CLOSE: {                    // 窗口关闭时的消息
    OutputDebugStringA("WM_CLOSE\n"); // 输出调试信息,表示窗口正在关闭
  } break;

  case WM_ACTIVATEAPP: { // 应用程序激活或失去焦点时的消息
    OutputDebugStringA(
        "WM_ACTIVATEAPP\n"); // 输出调试信息,表示应用程序激活或失去焦点
  } break;

  default: { // 对于不处理的消息,调用默认的窗口过程
    Result = DefWindowProc(hwnd, Message, wParam,
                           LParam); // 调用默认窗口过程处理消息
  } break;
  }

  return Result; // 返回处理结果
}

int CALLBACK WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, //
                     PSTR cmdline, int cmdshow) {
  WNDCLASS WindowClass = {};
  // 使用大括号初始化,所有成员都被初始化为零(0)或 nullptr

  // WindowClass.style:表示窗口类的样式。通常设置为一些 Windows
  // 窗口样式标志(例如 CS_HREDRAW, CS_VREDRAW)。
  WindowClass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
  // CS_HREDRAW 当窗口的宽度发生变化时,窗口会被重绘。
  // CS_VREDRAW 当窗口的高度发生变化时,窗口会被重绘

  //  WindowClass.lpfnWndProc:指向窗口过程函数的指针,窗口过程用于处理与窗口相关的消息。
  WindowClass.lpfnWndProc = MainWindowCallback;

  // WindowClass.hInstance:指定当前应用程序的实例句柄,Windows
  // 应用程序必须有一个实例句柄。
  WindowClass.hInstance = hInst;

  // WindowClass.lpszClassName:指定窗口类的名称,通常用于创建窗口时注册该类。
  WindowClass.lpszClassName = "gameWindowClass"; // 类名

  return 0;
}

注册窗口

在这里插入图片描述

注册窗口 成功后创建窗口

if (RegisterClass(&WindowClass)) {  // 如果窗口类注册成功
    HWND WindowHandle = CreateWindowEx(0,                                // 创建窗口,使用扩展窗口风格
                                       WindowClass.lpszClassName,        // 窗口类的名称,指向已注册的窗口类
                                       "game",                           // 窗口标题(窗口的名称)
                                       WS_OVERLAPPEDWINDOW | WS_VISIBLE, // 窗口样式:重叠窗口(带有菜单、边框等)并且可见
                                       CW_USEDEFAULT,                    // 窗口的初始位置:使用默认位置(X坐标)
                                       CW_USEDEFAULT,                    // 窗口的初始位置:使用默认位置(Y坐标)
                                       CW_USEDEFAULT,                    // 窗口的初始宽度:使用默认宽度
                                       CW_USEDEFAULT,                    // 窗口的初始高度:使用默认高度
                                       0,                                // 父窗口句柄(此处无父窗口,传0)
                                       0,                                // 菜单句柄(此处没有菜单,传0)
                                       hInst,                            // 当前应用程序的实例句柄
                                       0                                 // 额外的创建参数(此处没有传递额外参数)
    );
    // 如果窗口创建成功,WindowHandle 将保存窗口的句柄
} else {  // 如果窗口类注册失败
    // 这里可以处理注册失败的逻辑
    // 比如输出错误信息,或退出程序等
}

如果窗口创建成功,启动一个无限循环,等待和处理消息

// 如果窗口创建成功,WindowHandle 将保存窗口的句柄
if (WindowHandle) {  // 检查窗口句柄是否有效,若有效则进入消息循环
    for (;;) {  // 启动一个无限循环,等待和处理消息
        MSG Message;  // 声明一个 MSG 结构体,用于接收消息
        BOOL MessageResult = GetMessage(&Message, // 获取下一个消息
                                        0,        // 目标窗口句柄,0表示从所有窗口获取消息
                                        0,        // 获取所有消息
                                        0);       // 获取所有消息

        if (MessageResult > 0) {  // 如果返回值大于 0,表示成功获取到消息
            TranslateMessage(&Message);  // 翻译消息,如果是键盘消息需要翻译
            DispatchMessage(&Message);   // 分派消息,调用窗口过程处理消息
        } else {  // 如果返回值为 0 或 -1,表示没有更多消息或发生了错误
            break;  // 跳出循环,结束消息循环
        }
    }
} else {  // 如果窗口创建失败
    // 这里可以处理窗口创建失败的逻辑
    // 比如输出错误信息,或退出程序等
}

至此windows窗口创建成功
alt text
现在窗口不能关闭,能输出WM_SIZE,WM_ACTIVATEAPP 消息

绘制

  case WM_PAINT: { // 处理 WM_PAINT 消息,通常在窗口需要重新绘制时触发
    PAINTSTRUCT Paint; // 定义一个 PAINTSTRUCT 结构体,保存绘制的信息
    // 调用 BeginPaint 开始绘制,并获取设备上下文 (HDC),同时填充 Paint 结构体
    HDC DeviceContext = BeginPaint(hwnd, &Paint);

    // 获取当前绘制区域的左上角坐标
    int x = Paint.rcPaint.left;
    int y = Paint.rcPaint.top;

    // 计算绘制区域的宽度和高度
    int Height = Paint.rcPaint.bottom - Paint.rcPaint.top;
    int Width = Paint.rcPaint.right - Paint.rcPaint.left;
    // 这里的宽度计算是错误的,应该是右边减去左边

    // 使用 WHITENESS 操作符填充矩形区域为白色
    PatBlt(DeviceContext, x, y, Width, Height, WHITENESS);

    // 调用 EndPaint 结束绘制,并释放设备上下文
    EndPaint(hwnd, &Paint);
  } break;
PAINTSTRUCT 主要在 窗口绘制(painting) 过程中使用,特别是当窗口的部分区域需要重绘时(例如窗口被覆盖后再恢复)。BeginPaint 和 EndPaint 函数通常会使用 PAINTSTRUCT 来获取绘制所需的上下文信息。
typedef struct tagPAINTSTRUCT {
    HDC         hdc;            // 设备上下文句柄,用于绘制窗口内容
    BOOL        fErase;         // 是否清除背景,TRUE表示清除,FALSE表示不清除
    RECT        rcPaint;        // 描述要更新的区域(矩形区域),窗口内容被绘制到该区域
    BOOL        fRestore;       // 是否恢复被擦除区域的内容,通常为 TRUE 时表示恢复
    BOOL        fIncUpdate;     // 是否为增量更新(更新的区域是变化部分)
    BYTE        rgbReserved[32]; // 保留字段,用于扩展结构体,通常不使用
} PAINTSTRUCT, *PPAINTSTRUCT, *NPPAINTSTRUCT, *LPPAINTSTRUCT;

//PatBlt 函数是 Windows 图形设备接口(GDI)的一部分,用于执行图形绘制操作,具体是填充矩形区域,且操作可以基于位图操作符(ROP)。以下是对 PatBlt 函数的详细解释:

WINGDIAPI BOOL WINAPI PatBlt(
    _In_ HDC hdc,   // 设备上下文句柄
    _In_ int x,     // 矩形区域的左上角 x 坐标
    _In_ int y,     // 矩形区域的左上角 y 坐标
    _In_ int w,     // 矩形的宽度
    _In_ int h,     // 矩形的高度
    _In_ DWORD rop  // 位图操作符
);

如果PatBlt 编译未定义链接Gdi32.lib

# 链接 User32.lib 库
target_link_libraries(game PRIVATE User32.lib Gdi32.lib)

设置填充颜色白色和黑色来回变换在刷新窗口的时候

static DWORD Operation = WHITENESS;

// 使用 WHITENESS 操作符填充矩形区域为白色
PatBlt(DeviceContext, x, y, Width, Height, Operation);
if (Operation == WHITENESS) {
    Operation = BLACKNESS;
} else {
    Operation = WHITENESS;
}

http://www.kler.cn/a/395278.html

相关文章:

  • Mac 使用mac 原生工具将mp4视频文件提取其中的 mp3 音频文件
  • ChatGPT登录失败的潜在原因分析
  • Mysql篇-三大日志
  • 网络技术-网桥模式
  • sql专题 之 where和join on
  • MaxKB
  • 深入理解 Spring Boot 中的 Starters
  • vue3+ant design vue实现日期等选择器点击右上角叉号默认将值变为null,此时会影响查询等操作~
  • 【C++】隐含的“This指针“
  • GIT将源码推送新分支
  • 第十四章 Spring之假如让你来写AOP——雏形篇
  • 二分查找--快速地将搜索空间减半
  • 大语言模型在序列推荐中的应用
  • MinIo在Ubantu和Java中的整合
  • 某军工变压器企业:通过集团级工业IOT平台,实现数字化转型
  • yakit远程连接(引擎部署在vps上)
  • PyAEDT:Ansys Electronics Desktop API 简介
  • Apache Doris:快速入门与实践
  • word转markdown的方法(pandoc)
  • 2024 年 10 月公链行业研报:比特币引领市场,Layer 2 竞争加剧
  • 如何在Mac上切换到JDK 17开发环境
  • windows C#-创建记录类型(上)
  • 高性能分布式缓存Redis-分布式锁与布隆过滤器
  • Python →爬虫实践
  • 如何在CentOS 7上搭建SMB服务
  • AviEar:一种基于物联网的低功耗鸟类声学监测解决方案