最近写了个拼图游戏, 是自从学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 效率会不会快一点..