CPictureEx 是一個為 MFC 程序使用的 C++ 類,對於一些需要使用JPEG 和 GIF 圖像格式作為 banner 的應用程序可以借助這個類來實現。對於靜態 banner 的顯示使用 OleLoadPicture 函數和 IPicture 接口並不難實現,但處理帶動畫的 GIF實現方法則完全不同。
在網上查了很多相關資料,僅僅發現一個可以免費使用的資源——CodeGuru上一個由George Tersaakov 寫的COM 對象。不幸的是,我用自己的 GIF 測試這個 COM 對象時出現了一些問題。當然,我可以購買第三方軟件庫,那樣我得支付額外功能的費用(這些功能我都用不上)。無奈之下我嘗試自己編寫一個類。基本思路是將 GIF 切分成單獨的幀並借助自己谙熟的 OleLoadPicture 和 IPicture來顯示這些幀。研究了一番 GIF87a 和 GIF98a 規范後。我編寫了本文介紹的 C++ 類,希望你也派上用場。CPictureEx 這個不僅可以顯示 GIFs (包括動畫 GIFs),還可以顯示 JPEG,BMP,WMF,ICO和CUR(也就是說凡是 OleLoadPicture 識別的圖像都能處理和顯示)。在此基礎上我又完成了這個 C++ 類的 ATL版本。下面是程序運行截圖:
下面先介紹 CPictureEx 類 MFC 版本的使用方法
在對話框中添加一個靜態文本或圖像控件(使用 Group 屬性也是一個技巧);修改控件ID 以便標示不同的圖像,比如:IDC_MYPICTURE 等,創建控件關聯的變量(例如:m_Picture),類別取 “Control”,變量類型取“CStatic”,接下來在對話框的頭文件中用 CPictureEx 替代掉 CStatic,(記住包含頭文件#include "PictureEx.h"並在工程項目中添加 PictureEx.h 和 PictureEx.cpp文件)。在 OnInitDialog 函數中添加如下代碼:
if (m_Picture.Load(_T("mypicture.gif")))
m_Picture.Draw();
完成後即可運行程序看看顯示的圖像吧。
你還可以將 CPicture 作為標准的 CStatic 對待,並通過調用 CPictureEx::Create() 函數手動創建它(如果你的宿主窗口不是對話框,你必須得這麼做),然後再調用 CPictureEx::Load 和 CPictureEx::Draw。
如何使用 CPictureEx 的 ATL 版本 CPictureExWnd
ATL 版本 CpictureExWnd 的使用方法類似於它的 MFC 版本,只不過需要手工在你的類中添加 CpictureExWnd 變量並在 WM_INITDIALOG處理加函數中加入相應的代碼:
HWND hWnd = GetDlgItem(IDC_MYPIC);
if (hWnd) m_wndBanner.SubclassWindow(hWnd);
然後調用CPictureExWnd::Load() 和 CPictureExWnd::Draw().。當然你也可以直接調用CPictureExWnd::Create ——在Windows 窗口過程中,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);
該版本的Load函數從一個文件加載。返回類型表示加載是否成功。
BOOL Load(HGLOBAL hGlobal, DWORD dwSize);
該版本的Load函數獲取全局內存塊句柄,用 GlobalAlloc 及 GMEM_MOVEABLE 標志分配內存。該函數不會釋放分配的內存,所以不要忘記調用 GlobalFree。返回值表示加載是否成功。
BOOL Load(LPCTSTR szResourceName,LPCTSTR szResourceType);
該函數獲取圖像資源名和資源類型,例如:
m_Picture.Load(MAKEINTRESOURCE(IDR_MYPIC),_T("GIFTYPE"));
獲取資源名和類型後加載對應的圖像,並用 CPictureEx[Wnd]::Draw() 顯示圖像,如果圖像是動畫 GIF,該函數會啟動一個背景處理線程完成動畫顯示,對於非動畫 GIF,則用 OleLoadPicture/IPicture。顯示。
任何時候你都可以用 CPictureEx[Wnd]::Stop() 函數終止背景處理線程。如果你不僅想停止動畫,還想釋放所有資源,使用 CPictureEx[Wnd]::UnLoad() (CPictureEx[Wnd]::Load() 自動調用UnLoad() )。
缺省情況下,圖像的背景是用 COLOR_3DFACE 填充的(對話框窗口的顏色),如果你需要改變圖像背景,調用 CPictureEx[Wnd]::Load()之後調用 CPictureEx[Wnd]::SetBkColor(COLORREF) 即可。
使用 CPictureEx[Wnd]::SetPaintRect(const LPRECT) 函數可以設置一個剪貼矩形,LPRECT 參數告訴類它應該顯示圖像的哪一部分。如果不設置剪貼矩形,則顯示整幅圖像。
使用 Stop()/Draw() 可以停止動畫GIF,調用Draw() 後可繼續從停止的那一幀繼續顯示。借助 IsPlaying() 函數,你還可以知道當前是否在顯示動畫。
實現細節請參考源代碼。
本文配套源碼