在MFC的对话框程序中需要使用OpenGL在某个对话框中作图,综合了网上的两篇文章的内容(文章一,文章二),也有自己的心得体会。
首先需要配置好opengl的环境,程序中会使用到glaux中的库和函数,这里将它的lib,h,dll文件的下载链接附上。其他的库windows中好像带有。
先将对OpenGL的操作封装成一个类,这是第一篇文章的主要思想:
头文件OpenGL.h
#pragma once #include <gl/GL.h> #include <gl/GLU.h> #include <GLAUX.H> class COpenGL { public: COpenGL(void); ~COpenGL(void); HDC hDC; HGLRC hRC; public: /************************************************************************/ /* 对OpenGL的一些初始化工作,width和height表示窗口的宽和高 */ /************************************************************************/ void Init(int width,int height); /************************************************************************/ /* 设置像素格式 */ /************************************************************************/ bool SetupPixelFormat(HDC hDC0); /************************************************************************/ /* 窗口大小改变时的回调函数 */ /************************************************************************/ void Reshap(int width,int height); /************************************************************************/ /* 具体的渲染操作,窗口中显示的内容是在这个函数中完成的 */ /************************************************************************/ void Render(); };
#include "StdAfx.h" #include "OpenGL.h" COpenGL::COpenGL(void) { } COpenGL::~COpenGL(void) { wglMakeCurrent(hDC,NULL); wglDeleteContext(hRC); } void COpenGL::Init(int width,int height){ // openGL的初始化设置 glClearColor(0.0, 1.0, 1.0, 0.0); glShadeModel(GL_SMOOTH); //glViewport(0, 0, 200, 200); glMatrixMode(GL_PROJECTION); gluPerspective(60, (GLfloat)width/(GLfloat)height, 0.1, 100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } bool COpenGL::SetupPixelFormat(HDC hDC0){ int nPixelFormat; // 象素点格式 hDC=hDC0; PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), // pfd结构的大小 1, // 版本号 PFD_DRAW_TO_WINDOW | // 支持在窗口中绘图 PFD_SUPPORT_OPENGL | // 支持OpenGL PFD_DOUBLEBUFFER, // 双缓存模式 PFD_TYPE_RGBA, // RGBA 颜色模式 24, // 24 位颜色深度 0, 0, 0, 0, 0, 0, // 忽略颜色位 0, // 没有非透明度缓存 0, // 忽略移位位 0, // 无累加缓存 0, 0, 0, 0, // 忽略累加位 32, // 32 位深度缓存 0, // 无模板缓存 0, // 无辅助缓存 PFD_MAIN_PLANE, // 主层 0, // 保留 0, 0, 0 // 忽略层,可见性和损毁掩模 }; 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); wglMakeCurrent(hDC, hRC); return TRUE; } void COpenGL::Reshap(int width,int height){ glViewport(0,0,width,height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective ( 60.0f, (GLfloat)width/(GLfloat)height, 0.1f, 100.0f ); //gluLookAt(10,5,10,0,0,0,0,1,0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void COpenGL::Render(){ glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0, 0.0, 0.0); glLoadIdentity(); glTranslatef(0.0, 0.0, -5.0); glBegin(GL_TRIANGLES); glVertex3f(0.0, 1.0, 0.0); glVertex3f(-1.0, -1.0, 0.0); glVertex3f(1.0, -1.0, 0.0); glEnd(); SwapBuffers(hDC); }
具体的方法是:
1.在需要绘图的窗口类中添加OpenGL.h头文件,并声明一个COpenGL类型的成员变量。如我想在CDialog4这个类中使用OpenGL绘图,那么在它 的头文件中包含OpenGL.h,并声明一个COpenGL类型的成员变量。
2.添加两个消息响应函数,即WM_SIZE和WM_TIMER消息的处理,重写一个函数OnInitDialog。
这两步操作完成后,CDialog4的头文件如下:
#pragma once #include "OpenGL.h" // CDialog4 对话框 class CDialog4 : public CDialog { DECLARE_DYNAMIC(CDialog4) public: COpenGL openGL; public: CDialog4(CWnd* pParent = NULL); // 标准构造函数 virtual ~CDialog4(); // 对话框数据 enum { IDD = IDD_DIALOG4 }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 DECLARE_MESSAGE_MAP() public: afx_msg void OnSize(UINT nType, int cx, int cy); virtual BOOL OnInitDialog(); afx_msg void OnTimer(UINT_PTR nIDEvent); };
// Dialog4.cpp : 实现文件 // #include "stdafx.h" #include "ComputerGraphic.h" #include "Dialog4.h" // CDialog4 对话框 IMPLEMENT_DYNAMIC(CDialog4, CDialog) CDialog4::CDialog4(CWnd* pParent /*=NULL*/) : CDialog(CDialog4::IDD, pParent) { } CDialog4::~CDialog4() { } void CDialog4::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CDialog4, CDialog) ON_WM_SIZE() ON_WM_TIMER() END_MESSAGE_MAP() void CDialog4::OnSize(UINT nType, int cx, int cy) { CDialog::OnSize(nType, cx, cy); openGL.Reshap(cx,cy); } BOOL CDialog4::OnInitDialog() { CDialog::OnInitDialog(); /************************************************************************/ /* 传递给SetupPixelFormat的参数是要绘图的对象的DC,可以是窗口中的某一个控件 这里使用的是窗口的DC,即在窗口中绘图,而不是在窗口的某个控件中绘图*/ /************************************************************************/ openGL.SetupPixelFormat(::GetDC(m_hWnd)); //得到绘图区域对应的长方形 CRect rect; GetClientRect(&rect); //设置绘图区域的宽和高 openGL.Init(rect.right,rect.bottom); SetTimer(1,10,0); return TRUE; // return TRUE unless you set the focus to a control // 异常: OCX 属性页应返回 FALSE } void CDialog4::OnTimer(UINT_PTR nIDEvent) { // TODO: 在此添加消息处理程序代码和/或调用默认值 openGL.Render(); CDialog::OnTimer(nIDEvent); }
程序运行后的效果如下图: