MFC MDI сплиттер с двумя графическими представлениями OpenGL не работает

Я хочу создать приложение, в котором приложение View будет разделено на 3D-модели OpenGL в двух разных видах, прикрепленных к Childframe с помощью сплиттера. Для этого я сделал родительский класс расширенным из класса представления, и внутри этого класса я инициализировал весь код, необходимый для 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

затем в классе childframe я добавил код разделителя и вызвал эти два класса в окне разделителя. Проблема в том, что код представления opengl работает нормально, но если я остановлю одну из инициализаций opengl, то отобразится другая. Я попробовал все, и я не могу отобразить две разные графические анимации OpenGL в обоих этих двух разных видах. Я проверил карту памяти HDC, и кажется, что оба класса используют parent по отношению к их динамическому объекту 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
#endifprotected:
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();

кое-как, как начальный код обновления родительского кода работает для его одного потомка, а не двух из них.

0

Решение

Редактировать: никакой причины быть не может wglMakeCurrent() Как я и думал вначале, вы, кажется, называете это достаточно.

Причиной может быть то, что вы называете oglInitialize() слишком много раз, однако. Это зависит от того, как вы создаете свои представления и разделители, но тот код, который вы не опубликовали. Один из способов исправить это — ограничить, сколько раз ваши представления будут фактически «первоначально обновляться».

Инициализируйте ваш hdc член до 0 в конструкторе (фактически всегда инициализировать все члены в конструкторах):

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

Выполните инициализацию ogl только один раз, когда hdc это 0:

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;
1

Другие решения

Хотя это может быть поздно, но вот мой ответ, который может помочь вам в будущем 🙂

в вызове функции Ontimer pdoc->UpdateAll(NULL,NULL,NULL) функция. pdoc — указатель на класс ваших документов. Он будет запрашивать все представления для обновления, и вы получите работающие оба окна :).

-1

По вопросам рекламы [email protected]