C ++ uses windowing capture PrintWindow

As used herein, C ++ double buffer specified window screenshots. CreateDIBSection create applications may write, device-independent bitmap (the DIB), which provides a pointer in bitmap memory, an external program can be used directly.

Note that, PrintWindow method can crawl using D3D rendering window (such as Excel, Win10 comes with video player), if an ordinary window will grab comes with drop shadows, shadows are visible windows using Windows D3D rendering out.

This article Environment: Win10 + VS2015.

1、PrintCaptureHelper.h

#pragma once

#include <windows.h>
#include <string>
using std::string;

class PrintCaptureHelper
{
public:
	PrintCaptureHelper();
	virtual ~PrintCaptureHelper();

	bool Init(const string& windowName);
	bool Init(HWND hwnd);
	void Cleanup();
	bool RefreshWindow();
	bool ChangeWindowHandle(const string& windowName);
	bool ChangeWindowHandle(HWND hwnd);
	bool Capture() const;

	const RECT& GetWindowRect() const { return windowRect_; }
	const RECT& GetClientRect() const { return clientRect_; }
	int GetBitmapDataSize() const { return bmpDataSize_; }
	HBITMAP GetBitmap() const { return bitmap_; }
	void* GetBitmapAddress() const { return bitsPtr_; }

private:
	HWND hwnd_;
	HDC scrDc_;
	HDC memDc_;
	HBITMAP bitmap_;
	HBITMAP oldBitmap_;
	void* bitsPtr_;

	RECT windowRect_;
	RECT clientRect_;
	int bmpDataSize_;
};

2, PrintCaptureHelper.cpp

#include "stdafx.h"
#include "PrintCaptureHelper.h"


PrintCaptureHelper::PrintCaptureHelper()
	: hwnd_(nullptr)
	, scrDc_(nullptr)
	, memDc_(nullptr)
	, bitmap_(nullptr)
	, oldBitmap_(nullptr)
	, bitsPtr_(nullptr)
	, windowRect_{ 0, 0, 0, 0 }
	, clientRect_{ 0, 0, 0, 0 }
	, bmpDataSize_(0)
{

}

PrintCaptureHelper::~PrintCaptureHelper()
{
	Cleanup();
}

bool PrintCaptureHelper::Init(const string& windowName)
{
	const auto handle = ::FindWindowA(nullptr, windowName.c_str());
	if (handle == nullptr)
	{
		return false;
	}

	return Init(handle);
}

bool PrintCaptureHelper::Init(HWND hwnd)
{
	hwnd_ = hwnd;

	//获取窗口大小
	if (!::GetWindowRect(hwnd_, &windowRect_) || !::GetClientRect(hwnd_, &clientRect_))
	{
		return false;
	}

	const auto clientRectWidth = clientRect_.right - clientRect_.left;
	const auto clientRectHeight = clientRect_.bottom - clientRect_.top;
	bmpDataSize_ = clientRectWidth * clientRectHeight * 4;

	//位图信息
	BITMAPINFO bitmapInfo;
	bitmapInfo.bmiHeader.biSize = sizeof(bitmapInfo);
	bitmapInfo.bmiHeader.biWidth = clientRectWidth;
	bitmapInfo.bmiHeader.biHeight = clientRectHeight;
	bitmapInfo.bmiHeader.biPlanes = 1;
	bitmapInfo.bmiHeader.biBitCount = 32;
	bitmapInfo.bmiHeader.biSizeImage = clientRectWidth * clientRectHeight;
	bitmapInfo.bmiHeader.biCompression = BI_RGB;

	scrDc_ = ::GetWindowDC(hwnd_);
	memDc_ = ::CreateCompatibleDC(scrDc_);
	bitmap_ = ::CreateDIBSection(scrDc_, &bitmapInfo, DIB_RGB_COLORS, &bitsPtr_, nullptr, 0);
	if (bitmap_ == nullptr)
	{
		::DeleteDC(memDc_);
		::ReleaseDC(hwnd_, scrDc_);
		return false;
	}

	oldBitmap_ = static_cast<HBITMAP>(::SelectObject(memDc_, bitmap_));
	return true;
}

void PrintCaptureHelper::Cleanup()
{
	if (bitmap_ == nullptr)
	{
		return;
	}

	//删除用过的对象
	::SelectObject(memDc_, oldBitmap_);
	::DeleteObject(bitmap_);
	::DeleteDC(memDc_);
	::ReleaseDC(hwnd_, scrDc_);

	hwnd_ = nullptr;
	scrDc_ = nullptr;
	memDc_ = nullptr;
	bitmap_ = nullptr;
	oldBitmap_ = nullptr;
}

bool PrintCaptureHelper::RefreshWindow()
{
	const auto hwnd = hwnd_;
	Cleanup();
	return Init(hwnd);
}

bool PrintCaptureHelper::ChangeWindowHandle(const string& windowName)
{
	Cleanup();
	return Init(windowName);
}

bool PrintCaptureHelper::ChangeWindowHandle(HWND hwnd)
{
	Cleanup();
	return Init(hwnd);
}

bool PrintCaptureHelper::Capture() const
{
	if (bitmap_ == nullptr || memDc_ == nullptr || scrDc_ == nullptr)
	{
		return false;
	}

	const auto ret = ::PrintWindow(hwnd_, memDc_, PW_CLIENTONLY | PW_RENDERFULLCONTENT);
	return ret != 0;
}

Guess you like

Origin www.cnblogs.com/xhubobo/p/12565475.html