C++ OpenGL 3D GameTutorial 1:Making the window with win32 API学习笔记


视频地址icon-default.png?t=N7T8https://www.youtube.com/watch?v=jHcz22MDPeE&list=PLv8DnRaQOs5-MR-zbP1QUdq5FL0FWqVzg

 一、入口函数

         首先看入口函数main代码:

#include<OGL3D/Game/OGame.h>int main()
{OGame game;game.Run();return 0;
}

        这里交代个关于C++语法的问题,这里OGame game;这行语句实际上是已经构造了一个OGame对象,并且名字叫game,如果想要想C#里面一样使用new关键字的写法的话,应该是这样的:

OGame* game = new OGame();
game->Run();

        是不是应该可以这样理解,new关键字实际上是新开辟了一个内存的意思,返回的是这块内存的指针,所以实际上是把值赋给了OGame*这个指向OGame类的指针。

        C#里面的new应该也是一个意思,但是写法上让开发者以为是赋给了一个对象,而不是一个指针,嗯,应该是这样吧。

 二、OGame类

        先贴代码:

        OGame.h

#pragma once
#include<memory>class OWindow;
class OGame
{
public:OGame();~OGame();void Run();void Quit();
protected:bool m_isRunning = true;std::unique_ptr<OWindow> m_display;
};

         OGame.cpp

#include<OGL3D/Game/OGame.h>
#include<OGL3D/Window/OWindow.h>
#include<Windows.h>OGame::OGame()
{m_display = std::unique_ptr<OWindow>(new OWindow());
}OGame::~OGame()
{
}void OGame::Run()
{MSG msg;while (m_isRunning && !m_display->isClosed()){if (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE)){TranslateMessage(&msg);DispatchMessage(&msg);}Sleep(1);}
}void OGame::Quit()
{m_isRunning = false;
}

        先看一下std::unique_ptr智能指针:

std::unique_ptr<OWindow> m_display;

        这行代码定义了一个名称为m_display的指向OWindow类型对象的智能指针,需要

#include<memory>;

        据说这东西能智能释放内存,呵呵,先这么理解吧,将来看效果。

        与PeekMessage类似的还有一个GetMessage函数,两者的不同在于在没有消息返回的情况下,PeekMessage会返回一个空值,而GetMessage会让程序休眠。还有就是GetMessage在从消息队列中取出消息后,一定会删除消息,但是PeekMessage可以通过最后参数来决定是否移除消息。GetMessage理解为“拿走”了消息,PeekMessage理解为“偷看”了消息,不一定“拿走”。我们这里把PeekMessage的最后一个参数设置为PM_REMOVE,就是“拿走”了的情形。

        TranslateMessage函数是用来把键盘消息转换为字符消息,并将转换后的新消息重新投递到调用线程的消息队列中。

        比如说当我们敲击键盘上的某个字符键时,系统将产生WM_KEYDOWN和WM_KEYUP消息。这两个消息的附加参数( wParam和 lParam)包含的是 虚拟键代码和扫描码等信息,而 我们在程序中往往需要得到某个字符的ASCII码,TranslateMessage这个函数就可以将WM_KEYDOWN和WM_ KEYUP消息的组合转换为一条WM_CHAR消息(该消息的wParam附加参数包含了字符的ASCII码),并将转换后的新消息投递到调用线程的消息队列中。注意,TranslateMessage函数并不会修改原有的消息。

        DispatchMessage这网上说得比较复杂,看着头大,我的理解是这个函数把消息发送给了窗口对象中lpfnWndProc属性所对应的函数,具体得分发机制慢慢研究,不过咱这程序里面就一个窗口,想发错了都没机会,没啥好说的。

三、OWindow类

        先贴代码:

        OWindow.h

#include<Windows.h>
class OWindow
{
public:OWindow();~OWindow();void OnDestroy();bool isClosed();
private:HWND m_handle = nullptr;
};

        OWindow.cpp

#include<OGL3D/Window/OWindow.h>
#include <Windows.h>
#include<assert.h>LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{switch (msg){case WM_DESTROY:{OWindow* window = (OWindow*)GetWindowLongPtr(hwnd, GWLP_USERDATA);window->OnDestroy();break;}default:return DefWindowProc(hwnd, msg, wParam, lParam);}return NULL;
}OWindow::OWindow()
{WNDCLASSEX wc = {};wc.cbSize = sizeof(WNDCLASSEX);wc.lpszClassName = L"OGL3DWindow";wc.lpfnWndProc = WndProc;assert(RegisterClassEx(&wc));RECT rc = { 0,0,1024,768 };AdjustWindowRect(&rc, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU, false);m_handle = CreateWindowEx(NULL, L"OGL3DWindow", L"Parcode | OpenGL 3D Game", WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU, CW_USEDEFAULT, CW_USEDEFAULT,rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, NULL, NULL);assert(m_handle);SetWindowLongPtr(m_handle, GWLP_USERDATA, (LONG_PTR)this);ShowWindow(m_handle, SW_SHOW);UpdateWindow(m_handle);
}OWindow::~OWindow()
{DestroyWindow(m_handle);
}void OWindow::OnDestroy()
{m_handle = nullptr;
}bool OWindow::isClosed()
{return !m_handle;
}

        字符串前面为什么加L?表示奖ANSI字符串转换成unicode字符串,这样每个字符占用两个字节。

        RegisterClassEx这个似乎就是用来注册窗口用的,大概就是将窗口的指针添加到一个列表里面,以方便遍历查找吧。RegisterClassEx依据编译环境来决定替换为RegisterClassExA或者RegisterClassExW。如果使用RegisterClassExA来注册窗口类,应用程序通知系统被注册类的窗回的消息使用ANSI字符集的文本和字符参数;如果使用RegisterClassExW来注册窗口类,应用程序需要系统以Unicode来传递消息的文本参数。也就是是在当前的环境下RegisterClassEx应该是等同于RegisterClassExW,这样要求消息字符串必须是unicode字符串,这就看出来前面说的消息字符串前面加字母L的必要性。

        SetWindowLongPtr函数用来设置一个窗口的扩展风格或者额外数据。这个函数兼容32位和64位版本的Windows系统。这里是把指向OWindow对象的指针转化为LONG_PRT类型并保存在窗口数据偏移了GWLP_USERDATA这个位置。好吧,不是很理解,总之指向OWindow对象的指针被保存了,将来需要的时候能取出来,并以此来访问到OWindow对象就是了。我们可以从WinProc方法里面看到对应于SetWindowLongPtr函数的GetWindowLongPtr函数是如何取值并调用方法的:

OWindow* window = (OWindow*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
window->OnDestroy();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/232031.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Swift爬虫使用代理IP采集唯品会商品详情

目录 一、准备工作 二、代理IP的选择与使用 三、使用Swift编写唯品会商品爬虫 四、数据解析与处理 五、注意事项与优化建议 六、总结 一、准备工作 在开始编写爬虫之前&#xff0c;需要准备一些工具和库&#xff0c;以确保数据抓取的顺利进行。以下是所需的工具和库&…

spring Security源码讲解-WebSecurityConfigurerAdapter

使用security我们最常见的代码&#xff1a; Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter {Overrideprotected void configure(HttpSecurity http) throws Exception {http.formLogin().permitAll();http.authorizeRequests().antMatcher…

虚幻UE 材质-边界混合之PDO像素深度偏移量

2024年的第一天&#xff01;&#xff01;&#xff01;大家新年快乐&#xff01;&#xff01;&#xff01; 可能是长大了才知道 当你过得一般 你的亲朋好友对你真正态度只可能是没有表露出来的冷嘲热讽了 希望大家新的一年平安、幸福、 永远活力满满地追求自己所想做的、爱做的&…

​三子棋(c语言)

前言&#xff1a; 三子棋是一种民间传统游戏&#xff0c;又叫九宫棋、圈圈叉叉棋、一条龙、井字棋等。游戏规则是双方对战&#xff0c;双方依次在9宫格棋盘上摆放棋子&#xff0c;率先将自己的三个棋子走成一条线就视为胜利。但因棋盘太小&#xff0c;三子棋在很多时候会出现和…

集合基础知识点

集合基础 1. 集合的由来 当 Java 程序中需要存放数据的时候&#xff0c;通常会定义变量来实现数据的存储&#xff0c;但是&#xff0c;当需要存储大量数据的时候该怎么办呢&#xff1f;这时首先想到的是数组&#xff0c;但是&#xff01;数组只能存放同一类型的数据&#xff…

Linux 编译安装 Nginx

目录 一、前言二、四种安装方式介绍三、本文安装方式&#xff1a;源码安装3.1、安装依赖库3.2、开始安装 Nginx3.3、Nginx 相关操作3.4、把 Nginx 注册成系统服务 四、结尾 一、前言 Nginx 是一款轻量级的 Web 服务器、[反向代理]服务器&#xff0c;由于它的内存占用少&#xf…

RabbitMQ(七)ACK 消息确认机制

目录 一、简介1.1 背景1.2 定义1.3 如何查看确认/未确认的消息数&#xff1f; 二、消息确认机制的分类2.1 消息发送确认1&#xff09;ConfirmCallback方法2&#xff09;ReturnCallback方法3&#xff09;代码实现方式一&#xff1a;统一配置a.配置类a.生产者c.消费者d.测试结果 …

淘宝京东1688商品详情API接口,搜索商品列表接口

前言 在实际工作中&#xff0c;我们需要经常跟第三方平台打交道&#xff0c;可能会对接第三方平台API接口&#xff0c;或者提供API接口给第三方平台调用。 那么问题来了&#xff0c;如果设计一个优雅的API接口&#xff0c;能够满足&#xff1a;安全性、可重复调用、稳定性、好…

嵌入式-C语言-ASCII码(字符)转换二进制和十六进制

一&#xff1a;ASCII码是什么&#xff1f; 问&#xff1a;ASCII码是什么&#xff1f; 答&#xff1a;ASCII码&#xff08;American Standard Code for Information Interchange&#xff0c;美国信息交换标准代码&#xff09;是一种用于表示字符的标准编码系统。它使用7位或8位…

poium测试库之JavaScript API封装原理

为什么要封装JavaScript的API&#xff1f; 因为有些场景下Selenium提供的API并不能满足我们需求。比如&#xff0c;滑动浏览滚动条&#xff0c;控制元素的显示/隐藏&#xff0c;日历控件的操作等&#xff0c;都可以通过JavaScrip实现&#xff0c;而且Selenium为我们提供了 exe…

C#之反编译之路(一)

本文将介绍微软反编译神器dnSpy的使用方法 c#反编译之路(一) dnSpy.exe区分64位和32位,所以32位的程序,就用32位的反编译工具打开,64位的程序,就用64位的反编译工具打开(个人觉得32位的程序偏多,如果不知道是32位还是64位,就先用32位的打开试试) 目前只接触到wpf和winform的桌…

leetcode——杨辉三角

https://leetcode.cn/problems/pascals-triangle/ 杨辉三角&#xff1a; 给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 核心思想&#xff1a;找出杨辉三角的规律&#xff0c;发…

实验笔记之——服务器链接

最近需要做NeRF相关的开发,需要用到GPU,本博文记录本人配置服务器远程链接的过程,本博文仅供本人学习记录用~ 连上服务器 首先先确保环境是HKU的网络环境(HKU AnyConnect也可)。伙伴已经帮忙创建好用户(第一次登录会提示重新设置密码)。用cmd ssh链接ssh -p 60001 <u…

window服务器thinkphp队列监听服务

经常使用linux的同学们应该对使用宝塔来做队列监听一定非常熟悉&#xff0c;但对于windows系统下&#xff0c;如何去做队列的监听&#xff1f;是一个很麻烦的事情。 本文将通过windows系统的服务来实现队列的监听。 对于thinkphp6 queue如何使用&#xff0c;不再赘述。其它系…

【总线接口】1.以Xilinx开发板为例,直观的认识硬件板卡和接口

初接触硬件&#xff0c;五花八门的总线、接口一定会让你有些疑惑&#xff0c;我尝试用一系列文章来解开你的疑惑 系列文章 【总线接口】1.以Xilinx开发板为例&#xff0c;直观的认识硬件接口 【总线接口】2.学习硬件这些年接触过的硬件接口、总线 大汇总 【总线接口】…

uniapp:签字版、绘画板 插件l-signature

官方网站&#xff1a;LimeUi - 多端uniapp组件库 使用步骤&#xff1a; 1、首先从插件市场将代码下载到项目 海报画板 - DCloud 插件市场 2、下载后&#xff0c;在项目中的uni_modules目录&#xff08;uni_modules优点&#xff1a;不需要import引入&#xff0c;还可以快捷更新…

论文阅读:基于MCMC的能量模型最大似然学习剖析

On the Anatomy of MCMC-Based Maximum Likelihood Learning of Energy-Based Models 相关代码&#xff1a;点击 本文只介绍关于MCMC训练的部分&#xff0c;由此可知&#xff0c;MCMC常常被用于训练EBM。最后一张图源于Implicit Generation and Modeling with Energy-Based Mod…

小红书 X WSDM 2024「对话式多文档问答挑战赛」火热开赛!

基于大语言模型&#xff08;LLM&#xff09;的对话问答机器人&#xff0c;已经成为当前人工智能领域学术界和工业界共同关注的的热门研究方向之一。在对话过程中&#xff0c;为大模型引入搜索结果&#xff0c;进行检索增强的生成&#xff08;Retrieval Augmented Generation&am…

MyBatis-Plus框架学习笔记

先赞后看&#xff0c;养成习惯&#xff01;&#xff01;&#xff01;❤️ ❤️ ❤️ 文章码字不易&#xff0c;如果喜欢可以关注我哦&#xff01; ​如果本篇内容对你有所启发&#xff0c;欢迎访问我的个人博客了解更多内容&#xff1a;链接地址 MyBatisPlus &#xff08;简称…