在GDI+中繪制GIF

GDI+中繪制一個(gè)圖片的代碼如下:
void CMyWnd::OnPaint()
{
CPaintDC dc(this);
Graphics graphics(&dc); // Create a GDI+ graphics object

Image image(L"Test.Gif"); // Construct an image
graphics.DrawImage(&image, 0, 0, image.GetWidth(), image.GetHeight());
}

Gif 分為兩種,一種是靜態(tài)的,對(duì)于這種格式的Gif,在GDI+中無(wú)需采用任何方法就能夠直接顯示(上面的代碼就屬于這種情況)。另一種是動(dòng)態(tài)的, 這種文件能夠顯示簡(jiǎn)單的動(dòng)畫(huà)。動(dòng)態(tài)的實(shí)際上由多幅靜態(tài)的組成,在顯示Gif時(shí),每幅圖片按照一定的時(shí)間間隔依次進(jìn)行顯示,從而實(shí)現(xiàn)了動(dòng)畫(huà)效果。
我把GIF封裝成了一個(gè)類(lèi)ImageEx,這個(gè)類(lèi)繼承了GDI+中的Image類(lèi)。我們首先要做的工作是判斷GIF是動(dòng)態(tài)的還是靜態(tài)的。
bool ImageEx::TestForAnimatedGIF()
{
UINT count = 0;
count = GetFrameDimensionsCount();
GUID* pDimensionIDs = new GUID[count];

// 得到子幀的對(duì)象列表
GetFrameDimensionsList(pDimensionIDs, count);

//獲取總幀數(shù)
m_nFrameCount = GetFrameCount(&pDimensionIDs[0]);

// 假設(shè)圖像具有屬性條目 PropertyItemEquipMake.
// 獲取此條目的大小.
int nSize = GetPropertyItemSize(PropertyTagFrameDelay);

// 為屬性條目分配空間.
m_pPropertyItem = (PropertyItem*) malloc(nSize);
GetPropertyItem(PropertyTagFrameDelay, nSize, m_pPropertyItem);
delete pDimensionIDs;
return m_nFrameCount > 1;

}
m_pPropertyItem->value 是一個(gè)長(zhǎng)整形數(shù)組, 每個(gè)長(zhǎng)整形代表每幀的延時(shí)。由于獲取的屬性不同,GetPropertyItem會(huì)獲得不同大小的對(duì)象, 因此要由用戶(hù)來(lái)獲得的對(duì)象大小,開(kāi)辟與刪除 GetPropertyItem相關(guān)的內(nèi)存。對(duì)象的大小是通過(guò)GetPropertyItemSize 獲取的,其參數(shù)是你所感興趣的屬性條目。 一旦獲取了幀的數(shù)量與延時(shí),我們就可生成一個(gè)線(xiàn)程來(lái)調(diào)用 DrawFrameGIF()來(lái)顯示。
bool ImageEx::DrawFrameGIF()
{
::WaitForSingleObject(m_hPause, INFINITE);
GUID pageGuid = FrameDimensionTime;
long hmWidth = GetWidth();
long hmHeight = GetHeight();
HDC hDC = GetDC(m_hWnd);
if (hDC)
{
Graphics graphics(hDC);
graphics.DrawImage(this, m_rc.left, m_rc.top, hmWidth, hmHeight);
ReleaseDC(m_hWnd, hDC);
}
SelectActiveFrame(&pageGuid, m_nFramePosition++);
if (m_nFramePosition == m_nFrameCount)
m_nFramePosition = 0;

long lPause = ((long*) m_pPropertyItem->value)[m_nFramePosition] * 10;
DWORD dwErr = WaitForSingleObject(m_hExitEvent, lPause);
return dwErr == WAIT_OBJECT_0;
}