如何在mfc中配置mfc 对话框 opengll

OpenGL在MFC中的实现_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
OpenGL在MFC中的实现
上传于||暂无简介
阅读已结束,如果下载本文需要使用1下载券
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,查找使用更方便
还剩13页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢在MFC框架中使用OpenGL的简单实例 - Jermaine.Lee - 博客园
  我们知道,在MFC框架中,用于绘图的接口是GDI。但GDI只能绘制简单的2D图形,要想制作精美的3D图形,一个可行的办法是使用OpenGL或者Direct3D等第三方库。
  由于最近在给导师的一个小项目帮忙,而且要求使用OpenGL,所以我特地在网上搜索&如何在MFC框架中使用OpenGL&,看了很多博文,甚至论文(居然还有人把这个写成论文)后,自己又到VS2012上尝试了一番,最终摸索出了最最简单基本的使用方法,故总结在这里。一方面开启自己在博客园的学习和自省之路,另一方面也为需要的朋友提供点小小的帮助。相信这个实例会是最简单最容易理解的。
  GDI绘图使用的是HDC,而OpenGL使用的则是HGLRC。与D2D通过把RenderTarget绑定到HDC以实现和GDI的混用的方法类似,OpenGL要想与HDC混用,或者说兼容HDC吧,需要使用wglCreateContext()函数来通过HDC创建一个HGLRC并把它选为当前所使用的环境。不过在此之前,我们还需要把像素格式设置成支持OpenGL的格式。另外,窗口也必须被改为特定的样式才能被OpenGL使用。做好了这三点,就能在MFC框架中使用OpenGL进行绘制了。
具体实现步骤
1. 封装OpenGL类
  首先,基于OOP的思想,我们把跟OpenGL相关的数据与操作封装起来:
#pragma once
class COpenGL
  HDC hDC;
 //GDI绘图中使用的的设备环境句柄
  HGLRC hRC;
//OpenGL渲染时使用的渲染环境句柄
  COpenGL(void);
  virtual ~COpenGL(void);
  bool SetupPixelFormat(HDC hdc);  //设置像素格式为适合OpenGL的格式
  void Init(void);           //初始化渲染过程中属性的设置
  void Render(void);          //绘制代码
  void Reshape(int width,int height);  //改变窗口大小时对视窗进行的操作
#include "stdafx.h"
#include "OpenGL.h"
COpenGL::COpenGL(void)
COpenGL::~COpenGL(void)
wglMakeCurrent(hDC, NULL);
wglDeleteContext(hRC);
void COpenGL::Init(void)
//可添加例如&开启深度探测&等绘图属性设置代码
bool COpenGL::SetupPixelFormat(HDC hdc)
PIXELFORMATDESCRIPTOR pfd =
sizeof(PIXELFORMATDESCRIPTOR),
// pfd结构的大小
PFD_DRAW_TO_WINDOW |
// 支持在窗口中绘图
PFD_SUPPORT_OPENGL |
// 支持OpenGL
PFD_DOUBLEBUFFER,
// 双缓存模式
PFD_TYPE_RGBA,
// RGBA 颜色模式
// 24 位颜色深度
0, 0, 0, 0, 0, 0,
// 忽略颜色位
// 没有非透明度缓存
// 忽略移位位
// 无累加缓存
0, 0, 0, 0,
// 忽略累加位
// 32 位深度缓存
// 无模板缓存
// 无辅助缓存
PFD_MAIN_PLANE,
// 忽略层,可见性和损毁掩模
int nPixelF
// 像素点格式
if (!(nPixelFormat = ChoosePixelFormat(hDC, &pfd)))
MessageBox(NULL,L"can not find proper mode",L"Error",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
SetPixelFormat(hDC,nPixelFormat,&pfd);
hRC = wglCreateContext(hDC);
//利用GDI绘图所使用的HDC创建对应的HGLRC
wglMakeCurrent(hDC, hRC);
//使OpenGL绘图所使用的HGLRC为当前绘图工具
return TRUE;
void COpenGL::Render()
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
//绘制操作:
glColor3ub(255,0,0);
glBegin(GL_POLYGON);//填充凸多边形
glVertex3f(0.5f,0.5f ,0.0f);
glVertex3f(0.5f,-0.5f, 0.0f);
glVertex3f(-0.5f,-0.5f,0.0f);
glVertex3f(-0.5f,0.5f,0.0f);
glFlush();
SwapBuffers(hDC);
void COpenGL::Reshape(int width,int height)
glViewport(0,0,width,height);
&2. 使用OpenGL类
  接下来,我们在MFC框架中的CProjNameView类中创建刚刚编写的OpenGL类成员并进行相应的调用和操作来进行绘制:
  先在头文件中添加成员变量:
  然后,改写CProjNameView::PreCreateWindow()函数以改变窗口样式来适应OpenGL的要求:
BOOL CProjNameView::PreCreateWindow(CREATESTRUCT& cs)
// TODO: 在此处通过修改
CREATESTRUCT cs 来修改窗口类或样式
cs.style|=WS_CLIPSIBLINGS|WS_CLIPCHILDREN;
return CView::PreCreateWindow(cs);
  再在CProjNameView::OnInitialUpdate()函数中添加设置像素格式、转换当前绘图所使用的环境和初始化OpenGL绘制属性的操作。(这里我们省去了初始化操作,即省去了OpenGL.cpp中的Init()函数的代码。设置像素格式、转换当前绘图所使用的环境都包含在COpenGL类的成员函数SetupPixelFormat()中)
void CProjNameView::OnInitialUpdate()
CView::OnInitialUpdate();
// TODO: 写入最终选择模式代码之后移除此代码
m_pSelection = NULL;
// 初始化所选内容
opengl.SetupPixelFormat(::GetDC(GetSafeHwnd()));
opengl.Init();
  接下来,在CProjNameView::OnDraw()函数中添加绘制操作。
void CProjNameView::OnDraw(CDC* /*pDC*/)
CFaceModelingDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
// TODO: 在此处为本机数据添加绘制代码
opengl.Render();
  最后,再改写CProjNameView::OnSize()函数,就大功告成了!(当然,这个并不是本例子中必要的,没有这项控制也能成功绘制。)
void CProjNameView::OnSize(UINT nType, int cx, int cy)
opengl.Reshape(cx,cy);
  效果图如下:
  当然,事先需要包含gl.h和glut.h两个头文件,他们一般都在GL文件夹目录下,而且gl.h是自带的,glut.h是需要自己扩展的。另外,还需要把glut.lib添加到工程可见的范围内。方便起见,我在这里提供一下glut的下载链接:
  另外,在MFC中使用OpenGL的绘制列表和纹理时要注意,MFC貌似不支持OpenGL的绘制列表,而且MFC似乎要求在每次绘制前都要设置一次纹理。这之中的道理只有深入了解MFC和OpenGL后才能明白了,如果有朋友知道的话,希望能在评论里给一些指导哦~!
  如果还有什么问题或是建议的话,希望大家提出来!新人第一次写随笔,还请多多指教~!2014年2月 C/C++大版内专家分月排行榜第二2013年4月 C/C++大版内专家分月排行榜第二2013年3月 C/C++大版内专家分月排行榜第二2012年12月 C/C++大版内专家分月排行榜第二2012年11月 C/C++大版内专家分月排行榜第二2012年8月 C/C++大版内专家分月排行榜第二
2014年12月 C/C++大版内专家分月排行榜第三2014年5月 C/C++大版内专家分月排行榜第三2014年3月 C/C++大版内专家分月排行榜第三2013年12月 C/C++大版内专家分月排行榜第三2013年10月 C/C++大版内专家分月排行榜第三2013年9月 C/C++大版内专家分月排行榜第三2013年7月 C/C++大版内专家分月排行榜第三2013年5月 C/C++大版内专家分月排行榜第三2013年2月 C/C++大版内专家分月排行榜第三2013年1月 C/C++大版内专家分月排行榜第三2012年9月 C/C++大版内专家分月排行榜第三
2014年2月 C/C++大版内专家分月排行榜第二2013年4月 C/C++大版内专家分月排行榜第二2013年3月 C/C++大版内专家分月排行榜第二2012年12月 C/C++大版内专家分月排行榜第二2012年11月 C/C++大版内专家分月排行榜第二2012年8月 C/C++大版内专家分月排行榜第二
2014年12月 C/C++大版内专家分月排行榜第三2014年5月 C/C++大版内专家分月排行榜第三2014年3月 C/C++大版内专家分月排行榜第三2013年12月 C/C++大版内专家分月排行榜第三2013年10月 C/C++大版内专家分月排行榜第三2013年9月 C/C++大版内专家分月排行榜第三2013年7月 C/C++大版内专家分月排行榜第三2013年5月 C/C++大版内专家分月排行榜第三2013年2月 C/C++大版内专家分月排行榜第三2013年1月 C/C++大版内专家分月排行榜第三2012年9月 C/C++大版内专家分月排行榜第三
匿名用户不能发表回复!|
每天回帖即可获得10分可用分!小技巧:
你还可以输入10000个字符
(Ctrl+Enter)
请遵守CSDN,不得违反国家法律法规。
转载文章请注明出自“CSDN(www.csdn.net)”。如是商业用途请联系原作者。如何在MFC对话框程序里采用OpenGL绘图
网上可以搜到很多介绍在MFC单文档/多文档程序里如何设置OpenGL绘图的方法,但是对话框MFC程序的与之有很大不同。下面的代码会示例如何在对话框程序里设置OpenGL。请注意几个重要的地方:
消息映射的添加/删除。
响应函数的添加/删除。
3. SwapBuffer函数,少了这个程序就会失灵。
建立一个基于对话框的工程(名称:OpenGL)并且在设置的Link里加入库opengl32.lib glu32.lib glaux.lib
(设置参见其他帖子)为对话框添加picture control 控件,ID:IDC_RENDER建立好框架后替换代码:
1、将以下代码替换OpenGLDlg.cpp中代码复制代码
// OpenGLDlg.cpp :
implementation file
#include "stdafx.h"
#include "OpenGL.h"
#include "OpenGLDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// COpenGLDlg dialog
COpenGLDlg::COpenGLDlg(CWnd* pParent )
: CDialog(COpenGLDlg::IDD, pParent)
//{{AFX_DATA_INIT(COpenGLDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in
PixelFormat=0;
m_yRotate = 0;
m_hIcon = AfxGetApp()-&LoadIcon(IDR_MAINFRAME);
void COpenGLDlg::DoDataExchange(CDataExchange* pDX)
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(COpenGLDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
BEGIN_MESSAGE_MAP(COpenGLDlg, CDialog)
//{{AFX_MSG_MAP(COpenGLDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_TIMER()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// COpenGLDlg message handlers
BOOL COpenGLDlg::OnInitDialog()
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX & 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
CString strAboutM
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
pSysMenu-&AppendMenu(MF_SEPARATOR);
pSysMenu-&AppendMenu(MF_STRING, IDM_ABOUTBOX,
strAboutMenu);
// Set the icon for this dialog. The framework does this
automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
///////////////////////OPENGL INIT/////////////////////////
CWnd *wnd=GetDlgItem(IDC_RENDER);
hrenderDC=::GetDC(wnd-&m_hWnd);
if(SetWindowPixelFormat(hrenderDC)==FALSE)
if(CreateViewGLContext(hrenderDC)==FALSE)
glPolygonMode(GL_FRONT,GL_FILL);
glPolygonMode(GL_BACK,GL_FILL);
///////////////////////////////////////////
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glViewport(0,0,259,231);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45,1,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(1,10,0);
////////////////////////////////////////////////////////////////
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a
void COpenGLDlg::OnSysCommand(UINT nID, LPARAM lParam)
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
CAboutDlg dlgA
dlgAbout.DoModal();
CDialog::OnSysCommand(nID, lParam);
// If you add a minimize button to your dialog, you will need the
code below
// to draw the icon. For MFC applications using the document/view
// this is automatically done for you by the framework.
void COpenGLDlg::OnPaint()
if (IsIconic())
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
CDialog::OnPaint();
// The system calls this to obtain the cursor to display while the
user drags
// the minimized window.
HCURSOR COpenGLDlg::OnQueryDragIcon()
return (HCURSOR) m_hI
BOOL COpenGLDlg::SetWindowPixelFormat(HDC hDC)
PIXELFORMATDESCRIPTOR pixelD
pixelDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pixelDesc.nVersion = 1;
pixelDesc.dwFlags = PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER |
PFD_TYPE_RGBA;
pixelDesc.iPixelType = PFD_TYPE_RGBA;
pixelDesc.cColorBits = 32;
pixelDesc.cRedBits = 0;
pixelDesc.cRedShift = 0;
pixelDesc.cGreenBits = 0;
pixelDesc.cGreenShift = 0;
pixelDesc.cBlueBits = 0;
pixelDesc.cBlueShift = 0;
pixelDesc.cAlphaBits = 0;
pixelDesc.cAlphaShift = 0;
pixelDesc.cAccumBits = 0;
pixelDesc.cAccumRedBits = 0;
pixelDesc.cAccumGreenBits = 0;
pixelDesc.cAccumBlueBits = 0;
pixelDesc.cAccumAlphaBits = 0;
pixelDesc.cDepthBits = 0;
pixelDesc.cStencilBits = 1;
pixelDesc.cAuxBuffers = 0;
pixelDesc.iLayerType = PFD_MAIN_PLANE;
pixelDesc.bReserved = 0;
pixelDesc.dwLayerMask = 0;
pixelDesc.dwVisibleMask = 0;
pixelDesc.dwDamageMask = 0;
PixelFormat = ChoosePixelFormat(hDC,&pixelDesc);
if(PixelFormat==0) // Choose default
PixelFormat = 1;
if(DescribePixelFormat(hDC,PixelFormat,
sizeof(PIXELFORMATDESCRIPTOR),&pixelDesc)==0)
return FALSE;
if(SetPixelFormat(hDC,PixelFormat,&pixelDesc)==FALSE)
return FALSE;
return TRUE;
COpenGLDlg::CreateViewGLContext(HDC hDC)
hrenderRC = wglCreateContext(hDC);
if(hrenderRC==NULL)
return FALSE;
if(wglMakeCurrent(hDC,hrenderRC)==FALSE)
return FALSE;
return TRUE;
void COpenGLDlg::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 COpenGLDlg::OnTimer(UINT nIDEvent)
//实时绘制场景
// TODO: Add your message handler code here and/or call
RenderScene();
m_yRotate +=3;
CDialog::OnTimer(nIDEvent);
2、替换OpenGLDlg.h代码复制代码
// OpenGLDlg.h : header
!defined(AFX_OPENGLDLG_H__8E962FCE_4DD3_4AE0_BA13_D93DE3FBA4A1__INCLUDED_)
AFX_OPENGLDLG_H__8E962FCE_4DD3_4AE0_BA13_D93DE3FBA4A1__INCLUDED_
#if _MSC_VER & 1000
#pragma once
#endif // _MSC_VER & 1000
/////////////////////////////////////////////////////////////////////////////
// COpenGLDlg dialog
class COpenGLDlg : public CDialog
// Construction
COpenGLDlg(CWnd* pParent = NULL); // standard
constructor
SetWindowPixelFormat(HDC hDC);
//设定象素格式
BOOL CreateViewGLContext(HDC hDC); //View GL Context
void RenderScene(); //绘制场景
HDC hrenderDC; //DC
HGLRC hrenderRC; //RC
float m_yR //转速
int PixelF
// Dialog Data
//{{AFX_DATA(COpenGLDlg)
enum { IDD = IDD_OPENGL_DIALOG };
// NOTE: the ClassWizard will add data members here
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(COpenGLDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV
//}}AFX_VIRTUAL
// Implementation
protected:
HICON m_hI
// Generated message map functions
//{{AFX_MSG(COpenGLDlg)
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);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations
immediately before the previous line.
!defined(AFX_OPENGLDLG_H__8E962FCE_4DD3_4AE0_BA13_D93DE3FBA4A1__INCLUDED_)
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。11:05 提问
Opengl MFC多线程如何在原窗口进行绘图
由于OPENGL绘图占用时间较长(32ms),不得不新开一个线程进行绘图,但我发现我现在的程序每次都要新建窗口。请问,怎么在原窗口上绘图啊?
按赞数排序
glutCreateWindow()从名字上看不是你注释的设置窗口标题,而是创建一个新窗口。
看你线程中的代码应该是从一个控制台项目中拷贝过来的,因为没用过opengl所以不能给你明确的解决办法,但估计opengl应该有个设置绘图窗口的函数,你在线程中调用这个函数就可以了。
建议还是仔细看过库的详细用法再动手开发,否则也是知其然不知其所以然。
这个nene的教程上面应该有的啊,就是旋转立方体的那个
原窗口,那你还是要在主线程上画图,那你线程中发送消息过去通知主线程画图。
已经解决了,这是我的线程函数(类似于单片机程序,很熟悉)
int OpenGLThread(LPVOID lpv)//线程run函数
//获得线程创建时对话框传入的参数,可以通过这里传递给opengl一些控制参数
COpenGLVS20122Dlg* pTaskMain = (COpenGLVS20122Dlg *)
pTaskMain-&MySetPixelFormat(::GetDC(pTaskMain-&m_hWnd));
// 设置当前的绘图像素格式
pTaskMain-&hdc = ::GetDC(pTaskMain-&m_hWnd);
// 获得绘图描述表
pTaskMain-&hglrc = wglCreateContext(pTaskMain-&hdc);
// 创建绘图描述表
wglMakeCurrent(pTaskMain-&hdc, pTaskMain-&hglrc);
// 使绘图描述表为当前调用现程的当前绘图描述表
//pTaskMain-&OnCreate(pTaskMain-&lpCreateStruct);
pTaskMain-&InitGL();
while (true)
pTaskMain-&GLDraw();
这样就OK了
其他相似问题

我要回帖

更多关于 vs mfc opengl 的文章

 

随机推荐