[vtkusers] Problem with Interactor with MFC.

BURRELL Benjamin Benjamin.Burrell at Tenix.com
Thu Mar 11 02:38:26 EST 2004


Hi,

I have created a program using Visual C++ and MFC. I have used the App wizard to give me a simple multi-document GUI. With this I am trying to embedd VTK inside a child frame (eg. when you go to File menu and select New a frame will appear containing the VTK object, all within the main window).
There is no problems when I close the frame containing the VTK object, but when I close the whole application I get a message showing the tells me an ASSERT has failed in the MFC code, in the file "C:\..\VC98\MFC\SRC\WINGDI.cpp".
Where I have an arrow is where the ASSERT has failed.

CPaintDC::~CPaintDC()
{
	ASSERT(m_hDC != NULL);
->	ASSERT(::IsWindow(m_hWnd));

	::EndPaint(m_hWnd, &m_ps);
	Detach();
}


In my code, in the 'void CVCVTKView::OnDraw(CDC* pDC)' routine, if I leave out the line
this->iren->SetRenderWindow(this->renWin);
I don't have the problem, instead VTK complains that the interactor (iren) cannot find a render window to get the mouse interactions from.
>From this I think the problem has something to do with the Interactor object having a window handle to the child frame and perhaps the Interactor takes control of deleting this window and later on the MFC code is looking for a valid window handle but the VTK code deletes it???????

Any one got ideas on how to fix this problem?

The code I have written/modified and refer to is below:


// VCVTKView.cpp : implementation of the CVCVTKView class
//

#include "stdafx.h"
#include "VCVTK.h"

#include "VCVTKDoc.h"
#include "VCVTKView.h"

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

/////////////////////////////////////////////////////////////////////////////
// CVCVTKView

IMPLEMENT_DYNCREATE(CVCVTKView, CView)

BEGIN_MESSAGE_MAP(CVCVTKView, CView)
	//{{AFX_MSG_MAP(CVCVTKView)
		// NOTE - the ClassWizard will add and remove mapping macros here.
		//    DO NOT EDIT what you see in these blocks of generated code!
	//}}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()

/////////////////////////////////////////////////////////////////////////////
// CVCVTKView construction/destruction

CVCVTKView::CVCVTKView()
{
	// TODO: add construction code here

  this->ren1 = vtkRenderer::New();
  this->renWin = vtkWin32OpenGLRenderWindow::New();
  this->renWin->AddRenderer(this->ren1);
  this->iren = vtkWin32RenderWindowInteractor::New();


}

CVCVTKView::~CVCVTKView()
{

  if (this->iren) 
    {
    this->iren->Delete();
    }
  if (this->ren1) 
    {
    this->ren1->SetRenderWindow(NULL);
    }
  if (this->renWin) 
    {
    this->renWin->Delete();
    }
  if (this->ren1) 
    {
    this->ren1->Delete();
    }

}

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

	return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CVCVTKView drawing

void CVCVTKView::OnDraw(CDC* pDC)
{
	CVCVTKDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here




	// TODO: Add your command handler code here


  // This creates a polygonal cylinder model with eight circumferential facets.
  //



  vtkCylinderSource *cylinder = vtkCylinderSource::New();
  cylinder->SetResolution(8);

  // The mapper is responsible for pushing the geometry into the graphics
  // library. It may also do color mapping, if scalars or other attributes
  // are defined.
  //
  vtkPolyDataMapper *cylinderMapper = vtkPolyDataMapper::New();
  cylinderMapper->SetInput(cylinder->GetOutput());

  // The actor is a grouping mechanism: besides the geometry (mapper), it
  // also has a property, transformation matrix, and/or texture map.
  // Here we set its color and rotate it -22.5 degrees.
  vtkActor *cylinderActor = vtkActor::New();
  cylinderActor->SetMapper(cylinderMapper);
  cylinderActor->GetProperty()->SetColor(1.0000, 0.3882, 0.2784);
  cylinderActor->RotateX(30.0);
  cylinderActor->RotateY(-45.0);

  // Create the graphics structure. The renderer renders into the 
  // render window. The render window interactor captures mouse events
  // and will perform appropriate camera or actor manipulation
  // depending on the nature of the events.
  //

  if (!this->iren->GetInitialized())
  {
    this->iren->SetRenderWindow(this->renWin);
    WNDPROC OldProc = (WNDPROC)GetWindowLong(this->m_hWnd,GWL_WNDPROC);
    this->iren->Initialize();
    SetWindowLong(this->m_hWnd,GWL_WNDPROC,(LONG)OldProc);
  }

  // Add the actors to the renderer, set the background and size
  //
  ren1->AddActor(cylinderActor);
  ren1->SetBackground(0.1, 0.2, 0.4);
  renWin->SetSize(200, 200);

  // We'll zoom in a little by accessing the camera and invoking a "Zoom"
  // method on it.
  ren1->GetActiveCamera()->Zoom(1.5);
  renWin->Render();
  
  iren->Initialize();
  // This starts the event loop and as a side effect causes an initial render.
  iren->Start();

}


LRESULT CVCVTKView::WindowProc(UINT message, WPARAM wParam, LPARAM
lParam)

        {
        int status;
        double camera_x, camera_y, camera_z;

        status = CWnd::WindowProc(message, wParam, lParam);

        switch (message)
                {
                case WM_RBUTTONDOWN:
                case WM_LBUTTONDOWN:
                case WM_LBUTTONUP:
                case WM_MBUTTONDOWN:
                case WM_MBUTTONUP:
                case WM_RBUTTONUP:
                case WM_MOUSEMOVE:
                case WM_CHAR:
                case WM_TIMER:
                        if (iren != NULL)
                                {
                                if (iren->GetInitialized())
                                        {
                                        return
vtkHandleMessage2(this->m_hWnd, message, wParam, lParam,
this->iren);
                                        }
                                }
                break;

                default:
// status = 1;
                break;
                }
        return (status);
        } 

/////////////////////////////////////////////////////////////////////////////
// CVCVTKView printing

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

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

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

/////////////////////////////////////////////////////////////////////////////
// CVCVTKView diagnostics

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

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

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

/////////////////////////////////////////////////////////////////////////////
// CVCVTKView message handlers



int CVCVTKView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
  if (CVCVTKView::OnCreate(lpCreateStruct) == -1)
    return -1;
  
  // TODO: Add your specialized creation code here
  this->renWin->SetParentId(lpCreateStruct->hwndParent);

  return 0;
}


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

  // TODO: Add your specialized creation code here
  
  this->renWin->SetWindowId(this->m_hWnd);
  this->renWin->WindowInitialize();
}


void CVCVTKView::OnSize(UINT nType, int cx, int cy) 
{
  CVCVTKView::OnSize(nType, cx, cy);
  
  // TODO: Add your message handler code here
  if (this->iren->GetInitialized())
    {
    this->iren->SetSize(cx,cy);		
    }
}



Regards,
Benjamin Burrell




More information about the vtkusers mailing list