在进行低层次SDK编程时,经常需要处理外部依赖问题。本文将介绍如何使用Windows Vista引入的桌面合成功能来实现这一点。桌面合成允许窗口内容先绘制到视频内存中的离屏表面,然后渲染到桌面图像上并显示出来。在Windows 8中,桌面窗口管理器(DWM)始终处于开启状态,用户和应用程序无法禁用。而在Windows Vista和Windows 7中,只有在启用AERO Glass主题时,桌面合成才会被激活。
为了实现这一功能,使用了GDIPLUS的平面API来循环显示PNG图像的每一帧,同时使用标准WAV音频文件,通过重新混音以匹配动画的持续时间。所有的资源都被嵌入到程序中,以生成单一的最终EXE文件。
源代码是用C++编写的,设计为在64位模式下工作(VS2010及以上版本)。以下是加载嵌入资源的主要函数Load_TREX的代码示例:
LONG_PTR Load_TREX() {
LONG_PTR nRet = 0;
HRSRC hResource = FindResource(gP.instance, MAKEINTRESOURCE(TREX), RT_RCDATA);
if (hResource) {
long imageSize = SizeofResource(gP.instance, hResource);
if (imageSize) {
LPVOID pResourceData = LockResource(LoadResource(gP.instance, hResource));
if (pResourceData) {
HGLOBAL MemBuffer = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD, imageSize);
if (MemBuffer) {
LPVOID pBuffer = GlobalLock(MemBuffer);
if (pBuffer) {
CopyMemory(pBuffer, pResourceData, imageSize);
LPSTREAM pStream = NULL;
if (CreateStreamOnHGlobal(MemBuffer, FALSE, &pStream) == 0) {
LONG_PTR hImage = 0;
if (GdipCreateBitmapFromStream(pStream, hImage) == 0) {
nRet = hImage;
}
//IUnknown_Release(pStream);
ReleaseObject((PFUNKNOWN*) pStream);
}
}
GlobalUnlock(MemBuffer);
}
GlobalFree(MemBuffer);
}
}
}
return nRet;
}
动画本身是由子线程执行的,而不是使用定时器(尽管也提供了定时器代码)。使用线程的主要优势在于处理多核处理器时,以及在主进程运行时需要使用动画。