《MFC dialog中加入OpenGL窗体》
《MFC dialog中加入OpenGL窗体》
最近学习了如何在MFC对话框程序中加入OpenGL窗体的方法,在这里将自己的实现过程归纳一下。
步骤零: 加入PictureControl控件
新建MFC对话框程序,删除对话框上的按钮控件的Label控件,然后向窗体添加PictureControl控件,作为绘制的窗体。
将该控件的ID设置为:IDC_RENDER
步骤一: 加入OpenGL的lib文件和头文件
在项目上单击右键,添加OpenGL的lib文件,freeglut_static.lib和gltools.lib,如下。
然后在stdafx.h中包含相关的头文件如下:
步骤二: 设置对话框的头文件***Dlg.h
在对话框头文件中声明相关的变量:
HDC hrenderDC; //设备上下文
HGLRC hrenderRC; //渲染上下文
float m_yRotate; //转速
int PixelFormat; //像素格式
在对话框头文件中声明相关方法:
BOOL SetWindowPixelFormat(HDC hDC); //设定像素格式
BOOL CreateViewGLContext(HDC hDC); //view GL Context
void RenderScene(); //绘制场景
加入消息映射函数:
afx_msg void OnTimer(UINT nIDEvent);
具体的对话框头文件如下:
// OpenGLTest1Dlg.h : 头文件
// #pragma once // COpenGLTest1Dlg 对话框
class COpenGLTest1Dlg : public CDialogEx
{
// 构造
public:
COpenGLTest1Dlg(CWnd* pParent = NULL); // 标准构造函数 BOOL SetWindowPixelFormat(HDC hDC); //设定像素格式
BOOL CreateViewGLContext(HDC hDC); //view GL Context
void RenderScene(); //绘制场景 HDC hrenderDC; //设备上下文
HGLRC hrenderRC; //渲染上下文
float m_yRotate; //转速
int PixelFormat; //像素格式 // 对话框数据
enum { IDD = IDD_OPENGLTEST1_DIALOG }; protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现
protected:
HICON m_hIcon; // 生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnTimer(UINT nIDEvent);
DECLARE_MESSAGE_MAP()
};
步骤三: 设置对话框的源文件***Dlg.cpp
a. 开启定时器消息循环
在消息循环的代码块中加入ON_WM_TIMER()消息循环:
BEGIN_MESSAGE_MAP(COpenGLTest1Dlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_TIMER()
END_MESSAGE_MAP()
这里的OnTimer函数用于相应SetTimer消息。当SetTimer设置的时间到了,就会自动调用OnTimer()函数。
写OnTimer函数的函数体,如下所示:
void COpenGLTest1Dlg::OnTimer(UINT nIDEvent) //实时绘制场景
{
// TODO: Add your message handler code here and/or call default
RenderScene();
m_yRotate +=;
CDialog::OnTimer(nIDEvent);
}
b. 写函数SetWindowPixelFormat,用于生成像素格式
函数体如下所示:
BOOL COpenGLTest1Dlg::SetWindowPixelFormat(HDC hDC)
{
PIXELFORMATDESCRIPTOR pixelDesc; pixelDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pixelDesc.nVersion = ; pixelDesc.dwFlags = PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER |
PFD_TYPE_RGBA; pixelDesc.iPixelType = PFD_TYPE_RGBA;
pixelDesc.cColorBits = ;
pixelDesc.cRedBits = ;
pixelDesc.cRedShift = ;
pixelDesc.cGreenBits = ;
pixelDesc.cGreenShift = ;
pixelDesc.cBlueBits = ;
pixelDesc.cBlueShift = ;
pixelDesc.cAlphaBits = ;
pixelDesc.cAlphaShift = ;
pixelDesc.cAccumBits = ;
pixelDesc.cAccumRedBits = ;
pixelDesc.cAccumGreenBits = ;
pixelDesc.cAccumBlueBits = ;
pixelDesc.cAccumAlphaBits = ;
pixelDesc.cDepthBits = ;
pixelDesc.cStencilBits = ;
pixelDesc.cAuxBuffers = ;
pixelDesc.iLayerType = PFD_MAIN_PLANE;
pixelDesc.bReserved = ;
pixelDesc.dwLayerMask = ;
pixelDesc.dwVisibleMask = ;
pixelDesc.dwDamageMask = ; PixelFormat = ChoosePixelFormat(hDC,&pixelDesc);
if(PixelFormat==) // Choose default
{
PixelFormat = ;
if(DescribePixelFormat(hDC,PixelFormat,
sizeof(PIXELFORMATDESCRIPTOR),&pixelDesc)==)
{
return FALSE;
}
} if(SetPixelFormat(hDC,PixelFormat,&pixelDesc)==FALSE) {
return FALSE;
} return TRUE;
}
c. 写函数CreateViewGLContext,用于生成渲染上下文
具体函数体如下:
BOOL COpenGLTest1Dlg::CreateViewGLContext(HDC hDC)
{
hrenderRC = wglCreateContext(hDC); if(hrenderRC==NULL)
return FALSE; if(wglMakeCurrent(hDC,hrenderRC)==FALSE)
return FALSE; return TRUE;
}
d. 写函数RenderScene,用于绘制场景
具体函数体如下:
void COpenGLTest1Dlg::RenderScene()
{ /////////////////////////////////////////////////
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity();
glTranslatef(0.0f,0.0f,-6.0f); // Move Left 1.5 Units And Into The Screen 6.0
glRotated(m_yRotate, 0.0, 1.0, 0.0);
glBegin(GL_TRIANGLES); // Drawing Using Triangles glVertex3f( 0.0f, 1.0f, 0.0f); // Top
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glEnd(); // Finished Drawing The Triangle
SwapBuffers(hrenderDC);
}
e. 在对话框初始化程序OnInitDialog中添加初始化代码
具体代码如下:
///////////////////////OPENGL INIT/////////////////////////
CWnd *wnd=GetDlgItem(IDC_RENDER);
hrenderDC=::GetDC(wnd->m_hWnd);
if(SetWindowPixelFormat(hrenderDC)==FALSE)
return ; if(CreateViewGLContext(hrenderDC)==FALSE)
return ; glPolygonMode(GL_FRONT,GL_FILL);
glPolygonMode(GL_BACK,GL_FILL);
///////////////////////////////////////////
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glViewport(,,,);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(,,0.1,100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
/////////////////////////////////////////////////////////////////////////
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY); SetTimer(,,); ////////////////////////////////////////////////////////////////
f. 整个.cpp源代码
// OpenGLTest1Dlg.cpp : 实现文件
// #include "stdafx.h"
#include "OpenGLTest1.h"
#include "OpenGLTest1Dlg.h"
#include "afxdialogex.h" #ifdef _DEBUG
#define new DEBUG_NEW
#endif // 用于应用程序“关于”菜单项的 CAboutDlg 对话框 class CAboutDlg : public CDialogEx
{
public:
CAboutDlg(); // 对话框数据
enum { IDD = IDD_ABOUTBOX }; protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现
protected:
DECLARE_MESSAGE_MAP()
}; CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
} void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
} BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP() // COpenGLTest1Dlg 对话框 COpenGLTest1Dlg::COpenGLTest1Dlg(CWnd* pParent /*=NULL*/)
: CDialogEx(COpenGLTest1Dlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
} void COpenGLTest1Dlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
} BEGIN_MESSAGE_MAP(COpenGLTest1Dlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_TIMER()
END_MESSAGE_MAP() // COpenGLTest1Dlg 消息处理程序 BOOL COpenGLTest1Dlg::OnInitDialog()
{
CDialogEx::OnInitDialog(); // 将“关于...”菜单项添加到系统菜单中。 // IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
} // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码
///////////////////////OPENGL INIT/////////////////////////
CWnd *wnd=GetDlgItem(IDC_RENDER);
hrenderDC=::GetDC(wnd->m_hWnd);
if(SetWindowPixelFormat(hrenderDC)==FALSE)
return ; if(CreateViewGLContext(hrenderDC)==FALSE)
return ; glPolygonMode(GL_FRONT,GL_FILL);
glPolygonMode(GL_BACK,GL_FILL);
///////////////////////////////////////////
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glViewport(,,,);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(,,0.1,100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
/////////////////////////////////////////////////////////////////////////
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY); SetTimer(,,); ////////////////////////////////////////////////////////////////
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
} void COpenGLTest1Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
} // 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。 void COpenGLTest1Dlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), ); // 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + ) / ;
int y = (rect.Height() - cyIcon + ) / ; // 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
} //当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR COpenGLTest1Dlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
} BOOL COpenGLTest1Dlg::SetWindowPixelFormat(HDC hDC)
{
PIXELFORMATDESCRIPTOR pixelDesc; pixelDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pixelDesc.nVersion = ; pixelDesc.dwFlags = PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER |
PFD_TYPE_RGBA; pixelDesc.iPixelType = PFD_TYPE_RGBA;
pixelDesc.cColorBits = ;
pixelDesc.cRedBits = ;
pixelDesc.cRedShift = ;
pixelDesc.cGreenBits = ;
pixelDesc.cGreenShift = ;
pixelDesc.cBlueBits = ;
pixelDesc.cBlueShift = ;
pixelDesc.cAlphaBits = ;
pixelDesc.cAlphaShift = ;
pixelDesc.cAccumBits = ;
pixelDesc.cAccumRedBits = ;
pixelDesc.cAccumGreenBits = ;
pixelDesc.cAccumBlueBits = ;
pixelDesc.cAccumAlphaBits = ;
pixelDesc.cDepthBits = ;
pixelDesc.cStencilBits = ;
pixelDesc.cAuxBuffers = ;
pixelDesc.iLayerType = PFD_MAIN_PLANE;
pixelDesc.bReserved = ;
pixelDesc.dwLayerMask = ;
pixelDesc.dwVisibleMask = ;
pixelDesc.dwDamageMask = ; PixelFormat = ChoosePixelFormat(hDC,&pixelDesc);
if(PixelFormat==) // Choose default
{
PixelFormat = ;
if(DescribePixelFormat(hDC,PixelFormat,
sizeof(PIXELFORMATDESCRIPTOR),&pixelDesc)==)
{
return FALSE;
}
} if(SetPixelFormat(hDC,PixelFormat,&pixelDesc)==FALSE) {
return FALSE;
} return TRUE;
} BOOL COpenGLTest1Dlg::CreateViewGLContext(HDC hDC)
{
hrenderRC = wglCreateContext(hDC); if(hrenderRC==NULL)
return FALSE; if(wglMakeCurrent(hDC,hrenderRC)==FALSE)
return FALSE; return TRUE;
} void COpenGLTest1Dlg::RenderScene()
{ /////////////////////////////////////////////////
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity();
glTranslatef(0.0f,0.0f,-6.0f); // Move Left 1.5 Units And Into The Screen 6.0
glRotated(m_yRotate, 0.0, 1.0, 0.0);
glBegin(GL_TRIANGLES); // Drawing Using Triangles glVertex3f( 0.0f, 1.0f, 0.0f); // Top
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glEnd(); // Finished Drawing The Triangle
SwapBuffers(hrenderDC);
} void COpenGLTest1Dlg::OnTimer(UINT nIDEvent) //实时绘制场景
{
// TODO: Add your message handler code here and/or call default
RenderScene();
m_yRotate +=;
CDialog::OnTimer(nIDEvent);
}
步骤四: 运行调试
运行结果如下所示:
《MFC dialog中加入OpenGL窗体》的更多相关文章
- 简单物联网:外网访问内网路由器下树莓派Flask服务器
最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...
- 利用ssh反向代理以及autossh实现从外网连接内网服务器
前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...
- 外网访问内网Docker容器
外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...
- 外网访问内网SpringBoot
外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...
- 外网访问内网Elasticsearch WEB
外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...
- 怎样从外网访问内网Rails
外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...
- 怎样从外网访问内网Memcached数据库
外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...
- 怎样从外网访问内网CouchDB数据库
外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...
- 怎样从外网访问内网DB2数据库
外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...
- 怎样从外网访问内网OpenLDAP数据库
外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...
随机推荐
- C#中字节数组byte[]和字符串string类型的相互转换
C#中字节数组byte[]和字符串string类型的相互转换: string转byte[]: byte[] byteArray = System.Text.Encoding.Default.GetBy ...
- codeforces 1288D. Minimax Problem(二分)
链接:https://codeforces.com/contest/1288/problem/D D. Minimax Problem 题意:给定n个数组,长度为m,从n中数组挑选两个数组,两个数组中 ...
- Request继承体系
ServletRequest——接口 ↑继承 HttpServletRequest——接口 ↑实现 org.apache.catalina.connector.RequestFacade——类(Tom ...
- JavaScript——BOM和DOM
什么是BOM bom:浏览器对象模型 什么是DOM dom:文档对象模型 BOM操作: 调用windows浏览器窗口 windows对象可以通过点调用子对象 windows.navigator对象,可 ...
- <context:component-scan>标签
在spring-mvc的配置文件Springmvc-servlet.xml中,要扫描Controller注解的类,用<context:include-filter>标签 <conte ...
- php设计模式之责任链模式实现举报功能实例代码
html <html> <head> <meta charset="UTF-8"> <title>责任链模式</title&g ...
- centos6 源码编译安装nginx 1.6 教程 nginx安装脚本
操作系统centos 6.9 安装nginx需要pcre zlib openssl的库,下文都是在官网直接下载用作编译安装 该nginx安装教程,有安装maxmind IP 库 该教材有修改最大打开文 ...
- Commercial Lighting: LED Ceiling Light, LED Ceiling Light
Unlike ceiling lamps, floor lamps, chandeliers, lamps that can sometimes rely on "faces", ...
- thinkphp一些经常用到的标签
volist标签(用于模板中的数组循环输出) //length:循环多少次 {volist name='list' id='vo' length='4'} <span>{$vo.name} ...
- 2020最新版idea激活教程
windows破解教程 首先下载jar包:(云盘链接发不上去,大家关注gzh"灰太狼学爪哇"回复idea获取)将其放到合适的文件夹(首选IDEA的同级目录)进行管理: 进入C盘 - ...