截屏小工具.

作者为了展示其拼图游戏效果,自行开发了一款用于创建GIF动态图的截图工具,该工具可以按照设定的时间间隔和数量自动截图并保存。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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


想要源码和exe文件请猛击我
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值