2009年7月10日 星期五

在MFC中使用OpenGL

這篇文章介紹如何在MFC上使用OpenGL.

1. 產生一個MFC Dialog, 然後引用OpenGL的標頭檔(gl.h, glu.h), 和連結OpenGL的函式庫(opengl32.lib, glu32.lib); 其作法可參考在Windows中使用OpenGL

2. 在ClassWizard增加WM_CREATE訊息處理OnCreate
函式(設定OpenGL RC);


部分程式碼所下所示:

int CMFC_OpenGLDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDialog::OnCreate(lpCreateStruct) == -1)
return -1;

// TODO: Add your specialized creation code here

//取得一個DC
m_hDC = ::GetDC(this->GetSafeHwnd());
//調整這個DC的像素格示
if(!SetPixelformat(m_hDC))

{
::MessageBoxA(::GetFocus(),"SetPixelformat Failed!","Error",MB_OK);
return -1;

}

//產生一個OpenGL rendering context
m_hGLRC = wglCreateContext(m_hDC);

//
設置為當前的RC
m_hDC, m_hGLRC); InitGL();
return 0;
}



3.
增加WM_SIZE訊息處理OnSize函式(改變ViewPort)

void CMFC_OpenGLDlg::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);

// TODO: Add your message handler code here
GLsizei width;
GLsizei height;

width = cx;
height = cy;

ReSizeGLScene((GLsizei) width, (GLsizei) height);
}

GLvoid CMFC_OpenGLDlg::ReSizeGLScene(GLsizei width, GLsizei height) // Resize And Initialize The GL Window
{

if (height==0) // Prevent A Divide By Zero By
{
height=1; // Making Height Equal One
}

glViewport(0,0,width,height); // Reset The Current Viewport

glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
glLoadIdentity(); // Reset The Projection Matrix

// Calculate The Aspect Ratio Of The Window
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);

glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
glLoadIdentity(); // Reset The Modelview Matrix

}



4. 增加WM_PAINT訊息處理OnPaint函式(將繪圖函式加在裡面)

void CMFC_OpenGLDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting

SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0);

// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
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);
}
else
{

DrawGLScene();
SwapBuffers(m_hDC);


CDialog::OnPaint();
}
}


int CMFC_OpenGLDlg::DrawGLScene(GLvoid) // Here's Where We Do All The Drawing
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer
glLoadIdentity(); // Reset The Current Modelview Matrix
glTranslatef(-1.5f,0.0f,-6.0f); // Move Left 1.5 Units And Into The Screen 6.0

glBegin(GL_TRIANGLES); // Drawing Using Triangles
glColor3f(1.0f,0.0f,0.0f); // Set The Color To Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top
glColor3f(0.0f,1.0f,0.0f); // Set The Color To Green
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glColor3f(0.0f,0.0f,1.0f); // Set The Color To Blue
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glEnd(); // Finished Drawing The Triangle
glTranslatef(3.0f,0.0f,0.0f); // Move Right 3 Units
glColor3f(0.5f,0.5f,1.0f); // Set The Color To Blue One Time Only
glBegin(GL_QUADS); // Draw A Quad
glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left
glVertex3f( 1.0f, 1.0f, 0.0f); // Top Right
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glEnd(); /// Done Drawing The Quad

return TRUE; // Keep Going
}


5. 增加WM_DESTROY訊息處理OnDestory函式(釋放不用的DCRC)


void CMFC_OpenGLDlg::OnDestroy()
{
CDialog::OnDestroy();
wglMakeCurrent(NULL,NULL);
wglDeleteContext(m_hGLRC);
}


結果如下面圖式:

沒有留言:

張貼留言