支持HW团队,就支付宝领取下面的红包吧!(2018年3月31前,就几毛,也会几块,可以和其他红包叠加使用),你领取消费,HW有奖励。红包使用无条件限制,有条件请注意是不是有病毒。

小伙伴们,给大家发红包喽!人人可领,领完就能用。祝大家领取的红包金额大大大!#吱口令#长按复制此消息,打开支付宝就能领取!er1OEj73Uj

登入 注册 | 验证
| 搜索

博主:初学MPEG

初学MPEG 本博客-采用Python的web框架Django与Mysql数据库,致力于对Python、Django的了解 与研究
Django技术QQ群:XXXXXXX
Python技术QQ群:XXXXXXX

分类

关键字

本站最新博文

友情链接  

【转载】MFC之OpenGL多文档程序框架完整示例

类别:其他 状态:游客可见,可回,会员可关联(精华) 阅读:3965 评论:0 时间:九月 27, 2015, 12:29 p.m.
关键字:MFC opengl

 在多文档中绘制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: 在此添加绘制代码

        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:  在此添加您专用的创建代码
        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;

        // TODO: 在此处添加消息处理程序代码
        CView::OnDestroy();
}

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

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

        // TODO: 在此处添加消息处理程序代码
        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: 在此添加专用代码和/或调用基类
        ////////////////////////////////////////////////////////////////////////////
        //设置窗口风格
        //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()的声明

protected:
        //////////////////////////////////////////////////////////////////////////////////////
        //改写CGLEnabledView类的场景绘制虚函数的声明
        void OnDrawGL();
        //////////////////////////////////////////////////////////////////////////////////////

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

void CMDIOpenGLView::OnLButtonDown(UINT nFlags, CPoint point)
{
        // TODO: 在此添加消息处理程序代码和/或调用默认值
        // 记录鼠标的位置

        MouseDownPoint=point;

        // 捕捉鼠标的运动

        SetCapture();

        //CGLEnabledView::OnLButtonDown(nFlags, point);
}


void CMDIOpenGLView::OnLButtonUp(UINT nFlags, CPoint point)
{
        // TODO: 在此添加消息处理程序代码和/或调用默认值
        // 鼠标抬起位置置于原点

        MouseDownPoint=CPoint(0,0);

        // 解除捕捉鼠标

        ReleaseCapture();

        //CGLEnabledView::OnLButtonUp(nFlags, point);
}


void CMDIOpenGLView::OnMouseMove(UINT nFlags, CPoint point)
{
        // TODO: 在此添加消息处理程序代码和/或调用默认值
        // 检测是否捕捉鼠标
        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;

        };

        //CGLEnabledView::OnMouseMove(nFlags, point);
}

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

CMDIOpenGLView::CMDIOpenGLView()
{
        // TODO: 在此处添加构造代码
        /////////////////////////////////////////////////////////////////////////////
        //初始化成员变量
        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>
////////////////////////////////////////////////////////////////////////////

 

文件名 大小 时间 会员 费用 操作
glut and glaux.zip(良好) 234K288B 九月 27, 2015, 12:30 p.m. 初学MPEG 积分:0
荣誉:0
会币:0
下载
MDIOpenGL.rar(精华) 713K691B 九月 29, 2015, 11:19 p.m. 初学MPEG 积分:0
荣誉:0
会币:0
下载
 
 
操作:

Please Login (or Sign Up) to leave a comment