0

我想创建一个应用程序,其中应用程序视图将在使用拆分器附加到 Childframe 的两个不同视图中与 OpenGL 3d 模型分开。为此,我创建了一个从视图类扩展的父类,并且在这个类中我已经初始化了所有 opengl 所需的代码。

例如

#pragma once

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

#define IL   //when you dont want to use image library and you want to load everything by your self then remove this

// COpenGlView view

class COpenGlView : public CView
{
    DECLARE_DYNCREATE(COpenGlView)

protected:
    void oglBeginRendering();
    COpenGlView();           // protected constructor used by dynamic creation
    virtual ~COpenGlView();

/*******************/
        /* Private Members */
        /*******************/
        // Window information
        CWnd  *hWnd;
        HDC   hdc;          
        HGLRC hrc;          
        int   m_nPixelFormat;
        CRect m_rect;
        CRect m_oldWindow;
        CRect m_originalRect;
public:
        /******************/
        /* Public Members */
        /******************/
        UINT_PTR m_unpTimer;
        // View information variables
        float    m_fLastX;
        float    m_fLastY;
        float    m_fPosX;
        float    m_fPosY;
        float    m_fZoom;
        float    m_fRotX;
        float    m_fRotY;
        bool     m_bIsMaximized;

        float    m_fZoomSpeed;
        float    m_fRotateSpeed;
        GLuint texture[1];


        void oglCreate(CRect rect, CWnd *parent,CString strWindowName=L"OpenGl");
        virtual void oglInitialize(void);
        virtual void oglDrawScene(void);
        float   randFloat(const float& min, const float& max);
        int     randInt(const int& min, const int& max);

        void Reset();


        virtual void OnDraw(CDC* pDC);      // overridden to draw this view

#ifdef _DEBUG
    virtual void AssertValid() const;
#ifndef _WIN32_WCE
    virtual void Dump(CDumpContext& dc) const;
#endif
#endif

protected:
    DECLARE_MESSAGE_MAP()
public:
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    afx_msg void OnPaint();
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg void OnTimer(UINT_PTR nIDEvent);
    virtual void OnInitialUpdate();
};

这是cpp

// OpenGlView.cpp : implementation file
//

#include "stdafx.h"

#include "OpenGlView.h"



// COpenGlView

IMPLEMENT_DYNCREATE(COpenGlView, CView)

COpenGlView::COpenGlView()
{

    m_fPosX = 0.0f;     // X position of model in camera view
    m_fPosY = 0.0f;     // Y position of model in camera view
    m_fZoom = 5.0f; // Zoom on model in camera view
    m_fRotX = 0.0f;     // Rotation on model in camera view
    m_fRotY = 0.0f;     // Rotation on model in camera view
    m_fZoomSpeed=0.05f;
    m_fRotateSpeed = 0.05f;
    m_bIsMaximized = false;

}

COpenGlView::~COpenGlView()
{
}

void COpenGlView::Reset()
{
    m_fPosX = 0.0f;     // X position of model in camera view
    m_fPosY = 0.0f;     // Y position of model in camera view
    m_fZoom = 5.0f; // Zoom on model in camera view
    m_fRotX = 0.0f;     // Rotation on model in camera view
    m_fRotY = 0.0f;     // Rotation on model in camera view
    m_fZoomSpeed=0.05f;
    m_fRotateSpeed = 0.05f;
    m_bIsMaximized = false;

}

BEGIN_MESSAGE_MAP(COpenGlView, CView)
    ON_WM_CREATE()
    ON_WM_PAINT()
    ON_WM_MOUSEMOVE()
    ON_WM_SIZE()
    ON_WM_TIMER()
END_MESSAGE_MAP()


// COpenGlView drawing

void COpenGlView::OnDraw(CDC* pDC)
{
    CDocument* pDoc = GetDocument();
    // TODO: add draw code here
}


// COpenGlView diagnostics

#ifdef _DEBUG
void COpenGlView::AssertValid() const
{
    CView::AssertValid();
}

#ifndef _WIN32_WCE
void COpenGlView::Dump(CDumpContext& dc) const
{
    CView::Dump(dc);
}
#endif
#endif //_DEBUG


// COpenGlView message handlers

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



    return 0;
}

void COpenGlView::OnPaint()
{
    //CPaintDC dc(this); // device context for painting
    // TODO: Add your message handler code here
    // Do not call CView::OnPaint() for painting messages

    ValidateRect(NULL);
}

void COpenGlView::OnMouseMove(UINT nFlags, CPoint point)
{
    int diffX = (int)(point.x - m_fLastX);
    int diffY = (int)(point.y - m_fLastY);
    m_fLastX  = (float)point.x;
    m_fLastY  = (float)point.y;


    // Left mouse button

    if (nFlags & MK_LBUTTON)
    {
        m_fRotX += (float)m_fRotateSpeed * diffY;

        if ((m_fRotX > 360.0f) || (m_fRotX < -360.0f))
        {
            m_fRotX = 0.0f;
        }

        m_fRotY += (float)0.5f * diffX;

        if ((m_fRotY > 360.0f) || (m_fRotY < -360.0f))
        {
            m_fRotY = 0.0f;
        }
    }

    // Right mouse button
    else if (nFlags & MK_RBUTTON)
    {
        m_fZoom -= (float)m_fZoomSpeed * diffY;
    }

    // Middle mouse button
    else if (nFlags & MK_MBUTTON)
    {
        m_fPosX += (float)0.05f * diffX;
        m_fPosY -= (float)0.05f * diffY;
    }


    OnDraw(NULL);


    CView::OnMouseMove(nFlags, point);
}

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

    if (0 >= cx || 0 >= cy || nType == SIZE_MINIMIZED) return;

    // Map the OpenGL coordinates.
    glViewport(0, 0, cx, cy);

    // Projection view
    glMatrixMode(GL_PROJECTION);

    glLoadIdentity();

    // Set our current view perspective
    gluPerspective(35.0f, (float)cx / (float)cy, 0.01f, 2000.0f);

    // Model view
    glMatrixMode(GL_MODELVIEW);

    switch (nType)
    {
        // If window resize token is "maximize"
        case SIZE_MAXIMIZED:
        {
            // Get the current window rect
            GetWindowRect(m_rect);

            // Move the window accordingly
            MoveWindow(6, 6, cx - 14, cy - 14);

            // Get the new window rect
            GetWindowRect(m_rect);

            // Store our old window as the new rect
            m_oldWindow = m_rect;

            break;
        }

        // If window resize token is "restore"
        case SIZE_RESTORED:
        {
            // If the window is currently maximized
            if (m_bIsMaximized)
            {
                // Get the current window rect
                GetWindowRect(m_rect);

                // Move the window accordingly (to our stored old window)
                MoveWindow(m_oldWindow.left, m_oldWindow.top - 18, m_originalRect.Width() - 4, m_originalRect.Height() - 4);

                // Get the new window rect
                GetWindowRect(m_rect);

                // Store our old window as the new rect
                m_oldWindow = m_rect;
            }

            break;
        }
    }
}


void COpenGlView::oglBeginRendering()
{
    SetTimer(1, 1, 0);
}

void COpenGlView::OnTimer(UINT_PTR nIDEvent)
{
    switch (nIDEvent)
    {
        case 1:
        {
            // Clear color and depth buffer bits
            wglMakeCurrent(hdc, hrc);

            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

            // Draw OpenGL scene
            oglDrawScene();

            // Swap buffers
            SwapBuffers(hdc);

            glFlush();
            wglMakeCurrent(NULL, NULL);



            break;
        }

        default:
            break;
    }


    CView::OnTimer(nIDEvent);
}

void COpenGlView::OnInitialUpdate()
{
    CView::OnInitialUpdate();

    COpenGlView::oglInitialize();
    // TODO: Add your specialized code here and/or call the base class
}


void COpenGlView::oglCreate(CRect rect, CWnd *parent,CString strWindowName)
{
    CString className = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW | CS_OWNDC, NULL, (HBRUSH)GetStockObject(BLACK_BRUSH), NULL);

    CreateEx(0, className,strWindowName, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, rect, parent, 0);

    // Set initial variables' values
    m_oldWindow    = rect;
    m_originalRect = rect;

    hWnd = parent;

    GLenum s = glGetError();

}

void COpenGlView::oglInitialize(void)
{
    // Initial Setup:
    //
    static PIXELFORMATDESCRIPTOR pfd =
    {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,
        PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
        PFD_TYPE_RGBA,
        32, // bit depth
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        16, // z-buffer depth
        0, 0, 0, 0, 0, 0, 0,
    };


    // Get device context only once.
    //hdc = GetDC()->m_hDC;

    // Pixel format.
    m_nPixelFormat = ChoosePixelFormat(hdc, &pfd);
    SetPixelFormat(hdc, m_nPixelFormat, &pfd);

    // Create the OpenGL Rendering Context.
    hrc = wglCreateContext(hdc);
    wglMakeCurrent(hdc, hrc);

    // Basic Setup:
    //
    // Set color to use when clearing the background.

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClearDepth(1.0f);

    // Turn on backface culling
    glFrontFace(GL_CCW);
    glCullFace(GL_BACK);

    // Turn on depth testing

    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);

    GLenum a = glGetError();


    OnDraw(NULL);

    //wglMakeCurrent(NULL, NULL);
}

void COpenGlView::oglDrawScene(void)
{
    // Wireframe Mode

    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

    glBegin(GL_QUADS);
            // Front Side
            glVertex3f( 1.0f,  1.0f, 1.0f);
            glVertex3f(-1.0f,  1.0f, 1.0f);
            glVertex3f(-1.0f, -1.0f, 1.0f);
            glVertex3f( 1.0f, -1.0f, 1.0f);

            // Back Side
            glVertex3f(-1.0f, -1.0f, -1.0f);
            glVertex3f(-1.0f,  1.0f, -1.0f);
            glVertex3f( 1.0f,  1.0f, -1.0f);
            glVertex3f( 1.0f, -1.0f, -1.0f);

            // Top Side
            glVertex3f( 1.0f, 1.0f,  1.0f);
            glVertex3f( 1.0f, 1.0f, -1.0f);
            glVertex3f(-1.0f, 1.0f, -1.0f);
            glVertex3f(-1.0f, 1.0f,  1.0f);

            // Bottom Side
            glVertex3f(-1.0f, -1.0f, -1.0f);
            glVertex3f( 1.0f, -1.0f, -1.0f);
            glVertex3f( 1.0f, -1.0f,  1.0f);
            glVertex3f(-1.0f, -1.0f,  1.0f);

            // Right Side
            glVertex3f( 1.0f,  1.0f,  1.0f);
            glVertex3f( 1.0f, -1.0f,  1.0f);
            glVertex3f( 1.0f, -1.0f, -1.0f);
            glVertex3f( 1.0f,  1.0f, -1.0f);

            // Left Side
            glVertex3f(-1.0f, -1.0f, -1.0f);
            glVertex3f(-1.0f, -1.0f,  1.0f);
            glVertex3f(-1.0f,  1.0f,  1.0f);
            glVertex3f(-1.0f,  1.0f, -1.0f);
    glEnd();

    glLoadIdentity();

    glTranslatef(0.0f, 0.0f, -m_fZoom);
    glTranslatef(m_fPosX, m_fPosY, 0.0f);
    glRotatef(m_fRotX, 1.0f, 0.0f, 0.0f);
    glRotatef(m_fRotY, 0.0f, 1.0f, 0.0f);

    GLenum a = glGetError();

}


//--------------------------------------------------------

// Get an random integer within a specified range

//--------------------------------------------------------

int COpenGlView::randInt(const int& min, const int& max) {
    return ((rand()%(int)(((max) + 1)-(min)))+ (min)); 
}

//--------------------------------------------------------

// Get a random float within a specified range

//--------------------------------------------------------

float COpenGlView::randFloat(const float& min, const float& max) {
    float range = max - min;
    float num = range * rand() / RAND_MAX;
    return (num + min);
}

然后我从同一个类类中扩展了另外两个视图类

C3dRightView : public COpenGlView 

C3dRightView : public COpenGlView 

然后在子框架类中我添加了拆分器代码并在拆分器窗口中调用了这两个类。问题是两个opengl视图代码都可以正常工作,但是如果我停止opengl的初始化之一,那么另一个会显示。我尝试了一切,但我无法在这两个不同的视图中显示两个不同的图形 opengl 动画。我检查了 HDC 内存映射,似乎两个类都在使用父类来处理它们的动态 hdc 对象,但是如果我停止一个代码,那么其他视图会正确显示。

详细课程如下

class C3dRightView : public COpenGlView
{
    DECLARE_DYNCREATE(C3dRightView)

protected:
    GLuint m_left_texture[53];

    C3dRightView();           // protected constructor used by dynamic creation
    virtual ~C3dRightView();

public:
    virtual void OnDraw(CDC* pDC);      // overridden to draw this view
#ifdef _DEBUG
    virtual void AssertValid() const;
#ifndef _WIN32_WCE
    virtual void Dump(CDumpContext& dc) const;
#endif
#endif


protected:
    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnPaint();
    virtual void OnInitialUpdate();

    void oglDrawScene(void);
    void oglInitialize(void);
    afx_msg void OnTimer(UINT_PTR nIDEvent);
};


void C3dRightView::OnPaint()
{
    CPaintDC dc(this); // device context for painting
    // TODO: Add your message handler code here
    // Do not call CView::OnPaint() for painting messages
}



void C3dRightView::OnInitialUpdate()
{
    hdc = C3dRightView::GetDC()->m_hDC;

    /** If i open below code then left view stop displaying model **/
        COpenGlView::OnInitialUpdate();
        oglInitialize();
    //-=-=-=-=-=-=-==--=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

    oglBeginRendering();
    // TODO: Add your specialized code here and/or call the base class
}


void C3dRightView::oglInitialize(void)
{
    COpenGlView::oglInitialize();

}
void C3dRightView::oglDrawScene(void)
{
    // Wireframe Mode

    glShadeModel(GL_SMOOTH);    

    glClearColor(0.0f, 1.0f, 1.0f, 0.0f);

    glLoadIdentity();
    //glTranslatef(0.0f, 0.0f, -m_fZoom);//this is for zoom using left mouse click but no placing
    glTranslatef(m_fPosX, m_fPosY,-m_fZoom); // this is for placing + zooming using middle scroll button mouse click

    glRotatef(m_fRotX, 1.0f, 0.0f, 0.0f);//these two for mouse movement
    glRotatef(m_fRotY, 0.0f, 1.0f, 0.0f);
    glRotated(90,0.0f, 0.0f, -1.0f);
    glRotatef(180,1.0f,0,0.0f);
    GLenum a = glGetError();

    glBegin(GL_TRIANGLES);                              // Start Drawing A Triangle
        glColor3f(1.0f,0.0f,0.0f);                      // Red
        glVertex3f( 0.0f, 1.0f, 0.0f);                  // Top Of Triangle (Front)
        glColor3f(0.0f,1.0f,0.0f);                      // Green
        glVertex3f(-1.0f,-1.0f, 1.0f);                  // Left Of Triangle (Front)
        glColor3f(0.0f,0.0f,1.0f);                      // Blue
        glVertex3f( 1.0f,-1.0f, 1.0f);                  // Right Of Triangle (Front)
        glColor3f(1.0f,0.0f,0.0f);                      // Red
        glVertex3f( 0.0f, 1.0f, 0.0f);                  // Top Of Triangle (Right)
        glColor3f(0.0f,0.0f,1.0f);                      // Blue
        glVertex3f( 1.0f,-1.0f, 1.0f);                  // Left Of Triangle (Right)
        glColor3f(0.0f,1.0f,0.0f);                      // Green
        glVertex3f( 1.0f,-1.0f, -1.0f);                 // Right Of Triangle (Right)
        glColor3f(1.0f,0.0f,0.0f);                      // Red
        glVertex3f( 0.0f, 1.0f, 0.0f);                  // Top Of Triangle (Back)
        glColor3f(0.0f,1.0f,0.0f);                      // Green
        glVertex3f( 1.0f,-1.0f, -1.0f);                 // Left Of Triangle (Back)
        glColor3f(0.0f,0.0f,1.0f);                      // Blue
        glVertex3f(-1.0f,-1.0f, -1.0f);                 // Right Of Triangle (Back)
        glColor3f(1.0f,0.0f,0.0f);                      // Red
        glVertex3f( 0.0f, 1.0f, 0.0f);                  // Top Of Triangle (Left)
        glColor3f(0.0f,0.0f,1.0f);                      // Blue
        glVertex3f(-1.0f,-1.0f,-1.0f);                  // Left Of Triangle (Left)
        glColor3f(0.0f,1.0f,0.0f);                      // Green
        glVertex3f(-1.0f,-1.0f, 1.0f);                  // Right Of Triangle (Left)
    glEnd();    

}

第二个视图文件是这样的

class C3dLeftView : public COpenGlView
{
    DECLARE_DYNCREATE(C3dLeftView)

protected:
    GLuint m_left_texture[53];
    C3dLeftView();           // protected constructor used by dynamic creation
    virtual ~C3dLeftView();

public:
    virtual void OnDraw(CDC* pDC);      // overridden to draw this view
#ifdef _DEBUG
    virtual void AssertValid() const;
#ifndef _WIN32_WCE
    virtual void Dump(CDumpContext& dc) const;
#endif
#endif

protected:
    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnPaint();
    virtual void OnInitialUpdate();

    void oglDrawScene(void);
    void oglInitialize(void);
    afx_msg void OnTimer(UINT_PTR nIDEvent);
};


void C3dLeftView::OnPaint()
{
    CPaintDC dc(this); // device context for painting
    // TODO: Add your message handler code here
    // Do not call CView::OnPaint() for painting messages
}

void C3dLeftView::OnInitialUpdate()
{
    hdc = C3dLeftView::GetDC()->m_hDC;
    COpenGlView::OnInitialUpdate();
    oglInitialize();
    oglBeginRendering();
    // TODO: Add your specialized code here and/or call the base class
}


void C3dLeftView::oglInitialize(void)
{
    COpenGlView::oglInitialize();


}
void C3dLeftView::oglDrawScene(void)
{
    glShadeModel(GL_SMOOTH);    

    glClearColor(0.0f, 1.0f, 0.0f, 1.0f);

    glLoadIdentity();
    //glTranslatef(0.0f, 0.0f, -m_fZoom);//this is for zoom using left mouse click but no placing
    glTranslatef(m_fPosX, m_fPosY,-m_fZoom); // this is for placing + zooming using middle scroll button mouse click

    glRotatef(m_fRotX, 1.0f, 0.0f, 0.0f);//these two for mouse movement
    glRotatef(m_fRotY, 0.0f, 1.0f, 0.0f);
    glRotated(90,0.0f, 0.0f, -1.0f);
    glRotatef(180,1.0f,0,0.0f);
    GLenum a = glGetError();

    glBegin(GL_TRIANGLES);                              // Start Drawing A Triangle
        glColor3f(1.0f,0.0f,0.0f);                      // Red
        glVertex3f( 0.0f, 1.0f, 0.0f);                  // Top Of Triangle (Front)
        glColor3f(0.0f,1.0f,0.0f);                      // Green
        glVertex3f(-1.0f,-1.0f, 1.0f);                  // Left Of Triangle (Front)
        glColor3f(0.0f,0.0f,1.0f);                      // Blue
        glVertex3f( 1.0f,-1.0f, 1.0f);                  // Right Of Triangle (Front)
        glColor3f(1.0f,0.0f,0.0f);                      // Red
        glVertex3f( 0.0f, 1.0f, 0.0f);                  // Top Of Triangle (Right)
        glColor3f(0.0f,0.0f,1.0f);                      // Blue
        glVertex3f( 1.0f,-1.0f, 1.0f);                  // Left Of Triangle (Right)
        glColor3f(0.0f,1.0f,0.0f);                      // Green
        glVertex3f( 1.0f,-1.0f, -1.0f);                 // Right Of Triangle (Right)
        glColor3f(1.0f,0.0f,0.0f);                      // Red
        glVertex3f( 0.0f, 1.0f, 0.0f);                  // Top Of Triangle (Back)
        glColor3f(0.0f,1.0f,0.0f);                      // Green
        glVertex3f( 1.0f,-1.0f, -1.0f);                 // Left Of Triangle (Back)
        glColor3f(0.0f,0.0f,1.0f);                      // Blue
        glVertex3f(-1.0f,-1.0f, -1.0f);                 // Right Of Triangle (Back)
        glColor3f(1.0f,0.0f,0.0f);                      // Red
        glVertex3f( 0.0f, 1.0f, 0.0f);                  // Top Of Triangle (Left)
        glColor3f(0.0f,0.0f,1.0f);                      // Blue
        glVertex3f(-1.0f,-1.0f,-1.0f);                  // Left Of Triangle (Left)
        glColor3f(0.0f,1.0f,0.0f);                      // Green
        glVertex3f(-1.0f,-1.0f, 1.0f);                  // Right Of Triangle (Left)
    glEnd();    

    /*************************************************************************************/


}

如果在视图的 initialupdate 函数内的代码下方注释,则其他视图代码可以正常工作。

    COpenGlView::OnInitialUpdate();
    oglInitialize();

一些父代码的初始更新代码如何为其一个孩子而不是其中两个工作。

4

2 回答 2

1

编辑:没有原因不能wglMakeCurrent()像我最初想的那样,你似乎称之为够了。

原因可能是你打电话给你oglInitialize()的次数太多了。这取决于您如何创建视图和拆分器,但您没有发布该代码。解决它的一种方法是限制您的视图实际“初始更新”的次数。

在构造函数中将你的hdc成员初始化为 0(实际上总是在构造函数中初始化所有成员):

COpenGlView::COpenGlView()
{
    hdc = 0;
    // ... etc your stuff
}

hdc当为 0时,只进行一次 ogl 初始化:

void C3dRightView::OnInitialUpdate()
{
    if ( hdc == 0 )
    {
        hdc = GetDC()->m_hDC;
        COpenGlView::OnInitialUpdate();
        oglBeginRendering();
    }
}

这里也:

void C3dLeftView::OnInitialUpdate()
{
    if ( hdc == 0 )
    {
        hdc = GetDC()->m_hDC;
        COpenGlView::OnInitialUpdate();
        oglBeginRendering();
    }
}

我相信这应该有效。

Edit2:尝试了您的代码。C3dRightView::OnInitialUpdate不像我上面贴的。我不确定是什么弄乱了初始化。例如,以下修复 CChildFrame::OnCreateClient似乎有效:

if (!m_wndSplitter.CreateView( 0, 1, RUNTIME_CLASS(C3dRightView), CSize(cr.Width()/2, cr.Height()), pContext))
{
    MessageBox(L"Error setting up splitter frames!", L"Init Error!", MB_OK | MB_ICONERROR);
    return FALSE;
}

// had to add this line here:
m_wndSplitter.GetPane( 0, 1 )->SendMessage(WM_INITIALUPDATE);

return TRUE;
于 2012-11-13T21:58:14.947 回答
-1

即使可能会迟到,但这是我的答案,将来可以帮助您:)

在 Ontimer 函数中调用pdoc->UpdateAll(NULL,NULL,NULL)函数。pdoc 是指向您的文档类的指针。它将请求所有视图更新,并且您将让两个窗口工作:)。

于 2013-03-01T13:44:27.533 回答