static UINT GifThread(LPVOID GifDC)
{
CDC* pDC = (CDC*)GifDC;
HINSTANCE hAndle = ::AfxGetResourceHandle();
HRSRC hRsrc = ::FindResource(hAndle,MAKEINTRESOURCE(IDR_GIF1),"GIF");
DWORD word = ::SizeofResource(hAndle,hRsrc);
BYTE* lpBy = (BYTE*)LoadResource(hAndle,hRsrc);
BYTE* pByte[200];
DWORD nu[200];
int num = 0;
DWORD firstLocation = 0;
for(DWORD i=0;i<word;i++)
{
if(lpBy[i]==0x2c)
{
if(num==0)
{
firstLocation = i;
}
pGif nImage = (pGif)&lpBy[i+1];
DWORD number = 1+sizeof(Gif);
while(lpBy[i+number]!=0)
{
number = number+(DWORD)lpBy[i+number]+1;
}
number++;
pByte[num] = new BYTE[number];
for(DWORD n=0;n<number;n++)
{
(BYTE)(pByte[num]+n) = lpBy[i+n];
}
nu[num] = number;
i = i+number-1;
num++;
}
}
while(1)
{
for(int m=0;m<num;m++)
{
DWORD dWord;
VirtualProtect(lpBy,word,PAGE_READWRITE,&dWord);
for(DWORD n=0;n<nu[m];n++)
{
lpBy[firstLocation+n] = (BYTE)(pByte[m]+n);
}
VirtualProtect(lpBy,word,dWord,NULL);
CMemFile mfile(lpBy,word);
CArchive aRc(&mfile,CArchive::load|CArchive::bNoFlushOnDelete);
CArchiveStream aRcstream(&aRc);
CComQIPtr<IPicture> m_picture;
OleLoadPicture((LPSTREAM)&aRcstream,0,false,IID_IPicture,(void**)&m_picture);
long x,y;
m_picture->get_Width(&x);
m_picture->get_Height(&y);
CSize size(x,y);
pDC->HIMETRICtoDP(&size);
CRect rect;
m_picture->Render(*pDC,0,0,size.cx,size.cy,0,y,x,-y,&rect);
Sleep(30);
}
}
return 1;
}
该回答引用ChatGPT-3.5
下面是对给定的VC++播放GIF线程代码的详细注释:
static UINT GifThread(LPVOID GifDC)
{
CDC* pDC = (CDC*)GifDC; // 传入的参数为CDC*,用于绘图
HINSTANCE hAndle = ::AfxGetResourceHandle(); // 获取当前资源句柄
HRSRC hRsrc = ::FindResource(hAndle, MAKEINTRESOURCE(IDR_GIF1), "GIF"); // 查找资源句柄
DWORD word = ::SizeofResource(hAndle, hRsrc); // 获取资源大小
BYTE* lpBy = (BYTE*)LoadResource(hAndle, hRsrc); // 加载资源数据
BYTE* pByte[200]; // 存储解析后的GIF数据
DWORD nu[200]; // 存储每个GIF数据的大小
int num = 0; // GIF数据的数量
DWORD firstLocation = 0; // 第一个GIF数据的位置
// 解析GIF文件,将每个GIF数据存储到pByte和nu数组中
for (DWORD i = 0; i < word; i++)
{
if (lpBy[i] == 0x2c) // GIF数据的起始标志
{
if (num == 0)
{
firstLocation = i; // 记录第一个GIF数据的位置
}
pGif nImage = (pGif)&lpBy[i + 1]; // 指向当前GIF数据的指针
DWORD number = 1 + sizeof(Gif); // GIF数据的大小,包括标志字节和Gif结构体大小
while (lpBy[i + number] != 0) // 继续读取GIF数据的大小,直到遇到0标志
{
number = number + (DWORD)lpBy[i + number] + 1;
}
number++;
pByte[num] = new BYTE[number]; // 为当前GIF数据分配内存
for (DWORD n = 0; n < number; n++)
{
(BYTE)(pByte[num] + n) = lpBy[i + n]; // 将GIF数据复制到pByte中
}
nu[num] = number; // 记录当前GIF数据的大小
i = i + number - 1; // 跳过已解析的GIF数据
num++; // 增加已解析的GIF数据数量
}
}
// 循环播放GIF动画
while (1)
{
for (int m = 0; m < num; m++)
{
DWORD dWord;
VirtualProtect(lpBy, word, PAGE_READWRITE, &dWord); // 修改资源的保护属性,以便写入新的GIF数据
// 将解析后的GIF数据写入资源中,替换原始的GIF数据
for (DWORD n = 0; n < nu[m]; n++)
{
lpBy[firstLocation + n] = (BYTE)(pByte[m] + n);
}
VirtualProtect(lpBy, word, dWord, NULL); // 恢复资源的保护属性
// 创建内存文件和存档对象
CMemFile mfile(lpBy, word);
CArchive aRc(&mfile, CArchive::load | CArchive::bNoFlushOnDelete);
CArchiveStream aRcstream(&aRc);
// 使用OleLoadPicture函数加载图像数据
CComQIPtr<IPicture> m_picture;
OleLoadPicture((LPSTREAM)&aRcstream, 0, false, IID_IPicture, (void**)&m_picture);
long x, y;
m_picture->get_Width(&x); // 获取图像宽度
m_picture->get_Height(&y); // 获取图像高度
CSize size(x, y);
pDC->HIMETRICtoDP(&size); // 转换图像尺寸到设备坐标系
CRect rect;
// 渲染图像到设备上
m_picture->Render(*pDC, 0, 0, size.cx, size.cy, 0, y, x, -y, &rect);
Sleep(30); // 暂停一段时间,控制播放速度
}
}
return 1;
}
这段代码主要实现了从资源加载GIF文件并播放动画的功能。它解析了GIF文件中的每个图像帧,然后使用IPicture
接口加载并渲染图像到设备上。循环播放每个图像帧,通过Sleep
函数控制帧率。