Hello,
I have an extensive MFC (commercial) application and we need to replace the 3D graph. We were hoping to incorporate the LinePlot3D application, but, after many hours of trying to get a mini-application to work, I am hoping someone can assist me here. I have tried both a small MFC application and a code project example. In the MFC app, I used m_pvtkWnd = new MyVTKWindow(IDD_DIALOG_BLANK, GetDlgItem(IDD_VTKCHART)) to create the window, but that fails at CWnd::Create() within the vtkWindow constructor. We are using VTK 9.4 in MSVS 2022.
I have also attempted to use this example:
and that example works, but I cannot get the LinePlot3D application to display in that one either.
Can anyone guide me towards a solution or tell me where I might be making a mistake?
Sure, below is an excerpt from my custom dialog class. I attempted more than just this small section of code as well, but this is the minimum to reproduce an error. The if statement was used as a sanity check and it loads either the vtkMFCWindow or a CDialog that uses Direct2D to draw the window. The CDialog loads and draws just fine.
Please let me know if you need to see more of the code so you can reproduce and troubleshoot the error.
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != nullptr)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
if (true)
{ // Create the vtkMFCWindow and associate it with an MFC control
pvtkMFCWindow = new vtkMFCWindow(GetDlgItem(IDC_VTKAREA));
}
else
{
CRect rc;
CWnd* pWnd = GetDlgItem(IDC_VTKAREA);
if (pWnd) pWnd->GetWindowRect(rc);
ScreenToClient(rc);
m_d2dChart.Create(rc, this, IDC_VTKAREA);
if (m_d2dChart.GetSafeHwnd() == NULL) {
AfxMessageBox(_T("Graph: Failed to create dialog."));
return FALSE;
}
m_d2dChart.ShowWindow(SW_SHOW);
}
return TRUE; // return TRUE unless you set the focus to a control
The code project example uses a CView to draw the bitmap. From my screenshot above, my test app used the IPictEditor. To me, these are different ways to draw a scene in an MFC window. Which is preferred?
I will add that when I use CView from the Code Project example the line
m_pvtkMFCWindow = new vtkMFCWindow(this);
does not result in an exception, but this line has an exception:
this->Context->GetDevice()->SetViewportSize(vtkVector2i(size));
vtkContext2D::GetDevicevirtual returned nullptr.
it is in the function vtkContextActor::RenderOverlay(vtkViewport* viewport).
Do I need to set the device or initialize other members in CTestBMPView::OnInitialUpdate()?
The example from code project just does the following:
m_pvtkMFCWindow = new vtkMFCWindow(this);
m_pvtkMFCWindow->GetRenderWindow()->AddRenderer(m_pvtkRenderer);
m_pvtkRenderer->SetBackground(0.0, 0.0, 0.0);
if(NULL != GetDocument()->m_pvtkBMPReader)
{
//setup renderer
m_pvtkImageActor->GetMapper()->SetInputConnection(GetDocument()->m_pvtkBMPReader->GetOutputPort());
m_pvtkRenderer->AddActor(m_pvtkImageActor);
m_pvtkRenderer->ResetCamera();
}
I haven’t actually used vtkMFCWindow but I have done something similar with an OpenCascade rendering window, so I supposed that vtkMFCWindow requires a CView host.