暗夜心慌慌在哪里看:在你的MFC应用程序中显示一个JPG文件 - VC知识 - 界面程序资源 - DirectUI Skin UIPower专业界面开发与设计论坛 软件界面|界面开发 - Powered by Discuz!

来源:百度文库 编辑:中财网 时间:2024/04/29 01:41:07



DirectUI Skin++UIPower专业界面开发与设计论坛»界面程序资源 »VC知识 »在你的MFC应用程序中显示一个JPG文件
返回列表回复发帖
发新话题
发 布投票
发 布悬赏
发 布辩论
发 布活动
发 布视频
发 布商品

乞丐
发短消息
加为好友
uifan
UID
112
帖子
0
精 华
0
积分
-100
威望
-50
金 币
0 枚
贡献
0
阅读权限
0
在线 时间
0 小时
注册时间
2009-6-12


乞丐
 
1#打印 字体大小: tT
uifan发 表于 2009-12-13 23:08 |只看该作者
在你的MFC应用程序中显示一个JPG文件
>在你的MFC应用程序中显示一个JPG文件
原著:Paul DiLascia
翻译:flyzling
原文出处:MSDN       Magazine October 2001(C++ Q&A)
原代码下载:CQA0110.exe (202KB)
在VB中,我可以通过创建一个图像控件来显示一个JPG或GIF文件,但是我如何在我的MFC应用程序中显示一个JGP文件呢?
许多读者
好问题!有时使用VB的程序员觉得这个很容易。只要往你的表中拖入一个图像控件,然后你就可以往下做了……然而C++程序员就不得不感到烦恼和头疼。那我 们要做些什么呢,编写我们自己的JPG解压函数吗?
当然不是这样的!事实上,C/C++程序员能够使用与VB程序员所使用的非常类似(可以说是差不多)的图像控件。我并没有开玩笑。VB图像控件 是基于一个叫"IPicture"的系统COM类(如       Figure 1 所示)。IPicture管理一个图像对象和它的特性。图像对象为位图提供一个抽象化的东西。Windows提供 了一个知道如何处理BMP,JPG和GIF位图的标准操作。你所要做的只是使IPicture实例化,并调用Render。你可以调用一个叫 做"OleLoadPicture"的特殊函数,来替代通常所要调用的"CoCreateInstance"。
IStream* pstm = // 需要一个信息流
IPicture* pIPicture;
hr = OleLoadPicture(pstm, 0, FALSE,
IID_IPicture, (void**)&pIPicture);
OleLoadPicture从信息流里加载图像,并创建一个你能够用来显示图像的新的IPicture对象。
rc = // 要在其中显示的矩形
// 转换rc为HIMETRIC
spIPicture->Render(pDC, rc);
IPicture包揽了所有的令人厌烦的用来推算图像是否是Windows位图,JPEG,或GIF文件的事, 它甚至还可以推算图像是否是图标和图元文件!自然,其中的细节是需要些技巧,所以我就写了一个将它们都包含其中的叫"ImgView"( 如
Figure 2 所示)的演示程序。

Figure 2 ImgView
ImgView是一个典型的MFC文档/视图结构的应用程序,它使用了一个我以前写的叫"CPicture"的类(如       Figure 3 所示)来封装IPicture。CPicture将一些麻烦的COM类型的参数映射为那些更容易被MFC程序员接 受的类型。例如,CPicture可以让你直接从一个文件名加载图像,如CFile或CArchive,而不是处理信息流;而且 CPicture::Render完成了所有的令人厌烦的而又是IPicture所需要的HIMETRIC坐标转换,这样,你就没必要去做这些了。 CPicture甚至还有一个可以从你的资源数据中加载图像的加载函数,所以要显示一个资源图像,你所要做的就是像下面那样写:
CPicture pic(ID_MYPIC); // 加载pic
CRect rc(0,0,0,0);      // 使用默认 rc
pic.Render(pDC, rc);    // 显示它
什么能够使工作变得更加容易呢?CPicture::Render能获得一个你想在其中显示图像的矩形。IPicture可以适当地拉伸图像。 如果你传递了一个空的矩形,CPicture就使用图像本来的尺寸,并不对其进行拉伸。对于图像本身,CPicture要寻找一个名为"IMAGE"的资 源类型,所以你必须对你的RC文件进行如下的编写:
IDR_MYPIC IMAGE MOVEABLE PURE "res\MyPic.jpg"
总的来说,CPicture相当没头脑。它有一个ATL CComQIPtr巧妙的指向 IPicture界面的指针,其中不同的加载函数通过调用OleLoadPicture来初始化该界面。CPicture提供一般的封装函数来调用里面的 IPicture。CPicture仅封装了我编写ImgView所需要的IPicture成员函数;这么做是因为我是这样的一个懒惰的程序员。如果你还 需要调用IPicture::get_Handle或一些其它的较少用的IPicture成员函数,很抱歉,你就只好自己为其添加封装了。至少,这代码是 件琐碎的事情。
顺便说一下,在我写完CPicture后,我就觉得有件事要提一下,那就是我发现一个鲜为人知的叫 做"CPictureHolder"的MFC类也做了绝大部分的类似的事情。你可以在afxctl.h中找到它。
正如我先前提到的,ImgView是一个典型的MFC文档/视图结构的应用程序,其中 CPictureDoc和CPictureView类分别对应于文档和视图结构。如       Figure 4 所示 中显示了该视图。CPictureDoc有些琐碎;它使用CPicture来保存图像--
class CPictureDoc : public CDocument {
protected:
CPicture m_pict; // 图像
};
,并且CPictureDoc::Serialize调用CPicture:oad从MFC所建立的存档中读取图像。
void CPictureDoc::Serialize(CArchive& ar)
{
if (ar.IsLoading()) {
m_pict.Load(ar);
}
}
仅仅是为了有趣,CPictureDoc::OnNewDocument从程序的资源数据中加载了一张漂亮的NASA图像。为了显示这图 像,CPictureView::OnDraw调用了CPicture::Render。
void CPictureView::OnDraw(CDC* pDC)
{
CPictureDoc* pDoc = GetDocument();
CPicture* ppic = pDoc->GetPicture();
CRect rc;
GetImageRect(rc);
ppic->Render(pDC,rc);
}
GetImageRect是CPictureView的一个函数,它依靠当前ImgView缩放比例而返回一个适当的图像矩形。(ImgView可以 通过25%,33%,50%,75%,100%或"自适应比例"这六种比例形式来显示图像)。GetImageRect调用 CPicture::GetImageSize获得真实的图像尺寸,随后依据比例适当地缩放。
现在,在CPictureView中剩下的就是典型的CScrollView部分,其中有用于视的初始化和 滚动条尺寸与句柄命令的设置之类的代码。对于IPicture唯一有意思的是,正如之前我所提到的,IPicture::Render希望它的坐标是 HIMETRIC单位的,然而一般的MFC应用程序使用的是默认的MM_TEXT映射模式。不要担心,CPicture::Render和 CPicture::GetImageSize对其做了魔术般的转换,所以你就没必要为这样世俗的和令人厌烦的琐事而操过多的心了。
CPictureView有一个消息处理函数值得注意,它就是OnEraseBkgnd。它被要求在图像比 视的客户区小的情况时对空白的区域进行填充(如图5所示)。OnEraseBkgnd创建一个与图像大小一样的剪切的矩形,然后将客户矩形填充为黑色。当 你变化窗口尺寸的时候,这样的剪切就避免了闪烁,其中的FillRect并没有往被剪切的矩形中填充。这是标准的Windows图形101。

图 5  OnEraseBkgnd填充被剪切的图像
IPicture/CPicture真正使得显示图像变得容易了。它甚至可以完成调色板的实现和所有令人厌烦的事情。你可以丢掉原先所有的用来加载调 色板,BitBlts和StretchBlts等的DIB的绘图代码了,IPicture是个很好的办法。如果你还没有使用IPicture来显示图像, 那么现在就开始用它吧!
所有的事情都是这么的简单,这让我想写另一个类来试试。当你想写一个图像浏览器 时,CPictureView是很好用的,但要是你想将一个图像加到对话框或其它的一些窗口上,那该怎么办呢?为了实现这,我写了另一个 类,CPictureCtrl(如       Figure 6 所示)。CPictureCtrl可以让你将一个图像作为一个子控件放在任何的对话框或窗口上。例如:
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,同时还有一个具有相同ID的IMAGE资源。我从我那很常用的 CStaticLink中派生了CPictureCtrl,这样,如果你想的话就可以声明一个URL超链接了(或仅仅创建一个与控件和图像具有相同ID的 字符串资源)。如果你声明了一个URL,在这图像上点击鼠标将启动你的浏览器并实现这个链接。令人惊奇的是,CPicture保存了一个CPicture 对象,并通过重载WM_PAINT来调用CPicture::Render,而不是通过一般的静态控件。要想了解更多的细节,可从本文开始处的链接下载源 文件,使用它吧,我祝福你!
使用cppqa@microsoft.com 发送你的问题和评论给 Paul
作者简 介
Paul DiLascia 是一个自由作家,顾问和 Web/UI 方面资深的设计师。他是 Windows++: Writing Reusable
Windows Code in C++ (Addison-Wesley, 1992)一书的作者。你可以在
http://www.dilascia.com 网站和 Paul
联系上。
本文出自
MSDN Magazine 的
      October 2001 期刊,可通过当地
报摊获得,或者最好是订阅
本文由VCK
收藏分享评分
DirectUI 界面开发技术      DirectUI界面开发技术视频教程      DirectUI SDK文档
回复引用
订阅TOP
返回列表
UIPower.com(沪ICP备05028907号)|联系我们|论坛统计|Archiver|WAP|站长统计
GMT+8, 2010-3-21 20:31, Processed in 0.050604second(s), 7 queries, Gzip enabled.
Powered byDiscuz!7.0.0
© 2001-2009Comsenz Inc.
请问如何将十张jpg图片变在一个jpg文件中显示 mfc中如何在指定路径下新建一个文件 在MFC中,如何读取外部的位图文件,让它显示在图片控件(Picture Control)中? 如何在vc的mfc中载入*.lib文件 在MFC中如何获得打开文件的路径 一个mfc中listbox的问题 在VB中存储JPG文件的问题 图片文件,在JPG中打开显示大小,数值分别代表什么 在c++的mfc中怎样从一个文本框中获得文本? 在MFC程序中,MFC在后台维护了一个句柄和C++类对象指针的一个映射表 这个“表”在哪个地方??怎么理解? 有关MFC中编辑框的显示问题,请教高手。 在c++的mfc中,怎样用代码改变一个button的disabled属性值 在SQL中存的JPG图片怎样在VFP中显示出来? mfc编程:如何在一个工程中同时导入Excel和PowerPoint的类型库? 在photoshop中怎样把两个文件合成一个,然后存为JPG格式 VC++的MFC编程中,寻某头文件 在xp中如何让他人共享你的应用程序 在VISUAL C++中win32应用,win32控制台应用,基于MFC的应用程序它们有什么联系吗,还是各自独立的 [求助]创建了一个MFC单文档的应用程序,怎样改变窗口大小? 我做了一个MFC基于对话框的应用程序,其中有个树型控件, 我做了一个MFC基于对话框的应用程序,其中有个树型控件,。。。 为什么有些.jpg文件在pmp上显示不出来? 我的MFC程序中有这样一个问题。。。。。。。。。。。。。 一个MFC的程序,在没有安装vc的环境下需要哪些文件才能正常运行