VTK與MFC聯合程式設計實現的單文件例項vtkSDI詳解
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();
-
}
a.Doc類設定
標頭檔案
-
// 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();
-
}
-
}