最近写了个拼图游戏, 是自从学D2D以来做的第二款, 在特效上花了些心思, 渐变, 缩放, 最大亮点是可以自动拼图.
我想把这个拼图放到博客上来, 但是我需要一个GIF图动态展示这个游戏的效果, 因此我需要一个截屏的工具.
我率先想到的居然不是屏幕录制, 而是把过程一张张图截下做成GIF.
由于懒得去找现成的工具, 于是自己就写了一个..
简介: |
输入时间间隔, 截图数量.
在倒计时3秒后会按照指定的间隔, 数量 截取前
内容会保存在当前目录的save目录下.
图像是用GDI获取的, 保存是用了GDI+的Bitmap类. 效率确实有点不敢恭维..
运行截图: |
源码: |
#include <iostream>
#include <tchar.h>
#include <windows.h>
#include <Shlwapi.h>
#include <gdiplus.h>
#pragma comment(lib, "shlwapi.lib")
#pragma comment(lib, "gdiplus.lib")
using namespace std;
using namespace Gdiplus;
BOOL StartupGdiPlus(ULONG_PTR *ptoken);
void CleanupGdiPlus(ULONG_PTR token);
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid);
void RunClipScreen(UINT num, UINT interval, HWND hWnd);
#define iooutput _tprintf
#define ioinput std::wcin
int main()
{
std::locale::global(std::locale("chs"));
ULONG_PTR token;
StartupGdiPlus(&token);
UINT num, interval;
while (true)
{
do {
ioinput.clear();
ioinput.sync();
iooutput(L"数量: ");
ioinput >> num;
iooutput(L"间隔: ");
ioinput >> interval;
} while (ioinput.fail() || ioinput.bad());
if ( !num || !interval )
{
break;
}
for (int i = 3; i != 0; --i)
{
iooutput(L"%d\n", i);
Sleep(1000);
}
RunClipScreen(num, interval, GetForegroundWindow());
}
CleanupGdiPlus(token);
return 0;
}
void RunClipScreen(UINT num, UINT interval, HWND hWnd)
{
RECT rc;
GetClientRect(hWnd, &rc);
rc.right -= rc.left;
rc.bottom -= rc.top;
CLSID clsid;
if ( -1 == GetEncoderClsid(L"image/jpeg", &clsid) )
{
return ;
}
if ( !PathFileExists(L"save"))
{
if ( !CreateDirectory(L"save", nullptr) )
{
return ;
}
}
HDC dcDesktop = GetDC(hWnd);
HDC dcMemory = CreateCompatibleDC(dcDesktop);
HBITMAP bmMemory = CreateCompatibleBitmap(dcDesktop, rc.right, rc.bottom);
SelectObject(dcMemory, bmMemory);
DWORD lastTime = GetTickCount();
for (int i = 0; i != num; ++i)
{
StretchBlt(dcMemory, 0, 0, rc.right, rc.bottom, dcDesktop, 0, 0, rc.right, rc.bottom, SRCCOPY);
TCHAR fname[256];
_stprintf_s(fname, 256, L"save\\img%d.jpg", i);
Bitmap bmp(bmMemory, nullptr);
bmp.Save(fname, &clsid);
DWORD time = GetTickCount(), sleep = 0;
if (time - lastTime < interval)
{
sleep = interval - (time - lastTime);
}
Sleep(sleep);
iooutput(L"OK %s\n", fname);
}
DeleteObject(bmMemory);
DeleteDC(dcMemory);
ReleaseDC(hWnd, dcDesktop);
}
BOOL StartupGdiPlus(ULONG_PTR *ptoken)
{
Gdiplus::GdiplusStartupInput input;
return Gdiplus::Ok == Gdiplus::GdiplusStartup(ptoken, &input, nullptr);
}
void CleanupGdiPlus(ULONG_PTR token)
{
Gdiplus::GdiplusShutdown(token);
}
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
UINT num= 0;
UINT size= 0;
ImageCodecInfo* pImageCodecInfo= NULL;
GetImageEncodersSize(&num, &size);
if(size== 0)
{
return -1;
}
pImageCodecInfo= (ImageCodecInfo*)(malloc(size));
if(pImageCodecInfo== NULL)
{
return -1;
}
GetImageEncoders(num, size, pImageCodecInfo);
for(UINT j=0; j< num; ++j)
{
if(wcscmp(pImageCodecInfo[j].MimeType, format)== 0)
{
*pClsid= pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return j;
}
}
free(pImageCodecInfo);
return -1;
}
尾声: |
代码比较简单, 唯一要强调的是 GetEncoderClsid, 这个函数网上一大把, MSDN的例子貌似就是这样的.
不知道用GDI保存为 .bmp 效率会不会快一点..