截屏小工具.

最近写了个拼图游戏, 是自从学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文件请猛击我

你可能感兴趣的:(工具)