VTK与MFC联合编程实现的单文档实例vtkSDI详解

来源:互联网 发布:linux l2tp client 编辑:程序博客网 时间:2024/04/29 10:29

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.cppinline 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// CvtkSDIViewIMPLEMENT_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/destructionCvtkSDIView::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 printingBOOL 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 _DEBUGvoid 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 handlersint 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 onceclass CvtkSDIDoc : public CDocument{protected: // create from serialization only  CvtkSDIDoc();  DECLARE_DYNCREATE(CvtkSDIDoc)// Attributesprivate:  vtkDataSetReader *pvtkDataSetReader;// Operationspublic:// Overrides  public:  virtual BOOL OnNewDocument();  virtual void Serialize(CArchive& ar);// Implementationpublic:  virtual ~CvtkSDIDoc();#ifdef _DEBUG  virtual void AssertValid() const;  virtual void Dump(CDumpContext& dc) const;#endifprivate:  void ExecutePipeline();  void RemoveActors();
//数据处理和显示的mapper和actor对象  vtkDataSetMapper  *pvtkDataSetMapper;  vtkActor      *pvtkActor;  vtkActor2D      *pvtkActor2D;  vtkTextMapper    *pvtkTextMapper;// Generated message map functionsprotected:  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// CvtkSDIDocIMPLEMENT_DYNCREATE(CvtkSDIDoc, CDocument)BEGIN_MESSAGE_MAP(CvtkSDIDoc, CDocument)END_MESSAGE_MAP()// CvtkSDIDoc construction/destructionCvtkSDIDoc::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 serializationvoid CvtkSDIDoc::Serialize(CArchive& ar){  if (ar.IsStoring())  {    // TODO: add storing code here  }  else  {    // TODO: add loading code here  }}// CvtkSDIDoc diagnostics#ifdef _DEBUGvoid CvtkSDIDoc::AssertValid() const{  CDocument::AssertValid();}void CvtkSDIDoc::Dump(CDumpContext& dc) const{  CDocument::Dump(dc);}#endif //_DEBUG// CvtkSDIDoc commandsvoid 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构建自己的工程了。


0 0