如果你是一个使用VB编程的程序员,要在程序中显示JPG或者GIF图像简直易如反掌,将图像控件拖到Form中,分分钟即可搞掂。但是C++程序员要显  示同样的图形却没有那么轻松,那么是不是要自己编写JPG解压缩代码呢?当然不用那么复杂啦!本文将针对这个问题讨论如何在MFC中显示JPG或者GIF 图像。

用VB写图像显示程序之所以如此轻松,完全是利用了琳琅满目的图像处理控件,把你想要做的事情都一一搞掂。而C++程序员为了实现相同的功能必须忙 乎半 天。其实,C/C++程序员也能使用那些VB程序员所用的(或者说几乎一样的)图像控件。VB用的图像控件实际上都基于一个系统级COM类—— IPicture。下面是有关 IPicture 的方法描述:

方法 描述
get_Handle 返回图像对象的Windows GDI句柄
get_Hpal 返回图像对象当前使用的调色板拷贝
get_Type 返回当前图像对象的的图像类型
get_Width 返回当前图像对象的图像宽度
get_Height 返回当前图像对象的图像高度
Render 在指定的位置、指定的设备上下文上绘制指定的图像部分
set_Hpal 设置当前图像的调色板
get_CurDC 返回当前选中这个图像的设备上下文
SelectPicture 将一个位图图像选入给定的设备上下文,返回选中图像的设备上下文和图像的GDI句柄
get_KeepOriginalForma 返回图像对象KeepOriginalFormat 属性的当前值
put_KeepOriginalFormat 设置图像对象的KeepOriginalFormat 属性
PictureChanged 通知图像对象它的图像资源改变了
SaveAsFile 将图像数据存储到流中,格式与存成文件格式相同
get_Attributes 返回图像位属性当前的设置

从上面这个表可以看出,IPicture操纵着图像对象及其属性。图像对象提供对位图的抽象,而Windows负责BMP、JPG和GIF位图的标 准实 现。程序员要做的只是实例化IPicture,然后调用其Render函数。与通常使用接口的方式不同,这里实例的创建我们不用 CoCreateInstance函数,而是用一个专门的函数OleLoadPicture。

[cpp] view plaincopyprint?
  1. IStream* pstm = // 需要一个流(stream)
  2. IPicture* pIPicture;
  3. hr = OleLoadPicture(pstm, 0, FALSE, IID_IPicture, (void**)&pIPicture);
  4. OleLoadPicture从流中加载图像并创建一个可用来显示图像的新IPicture对象。

IStream* pstm = // 需要一个流(stream) IPicture* pIPicture; hr = OleLoadPicture(pstm, 0, FALSE, IID_IPicture, (void**)&pIPicture); OleLoadPicture从流中加载图像并创建一个可用来显示图像的新IPicture对象。

rc = // 显示图像的矩形
// 将rc 转换为 HIMETRIC
spIPicture->Render(pDC, rc);      

IPicture 负责处理所有琐事,以便确定图形之格式,如 Windows 位图、JPEG或者GIF文件——甚至是图标和元文件(metafiles)。当然啦,所有这些的实现细节是需要技巧的,为此我写了一个Demo程序 Myimgapp(如下图)来示范这些IPicture的使用方法。

Myimgapp是个典型的MFC文档/视图程序,在编写这个程序之前,我首先对 IPicture  COM接口进行封装,之所以要这么做,主要是考虑到并不是每一个程序员都能熟练运用COM接口进行编程,另外将IPicture的主要功能封装在C++类 中可以使我们的问题更容易解决,我封装的这个C++类名字叫做CPicture。它的定义和实现细节请参考本文提供的源代码。

我在这个类中将复杂而陌生的COM风格的参数映射成MFC程序员更为熟悉的类型。例如,CPicture可以让你直接从文件名加载一幅图 像,CFile或  者CArchive,而不用去处理流,CPicture::Render替你完成了IPicture中所有令人讨厌的但又是必须的HIMETRIC平滑转 换工作。CPicture甚至具备了一个Load函数,它可以从资源数据中加载图像,所以你只要用下面的代码就可以显示资源中的图像:

[cpp] view plaincopyprint?
  1. CPicture pic(ID_MYPIC); // 加载图像
  2. CRect rc(0,0,0,0); // 使用缺省的rc
  3. pic.Render(pDC, rc); // 显示图像

CPicture pic(ID_MYPIC); // 加载图像 CRect rc(0,0,0,0); // 使用缺省的rc pic.Render(pDC, rc); // 显示图像

CPicture::Render提供一个显示图片的矩形。IPicture 对图像进行延伸处理。如果传递一个空矩形,则CPicture用图像本身的大小--不进行延伸处理。对于图像本身而言,CPicture查  找"IMAGE"类型的资源,所以在资源文件中你必须要加入下面的代码:

[cpp] view plaincopyprint?
  1. IDR_MYPIC IMAGE MOVEABLE PURE "res//MyPic.jpg"

IDR_MYPIC IMAGE MOVEABLE PURE "res//MyPic.jpg"

CPicture是个很棒的傻瓜类,它具备一个 ATL 智能指针CComQIPtr指向IPicture接口,通过调用OleLoadPicture来初始化不同的Load函数。CPicture提供了常用的 打包函数来调用底层的 IPicture。CPicture只封装了那些在Demo例子程序中要用到的方法。如果你需要调用IPicture::get_Handle或其它一些 很少用到的IPicture方法,你可以自己尝试编写相应的打包代码。  另外,在编写完CPicture之后,我发现了一个现成的MFC类——CPictureHolder,这个类的功能几乎与CPicture完全一样,你可 以在afxctl.h文件中找到它的定义。  前面说过,Demo例子是个典型的MFC文档/视图应用程序,因此它肯定少不了与文档和视图类相对应的CPictureDoc 和CPictureView:

CPictureDoc类没有什么特别的处理代码,它用CPicture对象存储图像:

[cpp] view plaincopyprint?
  1. class CPictureDoc : public CDocument {
  2. protected:
  3. CPicture m_pict; // the picture
  4. };

class CPictureDoc : public CDocument { protected: CPicture m_pict; // the picture };

并且CPictureDoc::Serialize 调用CPicture::Load 从MFC存档的数据中读取图像。

[cpp] view plaincopyprint?
  1. void CPictureDoc::Serialize(CArchive& ar)
  2. {
  3. if (ar.IsLoading()) {
  4. m_pict.Load(ar);
  5. }
  6. }

void CPictureDoc::Serialize(CArchive& ar) { if (ar.IsLoading()) { m_pict.Load(ar); } }

为了使Myimgapp程序更实用,CPictureDoc::OnNewDocument从程序资源数据加载了一幅图像。为了显示这幅图  像,CPictureView::OnDraw要调用CPicture::Render。这样程序一启动便会显示一幅默认的图像。

[cpp] view plaincopyprint?
  1. void CPictureView::OnDraw(CDC* pDC)
  2. {
  3. CPictureDoc* pDoc = GetDocument();
  4. CPicture* ppic = pDoc->GetPicture();
  5. CRect rc;
  6. GetImageRect(rc);
  7. ppic->Render(pDC,rc);
  8. }

void CPictureView::OnDraw(CDC* pDC) { CPictureDoc* pDoc = GetDocument(); CPicture* ppic = pDoc->GetPicture(); CRect rc; GetImageRect(rc); ppic->Render(pDC,rc); }

GetImageRect是CPictureView类的一个成员函数,作用是根据当前Myimgapp的缩放比率(可用25%、33%、50%、 75%、100%或自适应方式)获取图像矩形。GetImageRect调用CPicture::GetImageSize来获得真正的图像大小,然后根 据比率显示。 CPictureView其余的部分完全和CScrollView的做法差不多,初始化视图并设置滚动大小,处理命令等等。唯一让人操心的是 IPicture::Render中HIMETRIC的处理问题,因为标准的MFC应用程序都使用MM_TEXT映射模型。不用担  心,CPicture::Render和CPicture::GetImageSize会将这一切转换过来,所以你不必为这些事情伤神。 CPictureView有一个消息处理器值得一提:它就是OnEraseBkgnd,当要显示的图像比客户区小的时候,这个函数必须绘制空白区域,如下 图,OnEraseBkgnd创建一个与图像大小相等的切边(clip)矩形,然后将客户区填成黑色。之所以要创建切边矩形,主要是避免当改变窗口大小时 出现的抖动——FillRect不绘制切边矩形内的区域,此乃Windows图形处理的常识。

IPicture/CPicture简化了图像的显示。它甚至可以实现调色板的识别这样复杂的处理。你完全可以抛开老式DIB 图像绘制方法,如加载调色板、BitBlts、StretchBlts等等——这一切IPicture全都可以搞掂。如果你未曾用IPicture显示过 图像,那么现在试试吧。 CPictureView完成图像浏览的任务看来不是什么难事了。但是如果要把一幅图像添加到一个对话框或者其它的什么窗口中怎么办呢?为此我创建了另外 一个类——CPictureCtrl。 CPictureCtrl 使你可以在任何对话框或窗口中把图像作为子窗口显示。例如:

[cpp] view plaincopyprint?
  1. class CAboutDialog : public CDialog {
  2. protected:
  3. CPictureCtrl m_wndPict;
  4. virtual BOOL OnInitDialog();
  5. };
  6. BOOL CAboutDialog::OnInitDialog()
  7. {
  8. m_wndPict.SubclassDlgItem(IDC_MYIMAGE,this);
  9. return CDialog::OnInitDialog();
  10. }

class CAboutDialog : public CDialog { protected: CPictureCtrl m_wndPict; virtual BOOL OnInitDialog(); }; BOOL CAboutDialog::OnInitDialog() { m_wndPict.SubclassDlgItem(IDC_MYIMAGE,this); return CDialog::OnInitDialog(); }

假设你的对话框中有一个静态控制,它的ID=IDC_IMAGE,并且有一幅IMAGE资源的ID与之相同。则从CStaticLink派生出的 CPictureCtrl还可以指定一个URL超链接(或者创建一个ID与此控制或图像的ID相同的串资源)。如果你指定了一个URL,则在图像上单击鼠 标将启动默认浏览器访问URL。真是酷呆了。CPicture控制着CPicture对象并改写WM_PAINT消息处理例程,调用 CPicture::Render代替通常的静态控制处理例程。处理细节请参见代码。打开Myimgapp程序的“关于”对话框就知道了。

原文地址:http://www.hellocpp.net/Articles/Article/340.aspx

在MFC程序中显示 JPG/GIF图像相关推荐

  1. mfc 内嵌 本地html,MFC程序中内嵌网页,附示例工程

    最近在课程设计,因为小悠太懒了,是在不想用C++完成一些简单的文件上传下载操作,于是就想着将网页内嵌到程序中,上传下载神马的就直接使用网页Web来完成就好了,本示例中将演示在MFC程序中内嵌一个htm ...

  2. 在MFC程序中增加控制台窗口

    MFC程序中,如果想要输出调试信息,我们一般都是TRACE或者使用LOG文件,都不是很方便,第一个需要我们在调试状态下,第二个也要配置麻烦而且不直观.而使用Console来显示调试信息应该是更好的选择 ...

  3. DELPHI 开发的 OCX 控件在 MFC 程序中编辑框快捷键不好使的解决

    公司一个大型的项目中使用了 DELPHI 来开发 OCX 控件做数据库的管理,但是GIS图形系统使用 MFC 开发,最后将 OCX 嵌入到 MFC 程序中作为一个完整的系统交付用户使用,但是在使用过程 ...

  4. 在Perl程序中显示进度条之多姿多彩的自写代码

    在Perl程序中显示进度条之多姿多彩的自写代码 yixf 于 2011-11-29,09:57   方法一 1 2 3 4 5 6 7 8 #!/usr/bin/perlmy $max = 10; f ...

  5. 屏蔽基于对话框的MFC程序中按下ESC关闭窗口的功能

    在基于对话框的MFC程序中,如果你按下ESC,将会关闭对话框.如何屏蔽这个键呢,其实很简单,只要重载下PreTranslateMessage()即可. 方法:在对话框类上右击,选择"Add ...

  6. 在MFC对话框中显示html网页

    最近在写一个小软件,想在MFC对话框中显示帮助文档,都是html格式的,上网找了好多资料,用一个CHtmlCtrl类的东西,但是网上找的这个类放在VS2005下编译不过去,老是提示错误.于是几经修改, ...

  7. html跳转 图文消息,GitHub - Arrrrray/newsToHtml: 微信公众号图文消息转换为HTML,方便插入到小程序中显示...

    newsToHtml 微信公众号图文消息转换为 HTML,方便插入到小程序中显示 项目来源 在编写公众号图文的时候,我们通常将一些小程序页卡插入其中.尤其是购物推荐类的公众号,用户在浏览图文消息的时候 ...

  8. MFC对话框中显示图片的四种方法

    先分类如下: (一) 非动态显示图片(即图片先通过资源管理器载入,有一个固定ID) (二) 动态载入图片(即只需要在程序中指定图片的路径即可载入) 为方便说明,我们已经建好一个基于对话框的工程,名为T ...

  9. 在小程序中显示地图并添加标注的教程

    前言 需求: 在小程序里显示地图,并标记地图上的一个坐标点. 管理员可以在后台设置坐标点 小程序显示地图和坐标点 .wxml文件 <view style="display:flex; ...

最新文章

  1. 读取复杂结构的yml配置项
  2. Git 学习笔记--3.EGit使用手册
  3. python全文检索引擎_Python中使用haystack实现django全文检索搜索引擎功能
  4. 264 参考帧 list0 list1
  5. JAVA--自制斐波那契数列输出
  6. 印度孟买机器人餐厅_2020,送餐机器人的海外市场爆发之年
  7. JAVA内存区域划分
  8. 决策树的三种常见算法
  9. 2022年暑期实习 PwC AC 普华永道信息技术 待遇+笔试+面试信息
  10. Android kotlin 大全
  11. 【转】七种常见阈值分割代码(Otsu、最大熵、迭代法、自适应阀值、手动、迭代法、基本全局阈值法)...
  12. 动画讲算法,终于来了!
  13. WebStorm中使用Live Tempalte
  14. CentOS 7使用samba共享文件夹
  15. python爬取哔哩哔哩网页弹幕内容,并将爬取的内容以五角星的形式显示出来
  16. STM32CUBEIDE(11)----输出PWM及修改PWM频率与占空比
  17. 周末愉快:洗碗就是洗碗
  18. 安科瑞预付费云平台系统在天津某大厦改造项目的研究与应用-Susie 周
  19. 《和声学教程》学习笔记(一):原位正三和弦及连接
  20. 【傅老师DarkSouls第一季】02

热门文章

  1. poj2513Colored Sticks(无向图判欧拉路、回路+trie树)
  2. [转]Time Tracker Starter Kit 简介
  3. PIL Error, TypeError: Cannot handle this data type:(1, 1), <i8
  4. cmd命令不识别exp_sqlplus、exp、imp不是内部或外部命令,也不是可运行的程序
  5. oracle no expand,NO_EXPAND Hint性能优化一例
  6. token怎么获取 php,如何用php获取某个页面中的input的csrf_token?
  7. css3制作八棱锥_CSS3制作各种形状图像
  8. linux path_lookup,Linux虚拟文件系统(4)-- 路径名查找
  9. php相差天数,php获取给定日期相差天数
  10. OpenCV-Python实战(19)——OpenCV与深度学习的碰撞