1. 程式人生 > >VTK與MFC聯合程式設計實現的單文件例項vtkSDI詳解

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類設定

標頭檔案

  1. // vtkSDIView.h : interface of the CvtkSDIView class

  2. //

  3. #pragma once

  1. //新增MFC顯示視窗的標頭檔案

  2. #include "vtkMFCWindow.h"

  3. class CvtkSDIView : public CView

  4. {

  5. public:

  6. virtual ~CvtkSDIView();

  7. #ifdef _DEBUG

  8. virtual void AssertValid() const;

  9. virtual void Dump(CDumpContext& dc) const;

  10. #endif

  11. CvtkSDIDoc* GetDocument() const;

  1. //獲得vtkRender的指標

  2. vtkRenderer* GetRenderer() { ASSERT(pvtkRenderer); return pvtkRenderer; }

  3. virtual void OnDraw(CDC* pDC); // overridden to draw this view

  4. afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

  5. afx_msg void OnDestroy();

  6. afx_msg BOOL OnEraseBkgnd(CDC* pDC);

  7. afx_msg void OnSize(UINT nType, int cx, int cy);

  8. private:

  1. //顯示的變數,vtkrender和vtkMFCWindow

  2. vtkRenderer *pvtkRenderer;

  3. vtkMFCWindow *pvtkMFCWindow;

  4. protected:

  5. DECLARE_DYNCREATE(CvtkSDIView)

  6. CvtkSDIView();

  7. virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);

  8. virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);

  9. virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);

  10. DECLARE_MESSAGE_MAP()

  11. public:

  12. virtual void OnInitialUpdate();

  13. };

  14. #ifndef _DEBUG // debug version in vtkSDIView.cpp

  15. inline CvtkSDIDoc* CvtkSDIView::GetDocument() const

  16. { return reinterpret_cast<CvtkSDIDoc*>(m_pDocument); }

  17. #endif

實現檔案

  1. // vtkSDIView.cpp : implementation of the CvtkSDIView class

  2. //

  3. #include "stdafx.h"

  4. #include "vtkSDI.h"

  5. #include "vtkSDIDoc.h"

  6. #include "vtkSDIView.h"

  7. #include "vtkCallbackCommand.h"

  8. #ifdef _DEBUG

  9. #define new DEBUG_NEW

  10. #endif

  11. // CvtkSDIView

  12. IMPLEMENT_DYNCREATE(CvtkSDIView, CView)

  13. BEGIN_MESSAGE_MAP(CvtkSDIView, CView)

  14. // Standard printing commands

  15. ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)

  16. ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)

  17. ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)

  18. ON_WM_CREATE()

  19. ON_WM_DESTROY()

  20. ON_WM_ERASEBKGND()

  21. ON_WM_SIZE()

  22. END_MESSAGE_MAP()

  23. // CvtkSDIView construction/destruction

  24. CvtkSDIView::CvtkSDIView()

  25. {

  26. this->pvtkMFCWindow = NULL;

  27. //新建檢視類物件

  28. this->pvtkRenderer = vtkRenderer::New();

  29. }

  30. CvtkSDIView::~CvtkSDIView()

  31. {

  32. // delete generic vtk window

  33. if (this->pvtkMFCWindow) delete this->pvtkMFCWindow;

  34. }

  35. void CvtkSDIView::OnDraw(CDC* pDC)

  36. {

  37. CvtkSDIDoc* pDoc = GetDocument();

  38. ASSERT_VALID(pDoc);

  39. if (this->pvtkMFCWindow)

  40. {

  41. if (pDC->IsPrinting())

  42. this->pvtkMFCWindow->DrawDC(pDC);

  43. }

  44. }

  45. // CvtkSDIView printing

  46. BOOL CvtkSDIView::OnPreparePrinting(CPrintInfo* pInfo)

  47. {

  48. // default preparation

  49. return DoPreparePrinting(pInfo);

  50. }

  51. void CvtkSDIView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)

  52. {

  53. // TODO: add extra initialization before printing

  54. }

  55. void CvtkSDIView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)

  56. {

  57. // TODO: add cleanup after printing

  58. }

  59. // CvtkSDIView diagnostics

  60. #ifdef _DEBUG

  61. void CvtkSDIView::AssertValid() const

  62. {

  63. CView::AssertValid();

  64. }

  65. void CvtkSDIView::Dump(CDumpContext& dc) const

  66. {

  67. CView::Dump(dc);

  68. }

  69. CvtkSDIDoc* CvtkSDIView::GetDocument() const // non-debug version is inline

  70. {

  71. ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CvtkSDIDoc)));

  72. return (CvtkSDIDoc*)m_pDocument;

  73. }

  74. #endif //_DEBUG

  75. // CvtkSDIView message handlers

  76. int CvtkSDIView::OnCreate(LPCREATESTRUCT lpCreateStruct)

  77. {

  78. if (CView::OnCreate(lpCreateStruct) == -1)

  79. return -1;

  80. return 0;

  81. }

  82. void CvtkSDIView::OnDestroy()

  83. {

  84. // Delete the the renderer, window and interactor objects.

  85. if (this->pvtkRenderer) this->pvtkRenderer->Delete();

  86. // destroy base

  87. CView::OnDestroy();

  88. }

  89. BOOL CvtkSDIView::OnEraseBkgnd(CDC* pDC)

  90. {

  91. return TRUE;

  92. }

  93. void CvtkSDIView::OnSize(UINT nType, int cx, int cy)

  94. {

  95. CView::OnSize(nType, cx, cy);

  96. if (this->pvtkMFCWindow)

  97. this->pvtkMFCWindow->MoveWindow(0, 0, cx, cy);

  98. }

  99. static void handle_double_click(vtkObject* obj, unsigned long,

  100. void*, void*)

  101. {

  1. //互動響應回撥函式,輸出提示資訊

  2. vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::SafeDownCast(obj);

  3. if(iren && iren->GetRepeatCount())

  4. {

  5. AfxMessageBox("Double Click");

  6. }

  7. }

  8. void CvtkSDIView::OnInitialUpdate()

  9. {

  10. CView::OnInitialUpdate();

  1. //初始化的時候建立vtkMFCwindow物件

  2. if (this->pvtkMFCWindow) delete this->pvtkMFCWindow;

  3. this->pvtkMFCWindow = new vtkMFCWindow(this);

  1. //將render物件新增到實現視窗vtkMFCwindow中

  2. this->pvtkMFCWindow->GetRenderWindow()->AddRenderer(this->pvtkRenderer);

  3. //新增互動中滑鼠左鍵響應回撥函式

  4. vtkCallbackCommand* callback = vtkCallbackCommand::New();

  5. callback->SetCallback(handle_double_click);

  6. this->pvtkMFCWindow->GetInteractor()->AddObserver(vtkCommand::LeftButtonPressEvent, callback, 1.0);

  7. callback->Delete();

  8. }

a.Doc類設定  

標頭檔案

  1. // vtkSDIDoc.h : interface of the CvtkSDIDoc class

  2. //

  3. #pragma once

  4. class CvtkSDIDoc : public CDocument

  5. {

  6. protected: // create from serialization only

  7. CvtkSDIDoc();

  8. DECLARE_DYNCREATE(CvtkSDIDoc)

  9. // Attributes

  10. private:

  11. vtkDataSetReader *pvtkDataSetReader;

  12. // Operations

  13. public:

  14. // Overrides

  15. public:

  16. virtual BOOL OnNewDocument();

  17. virtual void Serialize(CArchive& ar);

  18. // Implementation

  19. public:

  20. virtual ~CvtkSDIDoc();

  21. #ifdef _DEBUG

  22. virtual void AssertValid() const;

  23. virtual void Dump(CDumpContext& dc) const;

  24. #endif

  25. private:

  26. void ExecutePipeline();

  27. void RemoveActors();

  1. //資料處理和顯示的mapper和actor物件

  2. vtkDataSetMapper *pvtkDataSetMapper;

  3. vtkActor *pvtkActor;

  4. vtkActor2D *pvtkActor2D;

  5. vtkTextMapper *pvtkTextMapper;

  6. // Generated message map functions

  7. protected:

  8. DECLARE_MESSAGE_MAP()

  9. public:

  10. virtual void OnCloseDocument();

  11. virtual BOOL OnOpenDocument(LPCTSTR lpszPathName);

  12. };

實現檔案

  1. // vtkSDIDoc.cpp : implementation of the CvtkSDIDoc class

  2. //

  3. #include "stdafx.h"

  4. #include "vtkSDI.h"

  5. #include "vtkSDIDoc.h"

  6. #include "vtkSDIView.h"

  7. #ifdef _DEBUG

  8. #define new DEBUG_NEW

  9. #endif

  10. // CvtkSDIDoc

  11. IMPLEMENT_DYNCREATE(CvtkSDIDoc, CDocument)

  12. BEGIN_MESSAGE_MAP(CvtkSDIDoc, CDocument)

  13. END_MESSAGE_MAP()

  14. // CvtkSDIDoc construction/destruction

  15. CvtkSDIDoc::CvtkSDIDoc()

  16. {

  17. this->pvtkDataSetReader = NULL;

  18. // 建立物件,從而可以顯示

  19. this->pvtkDataSetMapper = vtkDataSetMapper::New();

  20. this->pvtkActor = vtkActor::New();

  21. this->pvtkActor2D = vtkActor2D::New();

  22. this->pvtkTextMapper = vtkTextMapper::New();

  23. }

  24. CvtkSDIDoc::~CvtkSDIDoc()

  25. {

  26. }

  27. BOOL CvtkSDIDoc::OnNewDocument()

  28. {

  29. if (!CDocument::OnNewDocument())

  30. return FALSE;

  31. //移除原有actor物件

  32. RemoveActors();

  33. //執行資料處理流程

  34. ExecutePipeline();

  35. return TRUE;

  36. }

  37. // CvtkSDIDoc serialization

  38. void CvtkSDIDoc::Serialize(CArchive& ar)

  39. {

  40. if (ar.IsStoring())

  41. {

  42. // TODO: add storing code here

  43. }

  44. else

  45. {

  46. // TODO: add loading code here

  47. }

  48. }

  49. // CvtkSDIDoc diagnostics

  50. #ifdef _DEBUG

  51. void CvtkSDIDoc::AssertValid() const

  52. {

  53. CDocument::AssertValid();

  54. }

  55. void CvtkSDIDoc::Dump(CDumpContext& dc) const

  56. {

  57. CDocument::Dump(dc);

  58. }

  59. #endif //_DEBUG

  60. // CvtkSDIDoc commands

  61. void CvtkSDIDoc::RemoveActors()

  62. {

  63. //活的view類物件

  64. POSITION pos = this->GetFirstViewPosition();

  65. CvtkSDIView *pcvtkSDIView = NULL;

  66. if (pos)

  67. {

  68. pcvtkSDIView = (CvtkSDIView *)GetNextView(pos);

  69. }

  70. else // return

  71. {

  72. ASSERT(FALSE);

  73. return;

  74. }

  75. //移除actor物件

  76. pcvtkSDIView->GetRenderer()->RemoveActor(this->pvtkActor);

  77. pcvtkSDIView->GetRenderer()->RemoveActor(this->pvtkActor2D);

  78. }

  1. //openfile 開啟資料檔案,將資料匯入

  2. BOOL CvtkSDIDoc::OnOpenDocument(LPCTSTR lpszPathName)

  3. {

  4. if (!CDocument::OnOpenDocument(lpszPathName))

  5. return FALSE;

  6. //移除物件

  7. RemoveActors();

  8. //讀入資料

  9. this->pvtkDataSetReader = vtkDataSetReader::New();

  10. this->pvtkDataSetReader->SetFileName(lpszPathName);

  11. //執行資料匯入流程,匯入資料

  12. ExecutePipeline();

  13. return TRUE;

  14. }

//釋放建立的記憶體
  1. void CvtkSDIDoc::OnCloseDocument()

  2. {

  3. // delete data

  4. if (this->pvtkDataSetReader) this->pvtkDataSetReader->Delete();

  5. // Delete the the objects used to form the visualisation.

  6. if (this->pvtkDataSetMapper) this->pvtkDataSetMapper->Delete();

  7. if (this->pvtkActor) this->pvtkActor->Delete();

  8. if (this->pvtkActor2D) this->pvtkActor2D->Delete();

  9. if (this->pvtkTextMapper) this->pvtkTextMapper->Delete();

  10. CDocument::OnCloseDocument();

  11. }

  1. //資料處理流程

  2. void CvtkSDIDoc::ExecutePipeline()

  3. {

  4. // 獲得檢視類物件

  5. POSITION pos = this->GetFirstViewPosition();

  6. CvtkSDIView *pcvtkSDIView = NULL;

  7. if (pos)

  8. {

  9. pcvtkSDIView = (CvtkSDIView *)GetNextView(pos);

  10. }

  11. else // return

  12. {

  13. ASSERT(FALSE);

  14. return;

  15. }

  16. if (pvtkDataSetReader) // 有資料,將資料新增到render中顯示

  17. {

  18. this->pvtkDataSetMapper->SetInput(this->pvtkDataSetReader->GetOutput());

  19. this->pvtkActor->SetMapper(this->pvtkDataSetMapper);

  20. this->pvtkTextMapper->SetInput(this->pvtkDataSetReader->GetFileName());

  21. this->pvtkTextMapper->GetTextProperty()->SetFontSize(12);

  22. this->pvtkActor2D->SetMapper(this->pvtkTextMapper);

  23. pcvtkSDIView->GetRenderer()->SetBackground(0.0,0.0,0.4);

  24. pcvtkSDIView->GetRenderer()->AddActor(this->pvtkActor);

  25. pcvtkSDIView->GetRenderer()->AddActor(this->pvtkActor2D);

  26. pcvtkSDIView->GetRenderer()->ResetCamera();

  27. pvtkDataSetReader->Delete();

  28. pvtkDataSetReader = NULL;

  29. }

  30. else //無匯入資料,顯示textmapper, hello world

  31. {

  32. this->pvtkTextMapper->SetInput("Hello World");

  33. this->pvtkTextMapper->GetTextProperty()->SetFontSize(24);

  34. this->pvtkActor2D->SetMapper(this->pvtkTextMapper);

  35. pcvtkSDIView->GetRenderer()->SetBackground(0.0,0.0,0.4);

  36. pcvtkSDIView->GetRenderer()->AddActor(this->pvtkActor2D);

  37. pcvtkSDIView->GetRenderer()->ResetCamera();

  38. }

  39. }