这里,我主要是利用opengl在一个picture控件中绘图,绘制的是一个静态图片,如果想实现动画,可以利用ontimer函数实现。编译器为vs2010。
1、首先创建一个基于对话框的MFC程序,我这里命名为MFC_Dlg。
2、配置opengl环境
首先添加链接库,在菜单栏 项目->属性->配置属性->链接器->输入->附加依赖项,添加glut32.lib,glaux.lib。如图:
然后,在stdafx.h里面添加opengl的头文件,如下:
////////////opengl头文件///////////////////// #include "gl\GLUT.H" #include "gl\GLAUX.H" #include <stdio.h> #include <math.h>
4、添加消息相应函数
这里主要是为了在窗口销毁时释放DC和RC资源,为对话框添加了WM_DESTORY消息的相应函数。
5、在对话框头文件中添加相应的成员函数以及数据成员,如下:
public: HGLRC m_hRC; //着色描述表 CDC *m_pDC; //设备描述表 BOOL InitOpengl(); //初始化opengl BOOL SetupPixelFormat(); //设置图片控件的像素格式 void RenderScene(); //绘制图像6、初始化opengl
在对话框的OnInitDialog()中调用了InitOpengl()对opengl进行初始化
// TODO: 在此添加额外的初始化代码 InitOpengl(); //初始化opengl return TRUE; // 除非将焦点设置到控件,否则返回 TRUE对应的InitOpengl()代码如下:
BOOL CMFC_DlgDlg::InitOpengl() { //获取图片控件DC m_pDC=new CClientDC(GetDlgItem(IDC_PIC)); if(m_pDC==NULL) return FALSE; //设置图片控件像素 if (!SetupPixelFormat()) return FALSE; //创建兼容RC m_hRC=wglCreateContext(m_pDC->GetSafeHdc()); if (m_hRC==0) { return FALSE; } //激活RC if (wglMakeCurrent(m_pDC->GetSafeHdc(),m_hRC)==FALSE) { return FALSE; } //设置投影模式 GLdouble aspect_ratio; GLsizei width,height; CRect rect; CWnd *pWnd=NULL; pWnd=GetDlgItem(IDC_PIC); pWnd->GetClientRect(rect); width=rect.right-rect.left; height=rect.bottom-rect.top; glViewport(0,0,width,height); aspect_ratio=(GLdouble)width/(GLdouble)height; glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f,aspect_ratio,0.1,200.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glClearColor(0.0f,0.0f,0.0f,0.0f); glClearDepth(1.0f); glEnable(GL_DEPTH_TEST); return TRUE; }7、在上述函数中调用了像素初始化函数SetupPixelFormat()对picture控件的像素进行初始化,其代码如下:
BOOL CMFC_DlgDlg::SetupPixelFormat() { static PIXELFORMATDESCRIPTOR pfd= { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW| PFD_SUPPORT_OPENGL| PFD_DOUBLEBUFFER, PFD_TYPE_RGBA, 24, 0,0,0,0,0,0, 0, 0, 0, 0,0,0,0, 16, 0, 0, PFD_MAIN_PLANE, 0, 0,0,0 }; int m_nPixelFormat=ChoosePixelFormat(m_pDC->GetSafeHdc(),&pfd);//在窗口找查找该像素格式 if (m_nPixelFormat==0) { return FALSE; } if (SetPixelFormat(m_pDC->GetSafeHdc(),m_nPixelFormat,&pfd)==FALSE)//设置picture控件的像素格式 { return FALSE; } return TRUE; }8、通过上面两步,就完成了初始化,下面开始绘图。为了保证图形在重绘时仍然存在,在对话框的OnPaint()函数中通过调用RenderScene()实现绘图操作,将代码添加到else块中
else { RenderScene(); //向缓冲区绘图 SwapBuffers(m_pDC->GetSafeHdc()); //交换缓冲区 CDialogEx::OnPaint(); }其中,RenderScene()代码如下:
void CMFC_DlgDlg::RenderScene() { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glTranslatef(0.0f,0.0f,-5.0f); glBegin(GL_TRIANGLES); glColor3f(1.0f,0.0f,0.0f); glVertex3f(0.0f,1.0f,1.0f); glColor3f(0.0f,1.0f,0.0f); glVertex3f(-1.5f,-1.0f,0.0f); glColor3f(0.0f,0.0f,1.0f); glVertex3f(1.5f,-1.0f,0.0f); glEnd(); }这里为了简单,只画了一个三角形。
9、释放资源
在写程序,如果忘记释放DC和RC,将会导致内存泄露,随着程序运行次数的增多,内存占有量越来越大。这里在WM_DESTORY的消息响应函数中释放资源,
void CMFC_DlgDlg::OnDestroy() { CDialogEx::OnDestroy(); // TODO: 在此处添加消息处理程序代码 if (wglMakeCurrent(NULL,NULL)==FALSE) //释放RC { MessageBox("无法释放RC"); } if (wglDeleteContext(m_hRC)==FALSE) //删除RC { MessageBox("无法删除RC"); } if (m_pDC) { delete m_pDC; } m_pDC=NULL; }
运行效果如下:
到此,整个框架就建立起来了,其他的绘图操作都可以在RenderScene()中实现。如果想实现动画效果,只需要设置一个定时器,并在WM_TIMER消息响应函数中改变图形位置并调用RenderScene()即可,并且在OnDestroy中killtimer。
我也是初学者,有什么不对,大家请指正!
参考: MFC单文档框架下的opengl
Nehe中文教程