【OpenGL】GLFW环境配置 + 扩展GLFW使其可以成为MFC子窗口

devtools/2024/11/23 23:08:06/

文章目录

  • OpenGL环境配置
  • GLFW配置
  • GLFW创建窗口
  • 扩展GLFW使其可以成为MFC子窗口
  • MFC中使用GLFW


现代OpenGL项目推荐使用GLFW + GLAD来配置使用OpenGL。配置环境:

  • VS2017
  • glfw-3.4
  • glad-opengl4.6-core

OpenGL环境配置

opengl32.lib已经包含在Microsoft SDK里了,它在Visual Studio安装的时候就默认安装了。将opengl32.lib添加进链接器设置里即可。

GLFW配置

下载源码 -> CMake生成VS2017项目 -> 编译生成glfw3.lib
在这里插入图片描述
将源码中的include/GLFW目录和生成的glfw3.lib添加进VS工程属性Linker(链接器)选项卡里的Input(输入)选项卡中。

#include <GLFW/glfw3.h>

GLFW创建窗口

	glfwInit();glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endifGLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpengl", NULL, NULL);if (window == NULL) {std::cout << "Failed to create CLFW window" << std::endl;glfwTerminate();return;}glfwMakeContextCurrent(window);//GLAD/*if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {std::cout << "Fail to initialize GLAD";return;}*///渲染循环while (!glfwWindowShouldClose(window)) {if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)glfwSetWindowShouldClose(window, true);glClearColor(0.2f, 0.3f, 0.3f, 1.0f);	//状态设置glClear(GL_COLOR_BUFFER_BIT);	//状态使用// glfw:交换缓冲区和轮询IO事件(按键按下或释放,鼠标移动等)glfwSwapBuffers(window);glfwPollEvents();}//回收前面分配的GLFW资源glfwTerminate();
  • 初始化GLFW库

    int glfwInit(void);
    

    This function initializes the GLFW library. Before most GLFW functions can be used, GLFW must be initialized, and before an application terminates GLFW should be terminated in order to free any resources allocated during or after initialization.
    @reentrancy This function must not be called from a callback.
    @thread_safety This function must only be called from the main thread.

  • 终止GLFW库
    销毁窗口,回收已分配资源

    void glfwTerminate(void);
    
  • 将指定的窗口提示设置为所需值。

    void glfwWindowHint(int hint, int value);
    
  • 创建窗口

    GLFWwindow* glfwCreateWindow(int width, int height, const char* title, GLFWmonitor* monitor, GLFWwindow* share);
    
  • 将窗口上下文设置为当前线程上下文

    void glfwMakeContextCurrent(GLFWwindow* window);
    
  • 获取/设置窗口关闭flag

    int glfwWindowShouldClose(GLFWwindow* window);
    void glfwSetWindowShouldClose(GLFWwindow* window, int value);
    
  • 交换指定窗口的前缓冲区后缓冲区
    前缓冲区:屏幕上显示的图像。
    后缓冲区:正在渲染的图像。

    void glfwSwapBuffers(GLFWwindow* window);
    
  • 轮询IO事件

    void glfwPollEvents(void);
    

    Processes all pending events.

    • This function processes only those events that are already in the event queue and then returns immediately. Processing events will cause the window and input callbacks associated with those events to be called.
    • On some platforms, a window move, resize or menu operation will cause event processing to block. This is due to how event processing is designed on those platforms. You can use the [window refresh callback](@ref window_refresh) to redraw the contents of your window when necessary during such operations.
    • Do not assume that callbacks you set will only be called in response to event processing functions like this one. While it is necessary to poll for events, window systems that require GLFW to register callbacks of its own can pass events to GLFW in response to many window system function calls. GLFW will pass those events on to the application callbacks before returning.
    • Event processing is not required for joystick input to work.

扩展GLFW使其可以成为MFC子窗口

修改glfw源码使其可以成为MFC子窗口,重新生成lib。

参考来源:https://blog.csdn.net/sunbibei/article/details/51783783

在VS中,找到glfwCreateWindow函数的定义位置,是在 glfw3.h文件中,新加入一个函数glfwCreateWindowEx声明,如下:
在这里插入图片描述
在原本glfwCreateWindow函数的参数列表中新加入了参数int hParent或者HWND hParent

然后打开win32_platform.h文件,找到其中struct _GLFWwindowWin32定义所在的位置,新加入int handleParent或者HWND handleParent,用来保存父窗口的句柄作为参数传递给创建窗口的函数。如下图所示:
在这里插入图片描述
修改好参数结构体之后,现在实现glfwCreateWindowEx
定位glfwCreateWindow函数的定义,定义于文件window.c中。复制glfwCreateWindow函数的定义, 粘贴在下方,更改函数名为glfwCreateWindowEx并加入参数 int hParent
在该函数的实现中找到 _glfw.platform.createWindow函数的调用地方, 在其前方加入window->win32.handleParent = hParent;

GLFWAPI GLFWwindow* glfwCreateWindowEx(int width, int height,const char* title,GLFWmonitor* monitor,GLFWwindow* share,/*HWND*/int hPerant)
{_GLFWfbconfig fbconfig;_GLFWctxconfig ctxconfig;_GLFWwndconfig wndconfig;_GLFWwindow* window;assert(title != NULL);assert(width >= 0);assert(height >= 0);_GLFW_REQUIRE_INIT_OR_RETURN(NULL);if (width <= 0 || height <= 0){_glfwInputError(GLFW_INVALID_VALUE,"Invalid window size %ix%i",width, height);return NULL;}fbconfig = _glfw.hints.framebuffer;ctxconfig = _glfw.hints.context;wndconfig = _glfw.hints.window;wndconfig.width = width;wndconfig.height = height;wndconfig.title = title;ctxconfig.share = (_GLFWwindow*)share;if (!_glfwIsValidContextConfig(&ctxconfig))return NULL;window = _glfw_calloc(1, sizeof(_GLFWwindow));window->next = _glfw.windowListHead;_glfw.windowListHead = window;window->videoMode.width = width;window->videoMode.height = height;window->videoMode.redBits = fbconfig.redBits;window->videoMode.greenBits = fbconfig.greenBits;window->videoMode.blueBits = fbconfig.blueBits;window->videoMode.refreshRate = _glfw.hints.refreshRate;window->monitor = (_GLFWmonitor*)monitor;window->resizable = wndconfig.resizable;window->decorated = wndconfig.decorated;window->autoIconify = wndconfig.autoIconify;window->floating = wndconfig.floating;window->focusOnShow = wndconfig.focusOnShow;window->mousePassthrough = wndconfig.mousePassthrough;window->cursorMode = GLFW_CURSOR_NORMAL;window->doublebuffer = fbconfig.doublebuffer;window->minwidth = GLFW_DONT_CARE;window->minheight = GLFW_DONT_CARE;window->maxwidth = GLFW_DONT_CARE;window->maxheight = GLFW_DONT_CARE;window->numer = GLFW_DONT_CARE;window->denom = GLFW_DONT_CARE;window->title = _glfw_strdup(title);window->win32.handleParent = hPerant;	//新增if (!_glfw.platform.createWindow(window, &wndconfig, &ctxconfig, &fbconfig)){glfwDestroyWindow((GLFWwindow*)window);return NULL;}return (GLFWwindow*)window;
}

然后,沿着 _glfwPlatformCreateWindow函数的函数调用一直找到API CreateWindowExW函数的调用地方,位于 win32_window.c文件定义的 static int createWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig)函数中被调用。在CreateWindowExW函数前加入下述代码,

if (NULL != window->win32.handleParent) {exStyle = 0;style = WS_CHILDWINDOW | (wndconfig->visible ? WS_VISIBLE : 0);
}

并将 CreateWindowExW函数的倒数第四个参数改成 window->win32.handleParent,如下图所示。
在这里插入图片描述
修改好了之后, 对代码进行编译,生成新的lib

MFC中使用GLFW

HWND hparent = GetDlgItem(IDC_PLAYWND)->m_hWnd;
CRect rect;
GetDlgItem(IDC_PLAYWND)->GetWindowRect(&rect);
int width = rect.Width(), 
int height = rect.Height()
std::string title = "WindowName";glfwInit();
GLFWwindow *glfw_window;
glfw_window = (-1 != hparent) ? (glfwCreateWindowEx(width, height, title.c_str(), NULL, NULL, hparent)): (glfwCreateWindow(width, height, title.c_str(), NULL, NULL));

http://www.ppmy.cn/devtools/136403.html

相关文章

人工智能之机器学习5-回归算法1【培训机构学习笔记】

培训内容&#xff1a; 模型评估 培训班上课的PPT里很多错误&#xff0c;即使讲了很多年也从没改正过来。 而且很多字母没有给出具体的解释&#xff0c;比如RSS和TSS&#xff0c;对初学者非常不友善。 个人学习&#xff1a; 分类和回归的区别 回归和分类是机器学习和统计学…

FPC柔性线路板与智能生活的融合

一、在智能家居中的应用 FPC柔性线路板因其可弯曲、可折叠的特性&#xff0c;被广泛应用于智能家居设备中&#xff0c;用于连接各种传感器和执行器&#xff0c;实现家居设备的智能化控制。例如&#xff0c;智能窗帘、智能照明系统等&#xff0c;都可以通过FPC实现灵活布线&…

ArcGIS计算水库库容量

一、数据获取 DEM数据来源于地理空间数据云&#xff0c;该网站是由中科院计算机网络信息中心于2008年创立的地学大数据平台。 二、填洼 将DEM数据中凹陷的区域填充至与倾斜点同样高度&#xff0c;这里的【Z限制】说的是设定一个特定的值&#xff0c;凹陷区域的最低点高程与倾斜…

uniapp rpx兼容平板

问题: 使用uniapp开发平板端时, rpx/upx 内容过小, 没有适应屏幕 原因: uniapp 默认支持最大设备宽度为960px 而平板宽度超出了960 uniapp官方文档https://uniapp.dcloud.io/collocation/pages?idglobalstyle 解决: // pages.json 文件&#xff1a; {//..."globalSt…

vue 目录结构

vue 目录结构 目录结构 my-vue-app/ │ ├── node_modules/ │ └── ... (项目依赖库) │ ├── public/ │ ├── favicon.ico (网站图标) │ └── index.html (主HTML文件) │ ├── src/ │ ├── assets/ (静态资源&#xff0c;如图片、样式文件等) │…

网页中调用系统的EXE文件,如打开QQ

遇到一个实际的问题&#xff0c;需要在网页中打开本地的某个工业软件。 通过点击exe文件就可以调用到程序。 比如双击qq的exe就可以启动qq的程序。 那么问题就变成了如何加载exe程序呢&#xff1f; 可以通过Java的 Process process Runtime.getRuntime().exec(command);通过…

数据结构-树状数组专题(1)

一、前言 树状数组可以解决部分区间修改和区间查询的问题&#xff0c;相比于线段树&#xff0c;代码更加简单易懂 二、我的模板 搬运jiangly鸽鸽的模板&#xff0c;特别注意这个模板中所有涉及区间的都是左闭右开区间&#xff0c;且vector的有效下标都从0开始 template <…

时间类的实现

在现实生活中&#xff0c;我们常常需要计算某一天的前/后xx天是哪一天&#xff0c;算起来十分麻烦&#xff0c;为此我们不妨写一个程序&#xff0c;来减少我们的思考时间。 1.基本实现过程 为了实现时间类&#xff0c;我们需要将代码写在3个文件中&#xff0c;以增强可读性&a…