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

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

文章目录

  • 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);
#endif

	GLFWwindow* 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.kler.cn/a/408454.html

相关文章:

  • python如何解压缩文件或文件夹
  • docker容器化部署springboot项目
  • 从〇开始深度学习(0)——背景知识与环境配置
  • 摄影:相机控色
  • 数字信号处理(Digital Signal Procession)总结
  • python语言基础
  • C0033.在Ubuntu中配置clion的环境
  • 数据集-目标检测系列- 安全背心 检测数据集 safety_vests >> DataBall
  • docker desktop上下载的镜像传到虚拟机上使用
  • Python编程整理汇总(基础汇总版)
  • sed使用扩展正则表达式时, -i 要写在 -r 或 -E 的后面
  • Window11系统下修改Anaconda3默认安装虚拟环境在C盘问题
  • C++设计模式——Singleton单例模式
  • Flask服务封装+Docker服务部署
  • Android OpenGL ES详解——Renderer接口介绍
  • 12-表的约束
  • JVM标量替换
  • mysql-分析并解决可重复读隔离级别发生的删除幻读问题
  • uniapp的列表渲染v-for 与正确写法,循环二维数组
  • 开源网络安全检测工具——伏羲 Fuxi-Scanner
  • 机器学习入门-Scikit-learn
  • 46.坑王驾到第十期:vscode 无法使用 tsc 命令
  • 04 - 尚硅谷 - MQTT 客户端编程
  • 一加ACE 3 Pro手机无法连接电脑传输文件问题
  • Window11+annie 视频下载器安装
  • Sketch在线版不存在?即时设计来填补空白