在MFC中编写OPENGL程序

2015年12月26日 转载
关键词: C++ opengl mfc
摘要 本文介绍了如何在mfc中搭建opengl框架编写opengl程序。

本文转载自:Phinecos(洞庭散人)

opengl是一个最受欢迎的图形库,它提供了glut库可以产生图形界面。然而我们也可以自己在mfc里搭建opengl的框架来绘图。

首先建立一个mfc单文档工程use_opengl。

然后在stdafx.h里添加opengl的头文件。

#include<gl.h> 
#include<glu.h> 
#include<glut.h>

在use_openglView.cpp中的PreCreateWindow添加:

BOOL Cuse_openglView::PreCreateWindow(CREATESTRUCT& cs)
{
    // TODO:  在此处通过修改
    //  CREATESTRUCT cs 来修改窗口类或样式
    cs.style |= (WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
    return CView::PreCreateWindow(cs);
}

这一步设置了窗口的样式,不会被父窗口和兄弟窗口遮挡后重绘。

在view里添加一个成员int m_GLPixelIndex来保存选择的像素格式。

继续在view里添加一个成员函数来选取像素格式:

BOOL Cuse_openglView::SetWindowPixelFormat(HDC hDC) {
 PIXELFORMATDESCRIPTOR pixelDesc=
    {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,
        PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|
        PFD_DOUBLEBUFFER|PFD_SUPPORT_GDI,
        PFD_TYPE_RGBA,
        24,
        0,0,0,0,0,0,
        0,
        0,
        0,
        0,0,0,0,
        32,
        0,
        0,
        PFD_MAIN_PLANE,
        0,
        0,0,0
    };

    this->m_GLPixelIndex = ChoosePixelFormat(hDC,&pixelDesc);
    if(this->m_GLPixelIndex==0)
    {
        this->m_GLPixelIndex = 1;
        if(DescribePixelFormat(hDC,this->m_GLPixelIndex,sizeof(PIXELFORMATDESCRIPTOR),&pixelDesc)==0)
        {
            return FALSE;
        }
    }

    if(SetPixelFormat(hDC,this->m_GLPixelIndex,&pixelDesc)==FALSE)
    {
        return FALSE;
    }
    return TRUE;
}

添加一个成员变量m_hGLContext来保存产生的绘制上下文。

继续添加一个成员函数来产生绘制上下文并且选中为当前的绘制上下文。

BOOL Cuse_openglView::CreateGLViewContext(HDC hDC)
{
    this->m_hGLContext = wglCreateContext(hDC);
    if (this->m_hGLContext == NULL)
    {//创建失败
        return FALSE;
    }

    if (wglMakeCurrent(hDC, this->m_hGLContext) == FALSE)
    {//选为当前RC失败
        return FALSE;
    }

    return TRUE;
}

 为view添加WM_CREATE消息相应函数

int Cuse_openglView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CView::OnCreate(lpCreateStruct) == -1)
        return -1;

    // TODO: Add your specialized creation code here
    HWND hWnd = this->GetSafeHwnd();
    HDC hDC = ::GetDC(hWnd);
    if (this->SetWindowPixelFormat(hDC) == FALSE)
    {
        return 0;
    }
    if (this->CreateGLViewContext(hDC) == FALSE)
    {
        return 0;
    }
    return 0;
}

继续添加WM_DESTROY消息响应函数:

void Cuse_openglView::OnDestroy()
{
    CView::OnDestroy();

    if (wglGetCurrentContext() != NULL)
    {
        wglMakeCurrent(NULL, NULL);
    }
    if (this->m_hGLContext != NULL)
    {
        wglDeleteContext(this->m_hGLContext);
        this->m_hGLContext = NULL;
    }
}

继续添加WM_SIZE消息响应函数,使opengl的窗口和windows的窗口一起改变大小:

void Cuse_openglView::OnSize(UINT nType, int cx, int cy)
{
    CView::OnSize(nType, cx, cy);
    GLsizei width, height;
    GLdouble aspect;
    width = cx;
    height = cy;
    if (cy == 0)
    {
        aspect = (GLdouble)width;
    }
    else
    {
        aspect = (GLdouble)width / (GLdouble)height;
    }
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0, 500.0*aspect, 0.0, 500.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

最后添加WM_PAINT消息响应函数进行图像的绘制:

void Cuse_openglView::OnPaint()
{
    CPaintDC dc(this); // device context for painting
    // TODO:  在此处添加消息处理程序代码
    // 不为绘图消息调用 CView::OnPaint()
    glLoadIdentity();
    glClear(GL_COLOR_BUFFER_BIT);
    glBegin(GL_POLYGON);
    glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
    glVertex2f(100.0f, 50.0f);
    glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
    glVertex2f(450.0f, 400.0f);
    glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
    glVertex2f(450.0f, 50.0f);
    glEnd();
    glFlush();
    SwapBuffers(dc.m_hDC);
}

运行程序,我们就可以看到opengl画出来的图像了