Gif专题:在对话框上显示Gif图片

Gif专题:在对话框上显示Gif图片

作者:BlogUpdater |  时间:2018-07-01 |  浏览:1331 |  评论已关闭 条评论

在上一篇文章中,我们介绍了如何导入一张Gif图片到VS2010中,今天我们继续讲解如何在对话框上显示Gif图片。
本文用到了上一篇文章中示例工程。

添加测试按钮
我们这次重点是描述如何加载并显示Gif图片,所以为了方便描述,我们首先在资源视图中添加一个按钮,当按钮被点击的时候,显示Gif图片的代码被执行,对话框上显示Gif图片。但是,这种方式下,因为显示Gif是一个阻塞过程,所以显示Gif的同时,对话框界面线程被阻塞。实际工程中,应该使用工作线程的方式来实现。

添加Gif显示代码
首先在对话框的头文件中添加如下成员:


private:
afx_msg void OnBnClickedButtonShowGif();

private:
Image* image;  
GUID Guid;
UINT frameCount;
UINT framePos;

同时,在对话框的构造函数中,我们需要对这些数据成员进行初始化

image = NULL;
frameCount = 0;
framePos = 0; 

这里使用到了GDI+中的Image类,所以,需要在对话框的头文件中添加对GDI+的引用。

#include <GdiPlus.h>
using namespace Gdiplus;

接下来是GDI+的初始化,如果没有这个初始化,则可能加载GIF图片阶段会报错。
将以下代码添加到App类的InitInstance中

Gdiplus::GdiplusStartupInput StartupInput;  
GdiplusStartup(&m_gdiplusToken, &StartupInput, NULL);

当然,我们先添加一个名为m_gdiplusToken数据成员

ULONG_PTR m_gdiplusToken;

在对话框类的实现代码中,我们首先定义一个函数,用来加载指定的资源ID到Image对象。

bool ImageFromIDResource(UINT nID, LPCTSTR sTR, Image * &pImg)
{
	HINSTANCE hInst = AfxGetResourceHandle();
	HRSRC hRsrc = ::FindResource (hInst,MAKEINTRESOURCE(nID),sTR); // type
	if (!hRsrc)
		return FALSE;
	// load resource into memory
	DWORD len = SizeofResource(hInst, hRsrc);
	BYTE* lpRsrc = (BYTE*)LoadResource(hInst, hRsrc);
	if (!lpRsrc)
		return FALSE;
	// Allocate global memory on which to create stream
	HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, len);
	BYTE* pmem = (BYTE*)GlobalLock(m_hMem);
	memcpy(pmem,lpRsrc,len);
	IStream* pstm;
	CreateStreamOnHGlobal(m_hMem,FALSE,&pstm);
	// load from stream
	pImg=Gdiplus::Image::FromStream(pstm);
	// free/release stuff
	GlobalUnlock(m_hMem);
	pstm->Release();
	FreeResource(lpRsrc);
	return TRUE;
}

最后,在按钮的点击响应代码中,我们的实现代码如下:

void CTestDlg::OnBnClickedButtonShowGif()
{
	// 导入Gif资源到Image对象
	ImageFromIDResource(IDR_GIF1, L"GIF",  image);

	UINT count = image->GetFrameDimensionsCount();
	GUID *pDimensionIDs = (GUID*)new GUID[count];
	image->GetFrameDimensionsList(pDimensionIDs, count);
	WCHAR strGuid[39];
	StringFromGUID2(pDimensionIDs[0], strGuid, 39);
	frameCount = image->GetFrameCount(&pDimensionIDs[0]);
	delete[] pDimensionIDs;

	// 这里的代码主要是为了下面计算等待时间
	UINT FrameDelayNums = image->GetPropertyItemSize(PropertyTagFrameDelay);
	PropertyItem* lpPropertyItem = new PropertyItem[FrameDelayNums];
	image->GetPropertyItem(PropertyTagFrameDelay, FrameDelayNums, lpPropertyItem);

	// 设置初始显示帧,这里的framePos为0
	Guid = FrameDimensionTime;
	image->SelectActiveFrame(&Guid, framePos);

	while (true)
	{
		if (image)
		{
			Graphics gh(m_hWnd);
			gh.DrawImage(image, 0, 0, image->GetWidth(), image->GetHeight());

			// 绘制背景
			Color clrTextForBrush;
			clrTextForBrush.SetFromCOLORREF(RGB(212, 208, 200));
			SolidBrush brush(clrTextForBrush);
			gh.FillRectangle(&brush, 0, 0, image->GetWidth(), image->GetHeight());

			// 绘制当前帧
			gh.DrawImage(image, 0, 0, image->GetWidth(), image->GetHeight());

			// 更新当前帧
			image->SelectActiveFrame(&Guid, framePos);
			framePos++;
			if (framePos == frameCount){
				framePos = 0;
			}
			long lPause = ((long*)lpPropertyItem->value)[framePos]*10;
			Sleep(lPause);
		}
	}
}

需要注意的地方
我们使用的是一张具有透明背景的Gif图片资源,所以在以上绘制代码中,我们首先按照对话框的颜色绘制了相同颜色的背景。
如果不加入绘制背景的代码,则Gif绘制会出现背景随机混乱的问题。

完工
修改好代码后,编译执行,点击按钮,就可以看到对话框上显示我们导入的Gif图片了。

标签:

评论已关闭。