mfc opengl 多文档

转载 2015年11月20日 21:59:34

在多文档中绘制OpenGL图形,相对比较复杂,主要步骤和关键技术是:

(1)由于在多文档中有多个窗口需要绘制,而当前的OpenGL绘制描述表RC只有一个,因此,在窗口的图形绘制完成之后,必须将OpenGL绘制描述表RC释放,以备其他窗口所用。

(2)必须新建一个视图父类,在该视图类中对Windows设备描述表DC和OpenGL的绘制描述表进行管理,而应用程序的其他各视图类均从该类中派生。

(3)在该新建的视图类中定义一个OpenGL绘图虚函数(下面程序中为OnDrawGL),在其派生类中可以对其进行重写。这样可以在派生的视图类中调用OpenGL命令绘图。

(4)必须删除派生的视图类中的WM_DRAW消息处理函数和PreCreateWindow虚函数的声明和实现。

以下是具体的编程步骤:

建立工程MDIOpenGL添加一个新类CGLEnabledViewclass typeMFC ClassBase ClassCView

CGLEnabledView添加成员变量

       CDC* m_pDC;                                         // Windows设备描述表

       HGLRC m_hRC;                                // OpenGL渲染描述表

       CRect m_ClientRect;                          // 客户区的大小

       double m_dAspectRatio;                     // 窗口的比例

       HPALETTE    m_hPalette;                  //调色板

 

CGLEnabledView类中添加Windows Message Handler处理WM_CREATEWM_DESTROYWM_SIZE消息。以及virtual void OnDrawGL();// 图形绘制虚函数,在继承类中可以改写

void CGLEnabledView::OnDrawGL()

{

       // 绘制三个坐标轴

       glBegin(GL_LINES);

              // 绘制红色的x

              glColor3f(1.f,0.f,0.f);

              glVertex3f(0.0f,0.0f,0.0f);

              glVertex3f(1.0f,0.0f,0.0f);

              glVertex3f(1.0f,0.0f,0.0f);

              glVertex3f(0.9f,0.1f,0.0f);

              glVertex3f(1.0f,0.0f,0.0f);

              glVertex3f(0.9f,-0.1f,0.0f);

              // 绘制蓝色的y

              glColor3f(0.f,1.f,0.f);

              glVertex3f(0.0f,0.0f,0.0f);

              glVertex3f(0.0f,1.0f,0.0f);

              glVertex3f(0.0f,1.0f,0.0f);

              glVertex3f(0.1f,0.9f,0.0f);

              glVertex3f(0.0f,1.0f,0.0f);

              glVertex3f(-0.1f,0.9f,0.0f);

              // 绘制绿色的z

              glColor3f(0.f,0.f,1.f);

              glVertex3f(0.0f,0.0f,0.0f);

              glVertex3f(0.0f,0.0f,1.0f);

              glVertex3f(0.0f,0.0f,1.0f);

              glVertex3f(0.0f,0.1f,0.9f);

              glVertex3f(0.0f,0.0f,1.0f);

              glVertex3f(0.0f,-0.1f,0.9f);

       glEnd();

}

3 OnDraw是个虚函数,MFC已经替我们创建。在void CGLEnabledView::OnDraw(CDC* pDC)的实现代码中加入如下代码

    void CGLEnabledView::OnDraw(CDC* pDC)

{

    CDocument* pDoc = GetDocument();

    // TODO: add draw code here

    static BOOL   bBusy = FALSE; // 准备一个标志信号

    if(bBusy) return;           //如果忙,则返回

    bBusy = TRUE;                   //置标志为忙,下面开始场景绘制

    wglMakeCurrent(m_pDC->GetSafeHdc(), m_hRC); // 获取设备描述表

    // 清除颜色缓冲区和深度缓冲区

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    OnDrawGL();// 调用场景绘制函数

    glFinish();// 完成图形的绘制

    SwapBuffers(m_pDC->GetSafeHdc()); // 启用双缓冲

    bBusy = FALSE; // 绘制完毕,置标志为空闲

    wglMakeCurrent(NULL,NULL); // 释放OpenGL绘制描述表

}

int CGLEnabledView::OnCreate(LPCREATESTRUCT lpCreateStruct)的实现部分加入如下代码

int CGLEnabledView::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

       if (CView::OnCreate(lpCreateStruct) == -1)

              return -1;

       // TODO: Add your specialized creation code here

       m_pDC = new CClientDC(this);

       // 初始化OpenGL

       InitializeOpenGL(m_pDC);

       // 释放OpenGL绘制描述表

    wglMakeCurrent(NULL,NULL);

       return 0;

}

void CGLEnabledView::OnDestroy()的实现部分加入如下代码

void CGLEnabledView::OnDestroy()

{

       // 获得设备描述表的OpenGL绘制描述表

    wglMakeCurrent(m_pDC->GetSafeHdc(), m_hRC);

       // 释放绘制描述表

       if (m_hRC!=NULL) ::wglDeleteContext(m_hRC);

       if (m_hPalette)

              DeleteObject(m_hPalette);//释放调色板

       // 释放Windows设备描述表

       if(m_pDC) delete m_pDC;

              CView::OnDestroy();

       // TODO: Add your message handler code here

}

void CGLEnabledView::OnSize(UINT nType, int cx, int cy)的实现中添加如下代码

       void CGLEnabledView::OnSize(UINT nType, int cx, int cy)

{

       CView::OnSize(nType, cx, cy);

      

       // TODO: Add your message handler code here

       if ( 0 < cx && 0 < cy )

       {

              // 更新客户区,计算窗口的比例

              m_ClientRect.right = cx;

              m_ClientRect.bottom = cy;

              m_dAspectRatio=double(cx)/double(cy);

             

              // 获取OpenGL绘制描述表

              wglMakeCurrent(m_pDC->GetSafeHdc(), m_hRC);

              // 设置视口变换

              glViewport(0,0,cx,cy);

             

              // 设置透视变换

              glPushMatrix();

              glMatrixMode(GL_PROJECTION);

              glLoadIdentity();

              gluPerspective(40.0,m_dAspectRatio,0.1f, 10.0f);

              glTranslatef(0.0f,0.0f,-4.f);

              glMatrixMode(GL_MODELVIEW);

              glPopMatrix();

             

              // 释放OpenGL绘制描述表

              wglMakeCurrent(NULL,NULL);

             

              // 更新窗口内容

              Invalidate(TRUE);

       };

}

CGLEnabledView类上右击Add VirtualFunction添加PreCreateWindow虚函数,然后在BOOL CGLEnabledView::PreCreateWindow(CREATESTRUCT& cs)的实现中加入如下代码

BOOL CGLEnabledView::PreCreateWindow(CREATESTRUCT& cs)

{

       // TODO: Add your specialized code here and/or call the base class

////////////////////////////////////////////////////////////////////////////

//设置窗口风格

       //OpenGL要求

       cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;

       //多文档应用程序要求

       cs.lpszClass = AfxRegisterWndClass(CS_OWNDC | CS_HREDRAW | CS_VREDRAW);

/////////////////////////////////////////////////////////////////////////////      

       return CView::PreCreateWindow(cs);

}

CGLEnabledView上右击Add Member Function分别添加三个public类型的成员函数

       BOOL SetupPixelFormat();

       BOOL InitializeOpenGL(CDC* pDC);

       void SetLogicalPalette(void);

添加以上三个函数BOOL SetupPixelFormat();BOOL InitializeOpenGL(CDC* pDC); 以及void SetLogicalPalette(void);的实现。在CGLEnabledViewcpp文件中添加

/////////////////////////////////////////////////////////////////////

//                       设置逻辑调色板

//////////////////////////////////////////////////////////////////////

void CGLEnabledView::SetLogicalPalette(void)

{

    struct

    {

        WORD Version;

        WORD NumberOfEntries;

        PALETTEENTRY aEntries[256];

    } logicalPalette = { 0x300, 256 };

 

       BYTE reds[] = {0, 36, 72, 109, 145, 182, 218, 255};

       BYTE greens[] = {0, 36, 72, 109, 145, 182, 218, 255};

       BYTE blues[] = {0, 85, 170, 255};

 

    for (int colorNum=0; colorNum<256; ++colorNum)

    {

        logicalPalette.aEntries[colorNum].peRed =

            reds[colorNum & 0x07];

        logicalPalette.aEntries[colorNum].peGreen =

            greens[(colorNum >> 0x03) & 0x07];

        logicalPalette.aEntries[colorNum].peBlue =

            blues[(colorNum >> 0x06) & 0x03];

        logicalPalette.aEntries[colorNum].peFlags = 0;

    }

 

    m_hPalette = CreatePalette ((LOGPALETTE*)&logicalPalette);

}

 

 

//////////////////////////////////////////////////////////

//                                        初始化openGL场景

//////////////////////////////////////////////////////////

BOOL CGLEnabledView::InitializeOpenGL(CDC* pDC)

{

       m_pDC = pDC;

       SetupPixelFormat();

       //生成绘制描述表

       m_hRC = ::wglCreateContext(m_pDC->GetSafeHdc());

       //置当前绘制描述表

       ::wglMakeCurrent(m_pDC->GetSafeHdc(), m_hRC);

 

       return TRUE;

}

 

//////////////////////////////////////////////////////////

//                                        设置像素格式

BOOL CGLEnabledView::SetupPixelFormat()

{

       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                           // 忽略层,可见性和损毁掩模

       };   

       int pixelformat;

       pixelformat = ::ChoosePixelFormat(m_pDC->GetSafeHdc(), &pfd);//选择像素格式

       ::SetPixelFormat(m_pDC->GetSafeHdc(), pixelformat, &pfd);  //设置像素格式

       if(pfd.dwFlags & PFD_NEED_PALETTE)

              SetLogicalPalette();       //设置逻辑调色板

       return TRUE;

}

//////////////////////////////////////////////////////////

 

10 利用MFC Class Wizard CMDIOpenGLView类删除标准消息WM_DRAW以及Window虚函数PreCreateWindows的响应函数,并且删除cpp文件中的相应的实现部分。

11 修改CMDIOpenGLView类的继承关系,使之继承于CGLEnabledView类:首先应该在CMDIOpenGLView类的头文件中修改继承关系

class CMDIOpenGLView: public CGLEnabledView

其次,在CMDIOpenGLView类的实现文件中将以下两句的CView改为CGLEnabledView

IMPLEMENT_DYNCREATE(CMDIOpenGLView, CView)

BEGIN_MESSAGE_MAP(CMDIOpenGLView, CView) 要改变为

IMPLEMENT_DYNCREATE(CMDIOpenGLView, CGLEnabledView)

BEGIN_MESSAGE_MAP(CMDIOpenGLView, CGLEnabledView)

12 CMDIOpenGLView类的声明文件MDIOpenGLView.h中首先添加私有成员变量

///////////////////////////////////////////////////////////////////////////////

//添加私有成员变量

private:

       CPoint MouseDownPoint;

       double X_Angle;

       double Y_Angle;

 

其次在Class语句上面添加包含CGLEnabledView的头文件的语句

////////////////////////////////////////////////////////////////////////////////

//包含类CGLEnabledView的说明文件

#include "GLEnabledView.h"

 

最后,在CMDIOpenGLView类中添加改写CGLEnabledView类的场景绘制虚函数OnDrawGL()的声明

public:

//////////////////////////////////////////////////////////////////////////////////////

//改写CGLEnabledView类的场景绘制虚函数的声明

       void OnDrawGL();

//////////////////////////////////////////////////////////////////////////////////////

13 利用MFC Class Wizard CMDIOpenGLView类添加消息WM_LBUTTONDOWN以及WM_LBUTTONUPWM_MOUSEMOVE的响应函数。它们的实现分别如下:

void CMDIOpenGLView::OnLButtonDown(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

       // 记录鼠标的位置

       MouseDownPoint=point;

       // 捕捉鼠标的运动

       SetCapture();

       //CView::OnLButtonDown(nFlags, point);

}

 

void CMDIOpenGLView::OnLButtonUp(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

       // 鼠标抬起位置置于原点

       MouseDownPoint=CPoint(0,0);

       // 解除捕捉鼠标

       ReleaseCapture();

       //CView::OnLButtonUp(nFlags, point);

}

 

void CMDIOpenGLView::OnMouseMove(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

       // 检测是否捕捉鼠标

       if (GetCapture()==this)

       {

              // 旋转对象一个步长

              X_Angle+=double(point.y-MouseDownPoint.y)/3.6;

              Y_Angle+=double(point.x-MouseDownPoint.x)/3.6;

              // 更新场景

              Invalidate(TRUE);

              // 记下鼠标位置

              MouseDownPoint=point;

       };   

       //CView::OnMouseMove(nFlags, point);

}

 

14 CMDIOpenGLView的构造函数中对X_AngleY_Angle进行初始化

CMDIOpenGLView::CMDIOpenGLView()

{

       // TODO: add construction code here

/////////////////////////////////////////////////////////////////////////////

       //初始化成员变量

       X_Angle=0.0;

       Y_Angle=0.0;

//////////////////////////////////////////////////////////////////////////////

}

15 CMDIOpenGLViewcpp文件中添加虚函数OnDrawGL()的实现。

void CMDIOpenGLView::OnDrawGL()

{

       glPushMatrix();

       // 旋转对象一个给定的角度

       glRotated(X_Angle,1.0,0.0,0.0);

       glRotated(Y_Angle,0.0,1.0,0.0);

       glBegin(GL_LINES);

       // yellow x axis arrow

       glColor3f(1.f,1.f,0.f);

       glVertex3f(0.0f,0.0f,0.0f);

       glVertex3f(1.0f,0.0f,0.0f);

       glVertex3f(1.0f,0.0f,0.0f);

       glVertex3f(0.9f,0.1f,0.0f);

       glVertex3f(1.0f,0.0f,0.0f);

       glVertex3f(0.9f,-0.1f,0.0f);

       // cyan y axis arrow

       glColor3f(0.f,1.f,1.f);

       glVertex3f(0.0f,0.0f,0.0f);

       glVertex3f(0.0f,1.0f,0.0f);

       glVertex3f(0.0f,1.0f,0.0f);

       glVertex3f(0.1f,0.9f,0.0f);

       glVertex3f(0.0f,1.0f,0.0f);

       glVertex3f(-0.1f,0.9f,0.0f);

       // magenta z axis arrow

       glColor3f(1.f,0.f,1.f);

       glVertex3f(0.0f,0.0f,0.0f);

       glVertex3f(0.0f,0.0f,1.0f);

       glVertex3f(0.0f,0.0f,1.0f);

       glVertex3f(0.0f,0.1f,0.9f);

       glVertex3f(0.0f,0.0f,1.0f);

       glVertex3f(0.0f,-0.1f,0.9f);

       glEnd();

      

       glPopMatrix();

}

16 stdafx.h中包含有关OpenGL函数的头文件

 

////////////////////////////////////////////////////////////////////////////

// 包含有关OpenGL函数的头文件

#include <gl/gl.h>

#include <gl/glu.h>

#include <gl/glaux.h>

#include <gl/glut.h>

////////////////////////////////////////////////////////////////////////////

相关文章推荐

基于MFC 多文档的OpenGL实例

  • 2011年11月22日 00:12
  • 51KB
  • 下载

OpenGL在MFC单文档中的应用

OpenGL(Fancy_mage) (参考《实战OpenGL三维可视化系统开发与源码精解》,吕希奎,周小平著)一、OpenGL像素格式1、像素格式设置  像素格式是OpenGL窗口的重要属性,它包...

OpenGL MFC单文档环境配置(VS2010)

OpenGL MFC单文档环境配置 本机环境:WIN10    VS2010 环境配置:请查看上一篇博客 一、简介 Windows GDI是通过设备句柄(Device Context(...
  • MissXy_
  • MissXy_
  • 2017年07月21日 20:15
  • 223

OpenGL MFC单文档 实现轨迹球

OpenGL MFC单文档 实现轨迹球 前言:我是一个怀揣着伟大梦想的普通男生!结果就是,一有时间就幻想着自己的伟大梦想,忘了自己下一步该迈出左脚还是右脚。这不,只顾做梦了,时光可不...
  • MissXy_
  • MissXy_
  • 2017年07月26日 21:25
  • 156

openGL三维网格坐标,旋转,缩放,灯光设置,纹理读取,模型读取(MFC单文档)

openGL三维网格坐标,旋转,缩放,灯光设置,纹理读取,模型读取(MFC单文档) 源码下载链接:链接:http://pan.baidu.com/s/1slANShZ 密码:hb...

MFC单文档程序中搭建OpenGL框架

一、简介 Windows GDI是通过设备句柄(Device Context(设备描述表)以下简称"DC")来绘图,而OpenGL则需要绘制环境(Rendering Context(着色描述表)...

MFC+OpenGL单文档制作三维图像

GDI:图形设备接口 DC:设备描述表 RC:着色描述表 OpenGL:专业图形程序接口 画图原理:每个GDI命令需要传给它一个DC,OpenGL需要绘制环境(RC), RC与特定的DC联系起来,完成...

MFC单文档结构,实现OpenGL的绘图,移动,旋转,缩放

MFC单文档结构,实现OpenGL的绘图,移动,旋转,缩放 基本知识: Windows应用程序是使用设备描述表(DeviceContext,简写为"DC")进行图形的绘制输出, ...
  • yulinxx
  • yulinxx
  • 2014年09月13日 23:05
  • 2294

基于MFC单文档的OpenGL环境配置

  • 2013年03月09日 14:58
  • 24.96MB
  • 下载

在MFC单文档中使用OpenGL

  • 2012年10月17日 15:55
  • 39KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:mfc opengl 多文档
举报原因:
原因补充:

(最多只允许输入30个字)