videoRender.h:
#pragma once
#include <QtWidgets/QWidget>
#include "ui_qtvideorender.h"
#include"Windows.h"
//#include<windows.h>
#include <QResizeEvent>
class QtVideoRender : public QWidget
{
Q_OBJECT
public:
QtVideoRender(QWidget *parent = nullptr);
~QtVideoRender();
virtual QPaintEngine* paintEngine() const { return NULL; }
virtual void resizeEvent(QResizeEvent* event);
void GLUpdate();
private:
bool createGLContext();
void render();
bool event(QEvent* event);
private:
Ui::QtVideoRenderClass ui;
private:
HDC dc;
//设备上下文
HGLRC rc;//opengl上下文 也是渲染上下文
HWND hwnd;//windows窗口句柄
};
videorender.cpp:
#include "qtvideorender.h"
#include <assert.h>
#include"GL\eglew.h"
//
#pragma comment(lib,"glew32.lib")
#pragma comment(lib,"opengl32.lib")
#include"QtEvent.h"
QtVideoRender::QtVideoRender(QWidget *parent)
: QWidget(parent,Qt::MSWindowsOwnDC)
//Qt::MSWindowsOwnDC 使用自己的pc
{
//1.
setAttribute(Qt::WA_PaintOnScreen);
//绘制到屏幕 就不能使用qt默认的了 的绘制就不能用了 ;已经手动实现paintEngine() 这个函数
setAttribute(Qt::WA_NoSystemBackground);//无系统背景
setAutoFillBackground(true);//自动填充
ui.setupUi(this);
//2.
hwnd = (HWND)winId();
bool sucess=createGLContext();
//
wglMakeCurrent(dc, rc);
assert(glewInit() == GLEW_OK);
QApplication::postEvent(this, new QtEvent(QtEvent::GL_Renderer));
}
QtVideoRender::~QtVideoRender()
{
wglMakeCurrent(NULL, NULL);
if (rc)
{
wglDeleteContext(rc);
}
if (dc)
{
ReleaseDC(hwnd, dc);
}
}
//2.
void QtVideoRender::resizeEvent(QResizeEvent* event)
{
glViewport(0, 0, event->size().width(), event->size().height());
GLUpdate();
}
void QtVideoRender::GLUpdate()
{
QApplication::postEvent(this, new QtEvent(QtEvent::GL_Renderer));
}
bool QtVideoRender::createGLContext()
{
//获取设备上下文
dc = GetDC(hwnd);
//概念:深度缓冲 模板缓冲区位深
PIXELFORMATDESCRIPTOR pfd;//???结构体
ZeroMemory(&pfd, sizeof(pfd));
pfd.nSize = sizeof(pfd);
//指定结构体版本号,设置为1
pfd.nVersion = 1;
//rgba 4个字节
pfd.cColorBits = 32;
//设置深度缓冲 空间物体 对于眼睛有距离 记录这些点的层次
pfd.cDepthBits = 24;
//设置模板缓冲区位深 :屏幕上的像素点保留一个无符号的整形
pfd.cStencilBits = 8;
//设置像素类型
pfd.iPixelType = PFD_TYPE_RGBA;
//可以绘制到窗口
// 第三个参数设置双缓冲 机制 有两张图 一个前一个后 前面显示,后面绘画 绘画完了 放在前面 显示放在后面 开始绘画 绘画完了 放在前面 两者交替循环
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
int format = 0;
format = ChoosePixelFormat(dc, &pfd);
if (!format)
{
throw;//实际开发不是这么做
//return false;
}
SetPixelFormat(dc, format, &pfd);
//opengl上下文
rc = wglCreateContext(dc);
return true;
}
bool QtVideoRender::event(QEvent* event)
{
if (event->type() == QtEvent::GL_Renderer)
{
//进行渲染
render();
}
return QWidget::event(event);
}
void QtVideoRender::render()
{
//glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
static float redv = 0;
redv += 0.01;
if (redv > 1)redv = 0;
glClearColor(redv, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
SwapBuffers(dc);
}
/*
Qt::MSWindowsOwnDC:
一:
实验 :
(1)显示窗口 是白色的
1.注意 平台的字节设置 是unicode 还是多字节的 根据平台选择 不然 导致错误
rc = wglCreateContext(dc);这一步会中断掉 这个问题不是错误 而是忽视 ,有时候忽视细节 会导致问题无法解决
从而花一大把时间去 查找不是问题的问题 ,最后这种经验算不算一种收获 也是值得深思的
(2)在窗口绘制颜色
(3)改变窗口大小 发现 渲染区域不改变
就实现 resize事件 去更新界面 渲染颜色随窗口变动而改变
*/
实验结果: