Table of Contents

2. Embedding VglTools in Application Frameworks

Graphics libraries generally communicate intimately with the application framework. There is a need to draw multiple views in application defined windows and interact in an application specific way to user input.

Table of Contents

2.1 Embedded, In-Window, Applications

This example illustrates how one connects an OpenGLDev object to an existing window. This process is typical of building component applications (such as finite element analysis systems) which are designed to be embedded in a host application (such as a CAD system). In this case, the host application provides a handle to the window system and a callback when graphics primtives generated by the embedded application are meant to be drawn. Usually the lighting and transformations are set by the host application and the embedded application provides 3D graphics primitives and attributes.
   vgl_OpenGLDev  *opengldev;
   vgl_DrawFun *dfdev;
   Vint iparam;

                   /* Once at the beginning */ 
                   /* a class method */ 
   vgl_OpenGLDevConnectWIN ();

                   /* create drawing functions */
   dfdev = vgl_DrawFunBegin();

                   /* create device objects and load drawing functions */
   opengldev = vgl_OpenGLDevBegin();
   vgl_OpenGLDevDrawFun (opengldev,dfdev);

                   /* use current graphics context of application */ 
   iparam = VGL_ON;
   vgl_DrawFunConfigureWindow (dfdev,VGL_WINDOWUSECONTEXT,&iparam);
                   /* connect to given Window window handle */ 
   vgl_DrawFunConnectWindow (dfdev,hWnd);

...

                   /* Now each time you need to draw to the window */ 
   vgl_DrawFunConfigureWindow (dfdev,VGL_WINDOWSTATEINIT,NULL);

                   /* all drawing occurs here */ 
.
.
.


                   /* when all drawing is complete */ 
   vgl_DrawFunConfigureWindow (dfdev,VGL_WINDOWSTATETERM,NULL);
...
                   /* Once at the end */ 
                   /* disconnect from window */ 
   vgl_DrawFunDisconnectWindow (dfdev);

                   /* destroy objects */ 
   vgl_OpenGLDevEnd (opengldev);
   vgl_DrawFunEnd (dfdev);

                   /* disconnect from window system */ 
   vgl_OpenGLDevDisconnect ();


Table of Contents

2.2 Creating a Simple Microsoft MFC Application

This example illustrates how to use VglTools with Microsoft's MFC class library. The example shows the modifications required to the default application view files. In addition to the default message handlers for OnDraw and PreCreateWindow, it is necessary to add functions for the following messages: The MFC application uses OpenGL to draw "Hello World" in the window. By using an OpenGLDev object and a DrawFun object, very little OpenGL specific code needs to be written.


Figure 1-3, Output from a Simple Microsoft MFC Application

2.2.1 Editing VglView.h

The editing required in the VglView.h file involves adding VglTools specific include files and two protected data members: pointers to an OpenGLDev object and a DrawFun object.
//
//          VglTools includes
//
#include "base/base.h"
#include "vgl/vgl.h"
 .
 .
protected:
//
//          VglTools objects;
//
   vgl_OpenGLDev *m_ogldev;
   vgl_DrawFun *m_dfdv;

2.2.2 Editing VglView.cpp

The editing required in the VglView.cpp file involves adding to the message handlers mentioned above as well as the class constructor, CVglView(), and destuctor, ~CVglView(). Only the code fragments needed to be added are shown below.

In the class constructor, CVglView(), connect the OpenGLDev module to Windows, instance OpenGLDev and DrawFun objects and load OpenGLDev drawing functions.

   vgl_OpenGLDevConnectWIN ();
   m_ogldev = vgl_OpenGLDevBegin ();
   m_dfdv = vgl_DrawFunBegin ();
   vgl_OpenGLDevDrawFun (m_ogldev,m_dfdv);

In the class destructor, ~CVglView(), destroy the OpenGLDev and DrawFun objects and disconnect the OpenGLDev module from Windows.

   vgl_OpenGLDevEnd (m_ogldev);
   vgl_DrawFunEnd (m_dfdv);
   vgl_OpenGLDevDisconnect ();

In PreCreateWindow, the OpenGL window must be created with the WS_CLIPSIBLINGS and WS_CLIPCHILDREN style. In addition, do not set the CS_PARENTDC bit.

   cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;

In OnEraseBkgnd, since OpenGL will be erasing the background with a Clear drawing function, there is no reason for Windows to do it. This is done by commenting out the original return and returning with a 1 always.

// return CView::OnEraseBkgnd(pDC);
   return 1;

In OnCreate, connect the MFC window, m_hWnd, to the OpenGL interface. At this point the MFC window should not be drawn to, wait for the first WM_SIZE message (OnSize function) before drawing.

   vgl_DrawFunConnectWindow(m_dfdv,(Vword)m_hWnd);

In OnDestroy, disconnect the MFC window from the OpenGL interface.

   vgl_DrawFunDisconnectWindow (m_dfdv);

In OnSize, inform the OpenGL interface that the window has been resized. This will occur when the MFC window initially assumes its original size and then any time the window is resized by the user. The call to vgl_DrawFunSetWindow is only needed if a multiple view interface is used and multiple instances of OpenGLDev objects (one for each view window) have been generated.

   vgl_DrawFunSetWindow (m_dfdv);
   vgl_DrawFunResize (m_dfdv);

In OnDraw, place the code necessary to render the scene. In this case we clear the background to blue and render "Hello World" in red anchored at the center of the screen. Call vgl_DrawFunSwap to swap the buffers. Again, the call to vgl_DrawFunSetWindow is only needed if a multiple view interface is used.

   Vfloat c[3];
   Vfloat x[3];
 .
 .
   vgl_DrawFunSetWindow (m_dfdv);
 .
 .
   c[0] = 0.; c[1] = 0.; c[2] = 1.;
   vgl_DrawFunBackColor (m_dfdv,c);
   vgl_DrawFunClear (m_dfdv);
   c[0] = 1.;  c[1] = 0.;  c[2] = 0.;
   vgl_DrawFunColor (m_dfdv,c);
   x[0] = 0.;  x[1] = 0.;  x[2] = 0.;
   vgl_DrawFunText (m_dfdv,x,"Hello World");
   vgl_DrawFunSwap (m_dfdv);

The source to this example resides in the files VglView.cpp and VglView.h in the exam directory.

// VglView.cpp : implementation of the CVglView class
//

#include "stdafx.h"
#include "Vgl.h"

#include "VglDoc.h"
#include "VglView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CVglView

IMPLEMENT_DYNCREATE(CVglView, CView)

BEGIN_MESSAGE_MAP(CVglView, CView)
	//{{AFX_MSG_MAP(CVglView)
	ON_WM_CREATE()
	ON_WM_DESTROY()
	ON_WM_SIZE()
	ON_WM_ERASEBKGND()
	//}}AFX_MSG_MAP
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CVglView construction/destruction

CVglView::CVglView()
{
	// TODO: add construction code here
//
//          Connect to Win32 and instance Vgl objects
//
	vgl_OpenGLDevConnectWIN ();
	m_ogldev = vgl_OpenGLDevBegin ();
	m_dfdv = vgl_DrawFunBegin ();
	vgl_OpenGLDevDrawFun (m_ogldev,m_dfdv);
}

CVglView::~CVglView()
{
//
//          Destroy objects and disconnect from Win32
//
	vgl_OpenGLDevEnd (m_ogldev);
	vgl_DrawFunEnd (m_dfdv);
	vgl_OpenGLDevDisconnect ();
}

BOOL CVglView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

//
//          OpenGL window must be created with the following flags
//
	cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
	return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CVglView drawing

void CVglView::OnDraw(CDC* pDC)
{
	Vfloat c[3];
	Vfloat x[3];

	CVglDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	// TODO: add draw code for native data here
//
//          Make sure in a multiple view interface that drawing goes
//          to the correct window.
//
	vgl_DrawFunSetWindow (m_dfdv);	
//
//          Draw Hello World
//
	c[0] = 0.; c[1] = 0.; c[2] = 1.;
	vgl_DrawFunBackColor (m_dfdv,c);
	vgl_DrawFunClear (m_dfdv);
	c[0] = 1.;  c[1] = 0.;  c[2] = 0.;
	vgl_DrawFunColor (m_dfdv,c);
	x[0] = 0.;  x[1] = 0.;  x[2] = 0.;
	vgl_DrawFunText (m_dfdv,x,"Hello World");
	vgl_DrawFunSwap (m_dfdv);
}

/////////////////////////////////////////////////////////////////////////////
// CVglView printing

BOOL CVglView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CVglView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void CVglView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////
// CVglView diagnostics

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

void CVglView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CVglDoc* CVglView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CVglDoc)));
	return (CVglDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CVglView message handlers

int CVglView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	// TODO: Add your specialized creation code here
//
//          Connect to MFC window
//
	vgl_DrawFunConnectWindow(m_dfdv,(Vword)m_hWnd);
	return 0;
}

void CVglView::OnDestroy() 
{
	CView::OnDestroy();
	
	// TODO: Add your message handler code here
//
//          Disconnect from window
//
	vgl_DrawFunDisconnectWindow (m_dfdv);	
}

void CVglView::OnSize(UINT nType, int cx, int cy) 
{
	CView::OnSize(nType, cx, cy);
	
	// TODO: Add your message handler code here
//
//          Resize
//
	vgl_DrawFunSetWindow (m_dfdv);	
	vgl_DrawFunResize (m_dfdv);
}

BOOL CVglView::OnEraseBkgnd(CDC* pDC) 
{
	// TODO: Add your message handler code here and/or call default
//
//          OpenGL will clear window, tell MFC not to
//
	
//	return CView::OnEraseBkgnd(pDC);
	return 1;
}
// VglView.h : interface of the CVglView class
//
/////////////////////////////////////////////////////////////////////////////

#if !defined(AFX_VGLVIEW_H__93035A8C_7819_11D1_B2AA_0060979C3AE3__INCLUDED_)
#define AFX_VGLVIEW_H__93035A8C_7819_11D1_B2AA_0060979C3AE3__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
//
//          VglTools includes
//
#include "base/base.h"
#include "vgl/vgl.h"

class CVglView : public CView
{
protected: // create from serialization only
	CVglView();
	DECLARE_DYNCREATE(CVglView)

// Attributes
public:
	CVglDoc* GetDocument();

// Operations
public:

// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CVglView)
	public:
	virtual void OnDraw(CDC* pDC);  // overridden to draw this view
	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
	protected:
	virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
	virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
	virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
	//}}AFX_VIRTUAL

// Implementation
public:
	virtual ~CVglView();
#ifdef _DEBUG
	virtual void AssertValid() const;
	virtual void Dump(CDumpContext& dc) const;
#endif

protected:
//
//          VglTools objects;
//
	vgl_OpenGLDev *m_ogldev;
	vgl_DrawFun *m_dfdv;

// Generated message map functions
protected:
	//{{AFX_MSG(CVglView)
	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
	afx_msg void OnDestroy();
	afx_msg void OnSize(UINT nType, int cx, int cy);
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

#ifndef _DEBUG  // debug version in VglView.cpp
inline CVglDoc* CVglView::GetDocument()
   { return (CVglDoc*)m_pDocument; }
#endif

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

//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_VGLVIEW_H__93035A8C_7819_11D1_B2AA_0060979C3AE3__INCLUDED_)