在GDI+中繪制GIF
GDI+中繪制一個圖片的代碼如下:
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
分為兩種,一種是靜態的,對于這種格式的Gif,在GDI+中無需采用任何方法就能夠直接顯示(上面的代碼就屬于這種情況)。另一種是動態的,
這種文件能夠顯示簡單的動畫。動態的實際上由多幅靜態的組成,在顯示Gif時,每幅圖片按照一定的時間間隔依次進行顯示,從而實現了動畫效果。
我把GIF封裝成了一個類ImageEx,這個類繼承了GDI+中的Image類。我們首先要做的工作是判斷GIF是動態的還是靜態的。
bool ImageEx::TestForAnimatedGIF()
{
UINT count = 0;
count = GetFrameDimensionsCount();
GUID* pDimensionIDs = new GUID[count];
// 得到子幀的對象列表
GetFrameDimensionsList(pDimensionIDs, count);
//獲取總幀數
m_nFrameCount = GetFrameCount(&pDimensionIDs[0]);
// 假設圖像具有屬性條目 PropertyItemEquipMake.
// 獲取此條目的大小.
int nSize = GetPropertyItemSize(PropertyTagFrameDelay);
// 為屬性條目分配空間.
m_pPropertyItem = (PropertyItem*) malloc(nSize);
GetPropertyItem(PropertyTagFrameDelay, nSize, m_pPropertyItem);
delete pDimensionIDs;
return m_nFrameCount > 1;
}
m_pPropertyItem->value
是一個長整形數組, 每個長整形代表每幀的延時。由于獲取的屬性不同,GetPropertyItem會獲得不同大小的對象,
因此要由用戶來獲得的對象大小,開辟與刪除 GetPropertyItem相關的內存。對象的大小是通過GetPropertyItemSize
獲取的,其參數是你所感興趣的屬性條目。 一旦獲取了幀的數量與延時,我們就可生成一個線程來調用 DrawFrameGIF()來顯示。
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;
}