1. 實例的編譯運行
新建工程時,可以直接通過cmake生成,但如果工程沒有編譯完全或者安裝成功的話,在安裝目錄沒法找到GUISupport/MFC/VTKMFCSettings.cmake,從而無法正常新建工程。這裏主要講解手動新建工程的過程,以方便大家的學習
和進一步理解。
a.新建工程,然後將vtkSDI文件夾直接覆蓋工程裏面的文件,res文件可以不復制。
b.設置頭文件
b.添加lib路徑和文件
c.修改property裏面的general選項裏的character set的設置。
d.編譯運行
e.選擇vtkdata中的vtk文件,然後進行查看處理
值得注意的是,要運用vtk和MFC聯合編程,編譯VTK源代碼的時候一定要選擇vtk gui support裏的MFC.
2.實例源碼詳解
學過MFC的基本都知道,MFC中view類主要處理顯示視圖,doc類處理文檔,mainframe主要爲整個窗口的和工程的設置管理。由此,VTK與MFC聯合編程時,需要主要的是數據操作,以及顯示要很好的與MFC中的結構結合,做到MVC分離的要求和規範,視圖-模型和控制一定要處理開來,尤其是大工程的處理時,才能不混亂。
a.view類設置
頭文件
// vtkSDIView.h : interface of the CvtkSDIView class
//
#pragma once
//添加MFC顯示窗口的頭文件
#include "vtkMFCWindow.h"
class CvtkSDIView : public CView
{
public:
virtual ~CvtkSDIView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
CvtkSDIDoc* GetDocument() const;
//獲得vtkRender的指針
vtkRenderer* GetRenderer() { ASSERT(pvtkRenderer); return pvtkRenderer; }
virtual void OnDraw(CDC* pDC); // overridden to draw this view
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnDestroy();
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnSize(UINT nType, int cx, int cy);
private:
//顯示的變量,vtkrender和vtkMFCWindow
vtkRenderer *pvtkRenderer;
vtkMFCWindow *pvtkMFCWindow;
protected:
DECLARE_DYNCREATE(CvtkSDIView)
CvtkSDIView();
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
DECLARE_MESSAGE_MAP()
public:
virtual void OnInitialUpdate();
};
#ifndef _DEBUG // debug version in vtkSDIView.cpp
inline CvtkSDIDoc* CvtkSDIView::GetDocument() const
{ return reinterpret_cast<CvtkSDIDoc*>(m_pDocument); }
#endif
// vtkSDIView.cpp : implementation of the CvtkSDIView class
//
#include "stdafx.h"
#include "vtkSDI.h"
#include "vtkSDIDoc.h"
#include "vtkSDIView.h"
#include "vtkCallbackCommand.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CvtkSDIView
IMPLEMENT_DYNCREATE(CvtkSDIView, CView)
BEGIN_MESSAGE_MAP(CvtkSDIView, CView)
// 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)
ON_WM_CREATE()
ON_WM_DESTROY()
ON_WM_ERASEBKGND()
ON_WM_SIZE()
END_MESSAGE_MAP()
// CvtkSDIView construction/destruction
CvtkSDIView::CvtkSDIView()
{
this->pvtkMFCWindow = NULL;
//新建視圖類對象
this->pvtkRenderer = vtkRenderer::New();
}
CvtkSDIView::~CvtkSDIView()
{
// delete generic vtk window
if (this->pvtkMFCWindow) delete this->pvtkMFCWindow;
}
void CvtkSDIView::OnDraw(CDC* pDC)
{
CvtkSDIDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (this->pvtkMFCWindow)
{
if (pDC->IsPrinting())
this->pvtkMFCWindow->DrawDC(pDC);
}
}
// CvtkSDIView printing
BOOL CvtkSDIView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CvtkSDIView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CvtkSDIView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
// CvtkSDIView diagnostics
#ifdef _DEBUG
void CvtkSDIView::AssertValid() const
{
CView::AssertValid();
}
void CvtkSDIView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CvtkSDIDoc* CvtkSDIView::GetDocument() const // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CvtkSDIDoc)));
return (CvtkSDIDoc*)m_pDocument;
}
#endif //_DEBUG
// CvtkSDIView message handlers
int CvtkSDIView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
return 0;
}
void CvtkSDIView::OnDestroy()
{
// Delete the the renderer, window and interactor objects.
if (this->pvtkRenderer) this->pvtkRenderer->Delete();
// destroy base
CView::OnDestroy();
}
BOOL CvtkSDIView::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}
void CvtkSDIView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
if (this->pvtkMFCWindow)
this->pvtkMFCWindow->MoveWindow(0, 0, cx, cy);
}
static void handle_double_click(vtkObject* obj, unsigned long,
void*, void*)
{
//交互響應回調函數,輸出提示信息
vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::SafeDownCast(obj);
if(iren && iren->GetRepeatCount())
{
AfxMessageBox("Double Click");
}
}
void CvtkSDIView::OnInitialUpdate()
{
CView::OnInitialUpdate();
//初始化的時候創建vtkMFCwindow對象
if (this->pvtkMFCWindow) delete this->pvtkMFCWindow;
this->pvtkMFCWindow = new vtkMFCWindow(this);
//將render對象添加到實現窗口vtkMFCwindow中
this->pvtkMFCWindow->GetRenderWindow()->AddRenderer(this->pvtkRenderer);
//添加交互中鼠標左鍵響應回調函數
vtkCallbackCommand* callback = vtkCallbackCommand::New();
callback->SetCallback(handle_double_click);
this->pvtkMFCWindow->GetInteractor()->AddObserver(vtkCommand::LeftButtonPressEvent, callback, 1.0);
callback->Delete();
}
頭文件
// vtkSDIDoc.h : interface of the CvtkSDIDoc class
//
#pragma once
class CvtkSDIDoc : public CDocument
{
protected: // create from serialization only
CvtkSDIDoc();
DECLARE_DYNCREATE(CvtkSDIDoc)
// Attributes
private:
vtkDataSetReader *pvtkDataSetReader;
// Operations
public:
// Overrides
public:
virtual BOOL OnNewDocument();
virtual void Serialize(CArchive& ar);
// Implementation
public:
virtual ~CvtkSDIDoc();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
private:
void ExecutePipeline();
void RemoveActors();
//數據處理和顯示的mapper和actor對象
vtkDataSetMapper *pvtkDataSetMapper;
vtkActor *pvtkActor;
vtkActor2D *pvtkActor2D;
vtkTextMapper *pvtkTextMapper;
// Generated message map functions
protected:
DECLARE_MESSAGE_MAP()
public:
virtual void OnCloseDocument();
virtual BOOL OnOpenDocument(LPCTSTR lpszPathName);
};
// vtkSDIDoc.cpp : implementation of the CvtkSDIDoc class
//
#include "stdafx.h"
#include "vtkSDI.h"
#include "vtkSDIDoc.h"
#include "vtkSDIView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CvtkSDIDoc
IMPLEMENT_DYNCREATE(CvtkSDIDoc, CDocument)
BEGIN_MESSAGE_MAP(CvtkSDIDoc, CDocument)
END_MESSAGE_MAP()
// CvtkSDIDoc construction/destruction
CvtkSDIDoc::CvtkSDIDoc()
{
this->pvtkDataSetReader = NULL;
// 創建對象,從而可以顯示
this->pvtkDataSetMapper = vtkDataSetMapper::New();
this->pvtkActor = vtkActor::New();
this->pvtkActor2D = vtkActor2D::New();
this->pvtkTextMapper = vtkTextMapper::New();
}
CvtkSDIDoc::~CvtkSDIDoc()
{
}
BOOL CvtkSDIDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
//移除原有actor對象
RemoveActors();
//執行數據處理流程
ExecutePipeline();
return TRUE;
}
// CvtkSDIDoc serialization
void CvtkSDIDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
}
// CvtkSDIDoc diagnostics
#ifdef _DEBUG
void CvtkSDIDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CvtkSDIDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
// CvtkSDIDoc commands
void CvtkSDIDoc::RemoveActors()
{
//活的view類對象
POSITION pos = this->GetFirstViewPosition();
CvtkSDIView *pcvtkSDIView = NULL;
if (pos)
{
pcvtkSDIView = (CvtkSDIView *)GetNextView(pos);
}
else // return
{
ASSERT(FALSE);
return;
}
//移除actor對象
pcvtkSDIView->GetRenderer()->RemoveActor(this->pvtkActor);
pcvtkSDIView->GetRenderer()->RemoveActor(this->pvtkActor2D);
}
//openfile 打開數據文件,將數據導入
BOOL CvtkSDIDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
if (!CDocument::OnOpenDocument(lpszPathName))
return FALSE;
//移除對象
RemoveActors();
//讀入數據
this->pvtkDataSetReader = vtkDataSetReader::New();
this->pvtkDataSetReader->SetFileName(lpszPathName);
//運行數據導入流程,導入數據
ExecutePipeline();
return TRUE;
}
//釋放創建的內存
void CvtkSDIDoc::OnCloseDocument()
{
// delete data
if (this->pvtkDataSetReader) this->pvtkDataSetReader->Delete();
// Delete the the objects used to form the visualisation.
if (this->pvtkDataSetMapper) this->pvtkDataSetMapper->Delete();
if (this->pvtkActor) this->pvtkActor->Delete();
if (this->pvtkActor2D) this->pvtkActor2D->Delete();
if (this->pvtkTextMapper) this->pvtkTextMapper->Delete();
CDocument::OnCloseDocument();
}
//數據處理流程
void CvtkSDIDoc::ExecutePipeline()
{
// 獲得視圖類對象
POSITION pos = this->GetFirstViewPosition();
CvtkSDIView *pcvtkSDIView = NULL;
if (pos)
{
pcvtkSDIView = (CvtkSDIView *)GetNextView(pos);
}
else // return
{
ASSERT(FALSE);
return;
}
if (pvtkDataSetReader) // 有數據,將數據添加到render中顯示
{
this->pvtkDataSetMapper->SetInput(this->pvtkDataSetReader->GetOutput());
this->pvtkActor->SetMapper(this->pvtkDataSetMapper);
this->pvtkTextMapper->SetInput(this->pvtkDataSetReader->GetFileName());
this->pvtkTextMapper->GetTextProperty()->SetFontSize(12);
this->pvtkActor2D->SetMapper(this->pvtkTextMapper);
pcvtkSDIView->GetRenderer()->SetBackground(0.0,0.0,0.4);
pcvtkSDIView->GetRenderer()->AddActor(this->pvtkActor);
pcvtkSDIView->GetRenderer()->AddActor(this->pvtkActor2D);
pcvtkSDIView->GetRenderer()->ResetCamera();
pvtkDataSetReader->Delete();
pvtkDataSetReader = NULL;
}
else //無導入數據,顯示textmapper, hello world
{
this->pvtkTextMapper->SetInput("Hello World");
this->pvtkTextMapper->GetTextProperty()->SetFontSize(24);
this->pvtkActor2D->SetMapper(this->pvtkTextMapper);
pcvtkSDIView->GetRenderer()->SetBackground(0.0,0.0,0.4);
pcvtkSDIView->GetRenderer()->AddActor(this->pvtkActor2D);
pcvtkSDIView->GetRenderer()->ResetCamera();
}
}
好了,到這裏,基本對MFC和vtk聯合編程就有了個詳細的瞭解了,這樣也就可以自己用VTK結合MFC構建自己的工程了。