mfc opengl 多文档

14 篇文章 0 订阅

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

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

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

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

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

以下是具体的编程步骤:

0 建立工程MDIOpenGL添加一个新类CGLEnabledView,class type为MFC Class,Base Class为CView

1 给CGLEnabledView添加成员变量

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

       HGLRC m_hRC;                                // OpenGL渲染描述表

       CRect m_ClientRect;                          // 客户区的大小

       double m_dAspectRatio;                     // 窗口的比例

       HPALETTE    m_hPalette;                  //调色板

 

2 在CGLEnabledView类中添加Windows Message Handler处理WM_CREATE,WM_DESTROY,WM_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绘制描述表

}

4 在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;

}

5 在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

}

6 在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);

       };

}

7 在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);

}

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

       BOOL SetupPixelFormat();

       BOOL InitializeOpenGL(CDC* pDC);

       void SetLogicalPalette(void);

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

/

//                       设置逻辑调色板

//

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_LBUTTONUP和WM_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_Angle,Y_Angle进行初始化

CMDIOpenGLView::CMDIOpenGLView()

{

       // TODO: add construction code here

/

       //初始化成员变量

       X_Angle=0.0;

       Y_Angle=0.0;

//

}

15 在CMDIOpenGLView的cpp文件中添加虚函数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>

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值