您的位置:首页 > 其它

在MFC程序中显示 JPG/GIF图像

2013-01-07 10:12 393 查看
如果你是一个使用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?IStream* pstm = // 需要一个流(stream)
IPicture* pIPicture;
hr = OleLoadPicture(pstm, 0, FALSE, IID_IPicture, (void**)&pIPicture);
OleLoadPicture从流中加载图像并创建一个可用来显示图像的新IPicture对象。
[cpp] view plaincopyprint?CPicture pic(ID_MYPIC); // 加载图像
CRect rc(0,0,0,0);      // 使用缺省的rc
pic.Render(pDC, rc);    // 显示图像
CPicture pic(ID_MYPIC); // 加载图像
CRect rc(0,0,0,0);      // 使用缺省的rc
pic.Render(pDC, rc);    // 显示图像


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

[cpp] view plaincopyprint?IDR_MYPIC IMAGE MOVEABLE PURE "res//MyPic.jpg"
[cpp] view plaincopyprint?class CPictureDoc : public CDocument {
protected:
CPicture m_pict; // the picture
};
class CPictureDoc : public CDocument {
protected:
CPicture m_pict; // the picture
};


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

[cpp] view plaincopyprint?void CPictureDoc::Serialize(CArchive& ar)
{
if (ar.IsLoading()) {
m_pict.Load(ar);
}
}
[cpp] view plaincopyprint?void CPictureView::OnDraw(CDC* pDC)
{
CPictureDoc* pDoc = GetDocument();
CPicture* ppic = pDoc->GetPicture();
CRect rc;
GetImageRect(rc);
ppic->Render(pDC,rc);
}
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?class CAboutDialog : public CDialog {
protected:
CPictureCtrl m_wndPict;
virtual BOOL OnInitDialog();
};
BOOL CAboutDialog::OnInitDialog()
{
m_wndPict.SubclassDlgItem(IDC_MYIMAGE,this);
return CDialog::OnInitDialog();
}
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: