65.9K
CodeProject 正在变化。 阅读更多。
Home

借助 CPictureEx 和 CPictureExWnd 为您的 MFC 和 ATL 项目添加 GIF 动画

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.95/5 (76投票s)

2001年10月5日

5分钟阅读

viewsIcon

1368697

downloadIcon

33518

一个用于显示 GIF 动画以及更多内容的类。提供 MFC 和 ATL 版本!

Sample Image

引言

CPictureEx 类最初是为了一个 MFC 项目编写的,该项目

需要支持 JPEG 和 GIF 格式的横幅广告。静态横幅广告使用 OleLoadPicture 函数和 IPicture 接口显示并不难,但处理 GIF 动画则完全是另一回事。

在搜索了无数的互联网链接后,我发现只有一个免费选项——CodeGuru 上 George Tersaakov 的一个 COM 对象。不幸的是,它在显示我的一些测试 GIF 时存在问题。当然,我可以购买第三方库,但那样的话,我就得为我实际上不需要的额外功能付费。我决定尝试自己写一个类。基本思路是将 GIF 分割成单独的帧,然后使用熟悉的 OleLoadPictureIPicture 组合来显示这些帧。在仔细阅读了 GIF87a 和 GIF89a 的规范后,我编写了这个类。请注意,CPictureEx 不仅可以显示 GIF(包括 GIF 动画),还可以显示 JPEG、BMP、WMF、ICO 和 CUR(即 OleLoadPicture 支持的所有格式)。之后,我又编写了该类的 ATL 版本。

如何使用 MFC 版本(CPictureEx)

在您的对话框中添加一个静态文本控件或图片控件(分组框也可以);将该控件的 ID 改为类似 IDC_MYPICTURE 的名称;使用类向导将一个成员变量(例如 m_Picture)与添加的控件关联,类别 - 控件,变量类型 - CStatic;在对话框的头文件中,将变量类型从 CStatic 替换为 CPictureEx(不要忘记 #include "PictureEx.h",并将 PictureEx.hPictureEx.cpp 添加到您的项目中);在 OnInitDialog(或您喜欢的任何地方)中,添加以下代码行

if (m_Picture.Load(_T("mypicture.gif")))
    m_Picture.Draw();

坐下来,享受动画吧 :)

您也可以将 CPictureEx 当作标准的 CStatic 来处理,并通过手动调用 CPictureEx::Create(),然后调用 CPictureEx::LoadCPictureEx::Draw 来创建它(如果您的宿主窗口不是对话框,则必须这样做)。

如何使用 ATL 版本(CPictureExWnd)

要使用 ATL 版本(CPictureExWnd),请遵循相同的步骤,但不要使用类向导,而是手动在您的类中添加一个 CPictureExWnd 类型的变量,并将以下代码添加到您的 WM_INITDIALOG 处理函数中

HWND hWnd = GetDlgItem(IDC_MYPIC);
if (hWnd) m_wndBanner.SubclassWindow(hWnd);

之后,您可以调用 CPictureExWnd::Load()CPictureExWnd::Draw()。当然,您也可以直接调用 CPictureExWnd::Create——CPictureExWnd 只是一个带有额外窗口过程功能的窗口。

接口函数

  • BOOL Load(...) - 加载 GIF 并准备对象以供绘制;
  • BOOL Draw() - 绘制图片或继续动画;
  • void Stop() - 停止动画;
  • void UnLoad() - 停止动画并释放所有资源;
  • void SetBkColor(COLORREF) - 设置透明区域的填充颜色;
  • COLORREF GetBkColor() - 获取当前填充颜色;
  • BOOL IsGIF() - 如果当前图片是 GIF,则返回 TRUE
  • BOOL IsAnimatedGIF() - 如果当前图片是 GIF 动画,则返回 TRUE
  • BOOL IsPlaying() - 如果当前图片正在显示动画,则返回 TRUE
  • SIZE GetSize() - 返回图片的尺寸;
  • int GetFrameCount() - 返回当前图片的帧数;
  • BOOL GetPaintRect(RECT *lpRect) - 返回当前绘制矩形;
  • BOOL SetPaintRect(const RECT *lpRect) - 设置当前绘制矩形;

CPictureEx[Wnd]::Load 有三个版本

BOOL Load(LPCTSTR szFileName);

此版本从文件 szFileName 加载图片。函数的返回值指示加载是否成功。

BOOL Load(HGLOBAL hGlobal, DWORD dwSize);

Load 获取一个全局内存块的句柄,该内存块使用 GlobalAllocGMEM_MOVEABLE 标志分配。函数**不释放**内存,因此请不要忘记使用 GlobalFree 释放它。返回值指示加载是否成功。

BOOL Load(LPCTSTR szResourceName,LPCTSTR szResourceType);

该函数获取一个包含图片的资源名称和一个资源类型名称。例如

m_Picture.Load(MAKEINTRESOURCE(IDR_MYPIC),_T("GIFTYPE"));

加载图片后,使用 CPictureEx[Wnd]::Draw() 函数进行显示。如果图片是 GIF 动画,该函数将启动一个后台线程来执行动画;如果图片是静态图片,则会立即使用 OleLoadPicture/IPicture 显示。您可以随时使用 CPictureEx[Wnd]::Stop() 函数停止启动的线程。如果您想不仅停止动画,还要释放所有相关资源,请使用 CPictureEx[Wnd]::UnLoad()CPictureEx[Wnd]::Load() 会自动调用 UnLoad())。

默认情况下,图片的背景填充为 COLOR_3DFACE(对话框窗口的背景色)。如果您需要更改图片的背景,请在调用 CPictureEx[Wnd]::Load() 后调用 CPictureEx[Wnd]::SetBkColor(COLORREF)

版本历史

  • 1.0 (2001 年 8 月 7 日) - 初始发布;
  • 1.1 (2001 年 9 月 6 日) - 类的 ATL 版本;
  • 1.2 (2001 年 10 月 31 日) - 各种 bug 修复
    • 修复了 MFC 版本类中多模块应用程序加载 GIF 资源的问题。感谢 Ruben Avila-Carretero 发现此问题。
    • ThreadAnimation() 中删除了可等待计时器,现在 CPictureEx[Wnd] 可以在 Win95 上运行。感谢 Alex Egiazarov 和 Wayne King 的建议。
    • 修复了使用 SetBkColor 时的视觉瑕疵。感谢 Kwangjin Lee 发现此问题。
  • 1.3 (2001 年 11 月 18 日) - bug 修复和新功能
    • 修复了 DC 泄漏问题。每次 UnLoad() 都会泄漏一个 DC(忘记在 CPictureExWnd::PrepareDC() 函数末尾放置 ReleaseDC())。
    • 现在可以使用 CPictureEx[Wnd]::SetPaintRect(const LPRECT) 函数设置剪裁矩形。LPRECT 参数告诉类应该显示图片的哪个部分。如果未设置剪裁 rect,则显示整个图片。感谢 Fabrice Rodriguez 的建议。
    • 增加了对 Stop/Draw 的支持。现在您可以 Stop() 一个 GIF 动画,然后再次 Draw() 它,它将从停止的帧继续动画。您还可以通过 IsPlaying() 函数知道 GIF 当前是否正在播放。
    • 删除了 math.h 并将 m_bExitThread 设置为 volatile。感谢 Piotr Sawicki 的建议。
© . All rights reserved.