MFC對話方塊程式中使用OpenGL
阿新 • • 發佈:2019-01-02
在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(); };
原始檔OpenGL.cpp
#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); }
上面將對OpenGL的操作封裝成了一個工具類,但是照第一篇文章的思路實現時由於我的工程是基於MFC的對話方塊程式,照他上面說的方法顯示出的對話方塊中沒有東西。於是使用這個工具類時參照了第二篇文章的方法,也明白瞭如何在其他的工程中使用這個工具類。
具體的方法是:
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);
};
CDialog4的原始檔如下:
// 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);
}
重點是在OnInitDialog中的函式呼叫,獲取不同控制元件的DC就可以在不同的控制元件中繪圖了。這時使用該方法就很靈活方便了。OnSize函式是在視窗改變時重新設定透視投影的寬和高,如果沒有這個訊息處理當視窗大小改變時圖形的位置不會變化,看起來就會很奇怪。
程式執行後的效果如下圖: