![]() |
VR-Forces 4.0.4 Class Documentation
|
This example shows how to embed a VR-Vantage window in an MFC application.
All MFC applications create a class that derives from CWinApp, and overrides its InitInstance() and Run() methods as well as its virtual destructor to initialize, run, and tear down the application.
Declare ExampleMFCApp, which derives from CWinApp:
class ExampleMFCApp : public CWinApp
The first CWinApp method overridden is InitInstance():
virtual BOOL InitInstance()
It creates tbe VR-Vantage display engine:
myDe = new makVrv::DtDe();
It then calls a helper function, initMfc(), which registers the window creators:
initMfc();
InitInstance() then registers the OSG plugin:
makVrv::vrvOsg::init(*myDe);
It creates the main window by calling the helper function createMainWindow():
createMainWindow();
It initializes the display engine with a display engine initializer created by makeDeInitializer() (see below):
myDe->setDeInitializer(makeDeInitializer());
myDe->initialize();
InitInstance() the creates a DtTimedSection to track frame time during the Tick() function (see below):
myTimer = new DtTimedSection;
And finally, calls and returns the result of the base class InitInstance() method:
return CWinApp::InitInstance();
The other CWinApp method overridden is Run():
virtual int Run()
Run() needs to manage Windows messages. If a message exists, it calls PumpMessage(); and if PumpMessage() fails, the instance is terminated:
_AFX_THREAD_STATE* pState = AfxGetThreadState();
for(;;)
{
if (PeekMessage(&(pState->m_msgCur) , NULL , 0, 0, PM_NOREMOVE))
{
if (!PumpMessage())
{
return ExitInstance();
It calls the Tick() method when there are no Windows messages to process:
else
{
Tick();
}
ExampleMFCApp also overrides CWinApp's virtual destructor so that it can delete the objects created at initialization:
virtual ~ExampleMFCApp() { delete myDe; delete myTimer; }
The following helper methods are defined (and called from InitInstance() or Run()):
makVrv::DtDeInitializer makeDeInitializer()
makeDeInitializer sets up all the configuration information needed for the VR-Vantage display engine. It first creates an observer configuration specifying a name and using the defaults for all other observer parameters:
std::string observerName = "Observer 1"; makVrv::DtObserverConfiguration observerConfig(observerName);
It then creates a channel configuration, and tells it to use the observer configuration created above:
makVrv::DtChannelConfiguration channel; channel.setObserverName(observerName);
Next, it creates a window configuration, and tells it to be an embedded window and to use the channel configuration created above:
makVrv::DtWindowConfiguration windowConfig; windowConfig.setWindowType(makVrv::DtWindowConfiguration::EmbeddedWindow); windowConfig.channelConfigurations().add(channel);
Then a display configuration is created, using the window configuration created above:
std::string displayName = "Example VR-Vantage Embedded in MFC App"; makVrv::DtDisplayConfiguration displayConfig(displayName); displayConfig.windowConfigurations().add(windowConfig);
An input driver configuration is created next:
makVrv::DtInputDriverConfiguration inputConfig; inputConfig.setOptionalParameter( "windowDependent", "true" ); inputConfig.observerConfigurations().add(observerConfig);
Now that a display configuration and input driver configuration exist, they are used to create a display engine initializer, which is then returned:
makVrv::DtDeInitializer init; init.deConfiguration().displayConfigurations().add(displayConfig); init.setDisplayEngineName(displayName); init.setInputDriverConfiguration( inputConfig );
void initMfc()
initMfc() registers creators for the main window (DtMfcMainWindow, derived from CFrameWnd and DtDeMainWindow):
makVrv::DtDeMainWindowProvider::registerInstance(*myDe, new DtMfcMainWindowProvider(*myDe));
and the embedded OSG window (DtEmbeddedMfcOsgWindow, derived from CWnd and DtOsgWindow):
makVrv::DtWindowFactory::instance(*myDe).setCreator( makVrv::DtWindowConfiguration::EmbeddedWindow, new DtEmbeddedMfcOsgWindowCreator);
void createMainWindow()
createMainWindow() gets the window provider:
makVrv::DtDeMainWindowProvider& windowProvider = makVrv::DtDeMainWindowProvider::instance(*myDe);
and then creates the new DtMfcMainWindow by calling the window provider's igMainWindow() accessor (which creates the main window since it doesn't yet exist):
windowProvider.igMainWindow();
void Tick()
Tick() calls DtTimedSection's stop() method to recalculate the time the application has run
myTimer->stop();
and then calls the Display Engine's tick method with the DtTimedSection's duration() as its argument:
myDe->tick(myTimer->duration());
Finally, an instance of the derived application class must be created with global scope:
ExampleMFCApp theApp;
VR-Vantage includes pre-built versions of the example application. To build it yourself, follow the instructions at Building VR-Vantage Examples, Applications, and Plug-ins.
This example is an application. You can run it by running ./bin/exampleMFCpage.exe (on Windows) or ./bin/exampleMFCpage (on Linux). For more information about running examples, please see Running Applications and Examples.
#include <afxwin.h> #include "MFCClasses.h" class ExampleMFCApp : public CWinApp { public: virtual BOOL InitInstance() { //Make the main Display Engine object. myDe = new makVrv::DtDe(); //Register the Mfc classes. initMfc(); //Register the osg module. makVrv::vrvOsg::init(*myDe); //Create the Main Window. createMainWindow(); //Initialize the De. myDe->setDeInitializer(makeDeInitializer()); myDe->initialize(); //Make time for getting system time. myTimer = new DtTimedSection; //Finish init. return CWinApp::InitInstance(); } virtual int Run() { _AFX_THREAD_STATE* pState = AfxGetThreadState(); for(;;) { if (PeekMessage(&(pState->m_msgCur) , NULL , 0, 0, PM_NOREMOVE)) { if (!PumpMessage()) { return ExitInstance(); } } else { Tick(); } } } virtual ~ExampleMFCApp() { delete myDe; delete myTimer; } protected: makVrv::DtDeInitializer makeDeInitializer() { // Configure an observer for channel control std::string observerName = "Observer 1"; makVrv::DtObserverConfiguration observerConfig(observerName); // Create a single channel for the observer makVrv::DtChannelConfiguration channel; channel.setObserverName(observerName); // Place the channel in a embedded window. makVrv::DtWindowConfiguration windowConfig; windowConfig.setWindowType(makVrv::DtWindowConfiguration::EmbeddedWindow); windowConfig.channelConfigurations().add(channel); // Add the window to the display config. std::string displayName = "Example VR-Vantage Embedded in MFC App"; makVrv::DtDisplayConfiguration displayConfig(displayName); displayConfig.windowConfigurations().add(windowConfig); // Create an input configuration. makVrv::DtInputDriverConfiguration inputConfig; inputConfig.setOptionalParameter( "windowDependent", "true" ); inputConfig.observerConfigurations().add(observerConfig); //Default initializer makVrv::DtDeInitializer init; init.deConfiguration().displayConfigurations().add(displayConfig); init.setDisplayEngineName(displayName); init.setInputDriverConfiguration( inputConfig ); return init; } void initMfc() { //Set the main window provider instance. makVrv::DtDeMainWindowProvider::registerInstance(*myDe, new DtMfcMainWindowProvider(*myDe)); //Set the embedded window creator. makVrv::DtWindowFactory::instance(*myDe).setCreator( makVrv::DtWindowConfiguration::EmbeddedWindow, new DtEmbeddedMfcOsgWindowCreator); } void createMainWindow() { // Get the DtDeMainWindowProvider, // and create the DtDeMainWindow makVrv::DtDeMainWindowProvider& windowProvider = makVrv::DtDeMainWindowProvider::instance(*myDe); // Causes creation of main window windowProvider.igMainWindow(); } void Tick() { //Stop to recalculate duration since start. myTimer->stop(); myDe->tick(myTimer->duration()); } protected: DtMfcMainWindow* myWindow; makVrv::DtDe* myDe; DtTimedSection* myTimer; }; ExampleMFCApp theApp;
#ifndef MFCClasses_H #define MFCClasses_H #include <afxwin.h> #include <GL/GL.h> #include <osg/GraphicsContext> #include <osgViewer/GraphicsWindow> #include <vlutil/vlPerformanceStats.h> #include <vrvCore/DtDe.h> #include <vrvCore/DtDeMainWindow.h> #include <vrvCore/DtWindow.h> #include <vrvCore/DtWindowFactory.h> #include <vrvOsg/DtOsgWindow.h> #include <vrvOsg/vrvOsg.h> class DtMfcMainWindow : public CFrameWnd, public makVrv::DtDeMainWindow { public: DtMfcMainWindow(makVrv::DtDe& de); //DtDeMainWindow Interface virtual void setApplicationTitle(const std::string& appName); virtual std::string DtMfcMainWindow::applicationTitle() const; virtual void setApplicationIcon(const std::string& iconName); virtual void setShowQuitDialogOnClose(bool value); virtual void destroyWindow(); virtual void quit(); protected: bool myShowQuitFlag; }; class DtMfcControlAsOsgContext; class DtEmbeddedMfcOsgWindow : public CWnd, public makVrv::DtOsgWindow { public: UINT_PTR m_unpTimer; DtEmbeddedMfcOsgWindow(makVrv::DtDe& de, makVrv::DtWindowConfiguration& wc); virtual ~DtEmbeddedMfcOsgWindow(); virtual bool isValid() const; virtual void setPosition(int x,int y); virtual void resize(int width,int height); virtual void sizeChanged(int width,int height); //Create the OpenGL Window void oglCreate(CRect rect, CWnd *parent); void oglInitialize(bool doubleBuffer, bool stereo, unsigned int colorBits, unsigned int depthBits, unsigned int stencilBits, bool vsync); bool isRealizedImplementation() const; void oglClose(); bool makeCurrent(); bool release(); void swapBuffers(); void setVSync(bool enabled); // Added message classes: afx_msg void OnPaint(); afx_msg void OnSize(UINT nType, int cx, int cy); afx_msg void OnDraw(CDC *pDC); afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg void OnMouseMove(UINT nFlags, CPoint point); afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnLButtonUp(UINT nFlags, CPoint point); afx_msg void OnRButtonDown(UINT nFlags, CPoint point); afx_msg void OnRButtonUp(UINT nFlags, CPoint point); afx_msg void OnMButtonDown(UINT nFlags, CPoint point); afx_msg void OnMButtonUp(UINT nFlags, CPoint point); DECLARE_MESSAGE_MAP() private: DtMfcControlAsOsgContext* myControl; CWnd* myHWnd; HDC myHDC; HGLRC myHGLRC; int myPixelFormat; }; class DtEmbeddedMfcOsgWindowCreator : public makVrv::DtWindowCreator { public: virtual makVrv::DtWindow* create(makVrv::DtDe& de, makVrv::DtWindowConfiguration& config); }; class DtMfcControlAsOsgContext : public osgViewer::GraphicsWindowEmbedded { public: DtMfcControlAsOsgContext( makVrv::DtDe& de, DtEmbeddedMfcOsgWindow* wnd, osg::GraphicsContext::Traits* traits); virtual bool valid() const; virtual bool realizeImplementation(); virtual bool isRealizedImplementation() const; virtual void closeImplementation(); virtual void grabFocus(); virtual void grabFocusIfPointerInWindow(); virtual bool makeCurrentImplementation(); virtual bool releaseContextImplementation(); virtual void swapBuffersImplementation(); virtual void requestWarpPointer( float x, float y ); virtual void useCursor( bool onOff ); protected: DtEmbeddedMfcOsgWindow* myControl; makVrv::DtDe& myDe; }; class DtMfcMainWindowProvider : public makVrv::DtDeMainWindowProvider { public: DtMfcMainWindowProvider(makVrv::DtDe& de); protected: virtual makVrv::DtDeMainWindow* createMainWindow(makVrv::DtDe& de); }; #endif
#include "MFCClasses.h" DtMfcMainWindow::DtMfcMainWindow(makVrv::DtDe& de) : DtDeMainWindow(de) { Create(NULL, "VR-Vantage MFC Example"); } //DtDeMainWindow Interface void DtMfcMainWindow::setApplicationTitle(const std::string& appName) { this->SetWindowText(appName.c_str()); } std::string DtMfcMainWindow::applicationTitle() const { CString cstr; this->GetWindowText(cstr); return std::string(cstr); } void DtMfcMainWindow::setApplicationIcon(const std::string& iconName) { HANDLE image = LoadImage(AfxGetInstanceHandle(),iconName.c_str(), IMAGE_ICON,16,16,LR_LOADFROMFILE | LR_DEFAULTSIZE); if(image != NULL) { this->SetIcon((HICON)image,FALSE); } } void DtMfcMainWindow::setShowQuitDialogOnClose(bool value) { myShowQuitFlag = value; } void DtMfcMainWindow::destroyWindow() { this->CloseWindow(); } void DtMfcMainWindow::quit() { this->SendMessage(WM_QUIT); } DtMfcControlAsOsgContext::DtMfcControlAsOsgContext( makVrv::DtDe& de, DtEmbeddedMfcOsgWindow* wnd, osg::GraphicsContext::Traits* traits) : osgViewer::GraphicsWindowEmbedded(traits) , myControl(wnd) , myDe( de ) { } bool DtMfcControlAsOsgContext::valid() const { return true; } bool DtMfcControlAsOsgContext::realizeImplementation() { myControl->oglInitialize(_traits->doubleBuffer, _traits->quadBufferStereo, _traits->red + _traits->green + _traits->blue + _traits->alpha, _traits->depth, _traits->stencil, _traits->vsync); return true; } bool DtMfcControlAsOsgContext::isRealizedImplementation() const { return myControl->isRealizedImplementation(); } void DtMfcControlAsOsgContext::closeImplementation() { myControl->oglClose(); } void DtMfcControlAsOsgContext::grabFocus() { myControl->GetFocus(); } void DtMfcControlAsOsgContext::grabFocusIfPointerInWindow() { } bool DtMfcControlAsOsgContext::makeCurrentImplementation() { if (!myControl->isRealizedImplementation()) { realizeImplementation(); } return myControl->makeCurrent(); } bool DtMfcControlAsOsgContext::releaseContextImplementation() { return myControl->release(); } void DtMfcControlAsOsgContext::swapBuffersImplementation() { return myControl->swapBuffers(); } void DtMfcControlAsOsgContext::requestWarpPointer( float x, float y ) { } void DtMfcControlAsOsgContext::useCursor( bool onOff ) { } DtEmbeddedMfcOsgWindow::DtEmbeddedMfcOsgWindow(makVrv::DtDe& de, makVrv::DtWindowConfiguration& wc) : DtOsgWindow(de,wc) , myControl(0) , myHWnd(0) , myHDC(0) , myHGLRC(0) , myPixelFormat(0) { osg::ref_ptr<osg::GraphicsContext::Traits> traits = DtOsgWindow::createDefaultTraits(); traits->x = 0; traits->y = 0; traits->doubleBuffer = myDe.deInitializer().doubleBuffer(); traits->vsync = myDe.deInitializer().vsync(); traits->width = 0; traits->height = 0; traits->windowName = myWindowConfiguration.name(); myControl = new DtMfcControlAsOsgContext(de,this,traits.get()); myContext = myControl; DtMfcMainWindow* mainWindow = dynamic_cast<DtMfcMainWindow*>(& makVrv::DtDeMainWindowProvider::instance(de).igMainWindow()); if(mainWindow) { //Create the window based on the size of the main Window. RECT bounds; mainWindow->GetClientRect(&bounds); oglCreate(bounds, mainWindow); } } DtEmbeddedMfcOsgWindow::~DtEmbeddedMfcOsgWindow() { myControl = 0; } BEGIN_MESSAGE_MAP(DtEmbeddedMfcOsgWindow, CWnd) ON_WM_PAINT() ON_WM_SIZE() ON_WM_CREATE() ON_WM_MOUSEMOVE() ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() ON_WM_RBUTTONDOWN() ON_WM_RBUTTONUP() ON_WM_MBUTTONDOWN() ON_WM_MBUTTONUP() END_MESSAGE_MAP() bool DtEmbeddedMfcOsgWindow::isValid() const { //Assume always valid return true; } void DtEmbeddedMfcOsgWindow::setPosition(int x,int y) { //Typically you can't set position of embedded window //Do Nothing } void DtEmbeddedMfcOsgWindow::resize(int width,int height) { //Typically you can't set position of embedded window //Do Nothing } void DtEmbeddedMfcOsgWindow::sizeChanged(int width,int height) { } bool DtEmbeddedMfcOsgWindow::isRealizedImplementation() const { return (myHDC != 0); } void DtEmbeddedMfcOsgWindow::oglCreate(CRect rect, CWnd *parent) { CString className = AfxRegisterWndClass( CS_HREDRAW | CS_VREDRAW | CS_OWNDC, NULL, (HBRUSH)GetStockObject(BLACK_BRUSH), NULL); CreateEx(0, className, "OpenGL", WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, rect, parent, 0); myHWnd = parent; } void DtEmbeddedMfcOsgWindow::OnPaint() { //CPaintDC dc(this); // device context for painting ValidateRect(NULL); } void DtEmbeddedMfcOsgWindow::OnMouseMove( UINT nFlags, CPoint point ) { myControl->getEventQueue()->mouseMotion(point.x,point.y); } void DtEmbeddedMfcOsgWindow::OnLButtonDown( UINT nFlags, CPoint point ) { myControl->getEventQueue()->mouseButtonPress(point.x,point.y,1); } void DtEmbeddedMfcOsgWindow::OnLButtonUp( UINT nFlags, CPoint point ) { myControl->getEventQueue()->mouseButtonRelease(point.x,point.y,1); } void DtEmbeddedMfcOsgWindow::OnRButtonDown( UINT nFlags, CPoint point ) { myControl->getEventQueue()->mouseButtonPress(point.x,point.y,3); } void DtEmbeddedMfcOsgWindow::OnRButtonUp( UINT nFlags, CPoint point ) { myControl->getEventQueue()->mouseButtonRelease(point.x,point.y,3); } void DtEmbeddedMfcOsgWindow::OnMButtonDown( UINT nFlags, CPoint point ) { myControl->getEventQueue()->mouseButtonPress(point.x,point.y,2); } void DtEmbeddedMfcOsgWindow::OnMButtonUp( UINT nFlags, CPoint point ) { myControl->getEventQueue()->mouseButtonRelease(point.x,point.y,2); } int DtEmbeddedMfcOsgWindow::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CWnd::OnCreate(lpCreateStruct) == -1) return -1; return 0; } void DtEmbeddedMfcOsgWindow::oglInitialize(bool doubleBuffer, bool stereo, unsigned int color, unsigned int depth, unsigned int stencil, bool vsync) { // Initial Setup: // PIXELFORMATDESCRIPTOR pfd; memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR)) ; pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); pfd.nVersion = 1 ; pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW ; pfd.iPixelType = PFD_TYPE_RGBA; pfd.cColorBits = color; pfd.cDepthBits = depth; pfd.cStencilBits = stencil; pfd.iLayerType = PFD_MAIN_PLANE ; // Get device context only once. myHDC = GetDC()->m_hDC; // Pixel format. myPixelFormat = ChoosePixelFormat(myHDC, &pfd); SetPixelFormat(myHDC, myPixelFormat, &pfd); // Create the OpenGL Rendering Context. myHGLRC = wglCreateContext(myHDC); wglMakeCurrent(myHDC, myHGLRC); setVSync(vsync); } void DtEmbeddedMfcOsgWindow::setVSync(bool enabled) { typedef BOOL (APIENTRY *PFNWGLSWAPINTERVALFARPROC)( int ); PFNWGLSWAPINTERVALFARPROC wglSwapIntervalEXT = 0; const char *extensions = (const char*)glGetString( GL_EXTENSIONS ); if( strstr( extensions, "WGL_EXT_swap_control" ) == 0 ) return; // Error: WGL_EXT_swap_control extension not supported on your computer.\n"); else { wglSwapIntervalEXT = (PFNWGLSWAPINTERVALFARPROC)wglGetProcAddress( "wglSwapIntervalEXT" ); if( wglSwapIntervalEXT ) { wglSwapIntervalEXT(enabled ? 1 : 0); } } } void DtEmbeddedMfcOsgWindow::oglClose() { wglDeleteContext(myHGLRC); myHGLRC = 0; myHDC = 0; } void DtEmbeddedMfcOsgWindow::OnSize(UINT nType, int cx, int cy) { CWnd::OnSize(nType, cx, cy); int width = cx; int height = cy; myControl->getEventQueue()->windowResize(0, 0, width, height); myControl->resized(0,0,width,height); myWindowConfiguration.setSize(cx,cy); } bool DtEmbeddedMfcOsgWindow::makeCurrent() { return wglMakeCurrent(myHDC,myHGLRC) == TRUE; } bool DtEmbeddedMfcOsgWindow::release() { return wglMakeCurrent(myHDC,0) == TRUE; } void DtEmbeddedMfcOsgWindow::swapBuffers() { SwapBuffers(myHDC); } DtMfcMainWindowProvider::DtMfcMainWindowProvider(makVrv::DtDe& de) : DtDeMainWindowProvider(de) { } makVrv::DtDeMainWindow* DtMfcMainWindowProvider::createMainWindow(makVrv::DtDe& de) { DtMfcMainWindow* window = new DtMfcMainWindow(de); window->ShowWindow(1); AfxGetApp()->m_pMainWnd = window; return window; } makVrv::DtWindow* DtEmbeddedMfcOsgWindowCreator::create(makVrv::DtDe& de, makVrv::DtWindowConfiguration& config) { return new DtEmbeddedMfcOsgWindow(de,config); }