基于VTK的MFC应用程序开发(1)

分类: VTK应用示例 2013-03-24 22:35 4195人阅读 评论(28) 收藏 举报
CMakeVTKMFC

目录(?)[+]

提到MFC一般都不陌生,大部分在校学生使用最多的应该就是它了。但是相对于Qt平台来说,MFC的机制比较复杂。当使用MFC平台进行VTK程序开发时,许多人可能没有头绪。这里结合一个实例讲一下如何在MFC平台下进行VTK程序开发。

这里在MFC下实现一个基于VTK的单文档图像显示程序。通过这个程序,主要演示两个方面:一是怎样使用CMake将MFC程序与VTK结合;二是怎样在MFC程序中调用VTK类实现具体的功能。这个也是基于MFC和VTK进行软件开发的基础,搭好这个框架后,以后的工作就是垒砖了,相信通过前面的学习,垒砖已经小菜一碟了。

在开始代码之前,这里提一下,相信许多人在网上查询这方面的资料的时候,有许多资料会讲到通过MFC中的开发环境(如Visual Studio 2008)设置VTK的包含路径和lib库路径等。但是这样配置对于一般用户来说比较复杂,每次开发新的工程时候,都要查找和设置这些库,既费时费力,又不利于程序的移植(例如换到另外一台机器,如果VTK编译路径不一致的话就会找不到库)。因此这里还是推荐大家使用CMake来管理程序。仅仅几行脚本代码就可以实现VTK库的配置,而且便于程序移植。

现在开始一步步实现VTK和MFC的程序开发。首先建立一个单文档的MFC工程,工程名字为vtkSDI。这里与基于Qt的VTK程序开发稍微有点不同。先建立工程的目的是我们需要把由MFC自动生成的类加入到CMakeLists.txt中,方便管理。MFC单文档工程的建立比较简单,过程不再演示。工程文件如下所示,主要的类为CvtkSDIApp,CMainFrame,CvtkSDIDoc,CvtkSDIView和CAboutDlg五个。由于我们使用CMake来配置和生成工程,因此将工程目录下的工程文件删除,主要是.ncb,.sln,.vcproj,.user文件。

图1 MFC单文档工程的建立时所包含的文件

下面编写CMakeLists.txt文件,将工程文件写入到CMakeLists.txt中并连接VTK动态库。VTK根据功能不同划分了多个不同的模块,每个模块都是一个库。因此在编写CMakeLists.txt文件的时候,可以根据需要添加相应的模块。

[plain] view plaincopy
  1. #----------------------------------------------------------------------------------
  2. cmake_minimum_required( VERSION 2.8 )
  3. project( vtkSDI )
  4. #----------------------------------------------------------------------------------
  5. # 查找并包含VTK工具包
  6. find_package( VTK )
  7. if (VTK_FOUND)
  8. include (${VTK_USE_FILE})
  9. else (VTK_FOUND)
  10. message (FATAL_ERROR "Cannot build without VTK. Please set VTK_DIR")
  11. endif( VTK_FOUND )
  12. #----------------------------------------------------------------------------------
  13. # 这里添加本工程的文件
  14. # 主要分为两部分:
  15. # 一是新建的单文档程序中的非工程文件
  16. # 二是用户后续添加的类文件
  17. SET( PROJECT_SRCS
  18. MainFrm.h
  19. MainFrm.cpp
  20. stdafx.h
  21. stdafx.cpp
  22. vtkSDI.h
  23. vtkSDI.cpp
  24. vtkSDIDoc.h
  25. vtkSDIDoc.cpp
  26. vtkSDIView.h
  27. vtkSDIView.cpp
  28. targetver.h
  29. Resource.h
  30. vtkSDI.rc
  31. res/vtkSDI.rc2
  32. res/vtkSDI.ico
  33. res/vtkSDIDoc.ico
  34. res/Toolbar.bmp
  35. res/Toolbar256.bmp
  36. )
  37. #----------------------------------------------------------------------------------
  38. # 设置工程包含的vtk模块,这里根据需要加载对应的模块
  39. include("${VTK_DIR}/GUISupport/MFC/VTKMFCSettings.cmake")
  40. set( VTK_LIBS ${vtk_libraries}
  41. vtkMFC
  42. vtkIO
  43. vtkRendering
  44. vtkGraphics
  45. vtkHybrid
  46. vtkFiltering
  47. vtkCommon
  48. vtkImaging
  49. )
  50. #----------------------------------------------------------------------------------
  51. ADD_EXECUTABLE( vtkSDI  WIN32  ${PROJECT_SRCS} )
  52. TARGET_LINK_LIBRARIES ( vtkSDI  ${VTK_LIBS} )
  53. <span style="font-size:14px;"> </span>

需要注意的是在倒数第二行中需要加入WIN32,否则生成的工程在编译时会出现错误。第二个需要注意的是,由于工程是基于MFC的,需要连接vtkMFC库。完成CMakeLists.txt文件后,利用CMake设置相应的代码路径(存放工程源代码)和工程路径(存在生成的工程和文件),配置、生成当前工程,得到工程文件vtkSDI.sln。

打开vtkSDI.sln并编译,编译后如无语法和链接错误,则可得到一个可运行的空工程。注意运行时可能会提示找不到dll文件错误,解决方法已在VTK与Qt整合的示例章节中说明,这里不再赘述。到此为止,基于MFC单文档工程的VTK编程框架已经搭建,接下来需要做的在该框架下调用VTK实现相应的功能。下面以图像的读取和显示为例进行说明。

首先为vtkSDI工程添加一个菜单项,通过该菜单项加载图像。打开工程的资源视图Resource View,双击Menu中IDR_MAINFRAME菜单,右键单击FILE菜单下的Open项,为该项添加一个事件Add Event Handler,弹出如下窗口:

图2 添加MFC事件响应向导

这里我们将该菜单的函数响应到CvtkSDIDoc文档类中,消息类型选择为COMMAND,点击Add and Edit按钮,完成消息的响应。该函数的作用是当用户选择该菜单时,弹出图像文件选择对话框,并将用户选择的图像文件加载。为此,我们需要为该类定义一个图像数据对象接收读入的图像数据。在CvtkSDIDoc头文件中添加如下代码,定义一个图像数据的智能指针:

vtkSmartPointer<vtkImageData> m_pImageData;

注意不要忘了添加头文件。在CvtkSDIDoc构造函数中对m_pImageData进行初始化,代码如下:

m_pImageData =vtkSmartPointer<vtkImageData>::New();

m_pImageData =NULL;

然后在菜单响应函数OnFileOpen中,添加读取图像的代码。这里以jpg格式的图像为例进行说。VTK中读取jpg图像的类为vtkJPEGReader,代码如下:

[cpp] view plaincopy
  1. void CvtkSDIDoc::OnFileOpen()
  2. {
  3. // TODO: Add your command handler code here
  4. CString FilePathName;
  5. CFileDialog dlg( TRUE, NULL, NULL,
  6. OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
  7. (LPCTSTR)_TEXT("JPG Files (*.jpg)|*.jpg|All Files (*.*)|*.*||"),
  8. NULL );
  9. if(dlg.DoModal()==IDOK)
  10. {
  11. FilePathName=dlg.GetPathName();
  12. vtkSmartPointer<vtkJPEGReader> reader = vtkSmartPointer<vtkJPEGReader>::New();
  13. reader->SetFileName(FilePathName.GetBuffer(0));
  14. reader->Update();
  15. m_pImageData = reader->GetOutput();
  16. }
  17. else
  18. {
  19. return;
  20. }
  21. }

下面在CvtkSDIView类中实现图像的显示功能。这里我们使用VTK中的类vtkImageViewer2。该类提供了强大的图像显示功能,可以接受vtkImageData输入,通过设置交互对象vtkRenderWindowInteractor实现用户交互,如窗宽窗位调节,图像放缩等。这里首先在CvtkSDIView头文件中定义vtkImageViewer2对象和窗口交互对象vtkRenderWindowInteractor。

vtkSmartPointer<vtkImageViewer2>                 m_pImageViewer;

vtkSmartPointer<vtkRenderWindowInteractor>m_pRenderWindowInteractor;

然后重载CvtkSDIView类的OnCreate()函数,在该函数中对定义的对象进行初始化,将MFC窗口句柄设置vtkImageViewer2的父窗口ID,以及设置vtkImageViewer2对象与vtkRenderWindowInteractor对象关联:

[cpp] view plaincopy
  1. int CvtkSDIView::OnCreate(LPCREATESTRUCT lpCreateStruct)
  2. {
  3. if (CView::OnCreate(lpCreateStruct) == -1)
  4. return -1;
  5. // TODO:  Add your specialized creation code here
  6. m_pImageViewer = vtkSmartPointer<vtkImageViewer2>::New();
  7. m_pImageViewer->SetParentId(GetSafeHwnd());
  8. m_pRenderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
  9. m_pImageViewer->SetupInteractor(m_pRenderWindowInteractor);
  10. m_pRenderWindowInteractor->Start();
  11. return 0;
  12. }

为了使图像能够居中显示,需要每次在窗口大小改变时,设置m_pImageViewer的大小。这里重载CvtkSDIView类的函数OnSize(),当每次响应该函数时,将当前窗口的客户区域大小设置为m_pImageViewer的大小。

[cpp] view plaincopy
  1. void CvtkSDIView::OnSize(UINT nType, int cx, int cy)
  2. {
  3. CView::OnSize(nType, cx, cy);
  4. // TODO: Add your message handler code here
  5. CRect rect;
  6. GetClientRect(rect);
  7. m_pImageViewer->SetSize(rect.Width(), rect.Height());
  8. }

最后在OnDraw函数中实现图像渲染。在该函数中,将文档类中读入的图像数据设置vtkImageViewer2的输入,然后调用m_pImageViewer的Render函数开始渲染图像,并监听外部消息实现交互功能。

[cpp] view plaincopy
  1. void CvtkSDIView::OnDraw(CDC* /*pDC*/)
  2. {
  3. CvtkSDIDoc* pDoc = GetDocument();
  4. ASSERT_VALID(pDoc);
  5. if (!pDoc)
  6. return;
  7. // TODO: add draw code for native data here
  8. m_pImageViewer->SetInput(pDoc->m_pImageData);
  9. m_pImageViewer->Render();
  10. }

编译链接后即可执行程序,运行结果如下所示。另外还可以测试交互功能,如按住鼠标右键拖动鼠标或者滑动滚轮,实现图像的放缩功能;按住鼠标左键,拖动鼠标即可实现图像窗宽窗位的调节。

图3 程序运行结果

从程序来看没有编译错误,而且正确显示图像。OK,关闭程序,这时意外出现了,在VS输出窗口中出现许多内存溢出,如下图所示:

图4 MFC&VTK程序内存溢出

这样的内存溢出是因为VTK的DLL先于MFC的DLL加载。因此在CMakeLists.txt中加入下面代码对VTK的DLL进行延迟加载,代码如下:

[plain] view plaincopy
  1. VTK_MFC_ADD_DELAYLOAD_FLAGS(CMAKE_EXE_LINKER_FLAGS
  2. vtkMFC.dll
  3. vtkIO.dll
  4. vtkRendering.dll
  5. vtkGraphics.dll
  6. vtkHybrid.dll
  7. vtkFiltering.dll
  8. vtkCommon.dll
  9. vtkImaging.dll
  10. )

添加如上代码后,重新编译工程(rebuild),运行然后关闭工程,观察VS输出窗口中的输出信息,没有内存溢出错误,正常退出。

==========欢迎转载,转载时请保留该声明信息==========

版权归@东灵工作室所有,更多信息请访问东灵工作室

教程系列导航:http://blog.csdn.net/www_doling_net/article/details/8763686

================================================

基于VTK的MFC应用程序开发(1)相关推荐

  1. 基于VTK的MFC应用程序开发(3)

    基于VTK的MFC应用程序开发(3) 分类: VTK应用示例 2013-05-17 13:37 3307人阅读 评论(23) 收藏 举报 目录(?)[+] 之前介绍了基于VTK的单文档应用程序开发,并 ...

  2. 基于VTK的MFC应用程序开发(2)

    基于VTK的MFC应用程序开发(2) 分类: VTK应用示例 2013-03-29 13:03 6647人阅读 评论(18) 收藏 举报 MFCVTK图像重采样 目录(?)[+] 现在基于VTK的MF ...

  3. 基于VTK的Qt应用程序开发

    分类: VTK应用示例 2013-03-13 15:51 6622人阅读 评论(25) 收藏 举报 VTKQtCMake 目录(?)[+] VTK附带的程序示例中大多是基于控制台的,作为可视化开发工具 ...

  4. 《基于Windows 7特性的程序开发系列》视频分享

    前一阵录制了<基于Windows 7特性的程序开发系列>视频课程,主要针对WinForm.WPF 开发具有Windows 7 特性的程序.现已发布到MSDN Webcast 欢迎大家拍砖. ...

  5. 小程序 | 基于WAMP的新闻网小程序开发(体验全栈式开发微信小程序)

    之前学习微信小程序开发,主要是基于JS.WXML.WXSS的前端开发,对于后端技术不精的我也是使用了微信开发者工具中的云开发功能,但是今天突发奇想,特别想体验一下全栈式开发微信小程序,学习了一下基于W ...

  6. 基于matlab的GPS单点定位程序开发(初学者)

    基于matlab的GPS单点定位程序开发 开发初衷 本人是测绘专业的学生,在初学GPS时遇到了很多代码问题,因此希望这篇文章能够帮助广大的测绘和导航专业的学子 代码开始 开发的第一部分是:文件读取,文 ...

  7. 基于VTK的PACS系统的开发 心路历程2

    中文操作手册-简介部分 翻译不易,且看且珍惜! 前言: 欢迎使用可视化工具包(VTK)的用户指南,VTK是一个开源的.面向对象的软件系统,用于计算机图形学.可视化. 和图像处理.虽然它大而复杂,一旦你 ...

  8. 基于ssm框架—微信小程序开发的会议管理系统

    本系统是基于ssm架构(Spring+SpringMVC+MyBatis)开发的后台管理会议系统,系统以Java作为编程语言,采用Mysql数据库作为后台数据库.它是基于Browser/Server结 ...

  9. 基于VFW的视频应用程序开发

    关  键  字: 视频捕获:SDK:VFW:AVI:MCI 当前,在Windows 平台下开发视频应用程序一般采用两种方式:一种是基于视频采集卡所附带的二次软件开发包SDK(Software deve ...

最新文章

  1. WebStrom如何设置字体?
  2. linux静默删除文件夹,Linux常用命令10 - unzip
  3. 如何进入embl的ebi网站fasta3服务器,The EMBL-EBI bioinformatics web and programmatic tools framework...
  4. 了解JavaScript中的循环缺点和迭代协议
  5. 北京大学计算机学院周磊,马秀莉-北京大学信息科学技术学院
  6. 谷歌浏览器:解决Chrome浏览器添加扩展程序报错无法从该网站添加应用、扩展程序和用户脚本
  7. html怎么设置自动音乐播放器,运用js教你轻松制作html音乐播放器
  8. 在angular的自定义回调中操作$scope
  9. 双线性对在密码学中的应用(下)
  10. Scrapy爬取当当网畅销图书保存csv格式!最详细的教程!
  11. memory hierachy
  12. PV-RCNN:Point-based与Voexl-based共同成就的高性能3D目标检测网络
  13. 麻将判断胡牌 java_麻将基本胡的算法——Java
  14. Reactjs开发基础
  15. 日记侠:你对微信关键词是如何理解的?
  16. css(六)--css高级技巧
  17. android下面res目录
  18. 006基于近似熵、递归量化分析和卷积神经网络的癫痫发作自动检测-2019
  19. 图灵机Turing Machine
  20. 常用软件官网下载地址

热门文章

  1. LINUX下文件字符集编码查看与转换并文件名编码转换
  2. MySQL事务的的介绍及使用
  3. layUI框架中文件上传前后端交互及遇到的相关问题
  4. Hive几种数据导入方式
  5. PetClinic 没有分页功能
  6. 人生何为苦何为乐何为幸福
  7. 重设忘记的Mysql密码
  8. blockhouses
  9. nyoj-483--Nightmare--BFS+允许回头
  10. nyoj1228矩形判断