• C++使用BitBlt进行窗口抓图


    本文使用C++双缓存进行指定窗口截图。CreateDIBSection创建应用程序可以直接写入的、与设备无关的位图(DIB),它提供内存中位图的指针,外部程序可以直接使用。

    需要注意的是,BitBlt方法只能抓图普通窗口的截图,对于使用D3D渲染的窗口(例如Excel、Win10自带视频播放器)则只能获取黑屏。

    1、DibCaptureHelper.h

    #pragma once
    
    #include <windows.h>
    #include <string>
    using std::string;
    
    class DibCaptureHelper
    {
    public:
    	DibCaptureHelper();
    	virtual ~DibCaptureHelper();
    
    	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_;
    	POINT bitbltStartPoint_;
    	int bmpDataSize_;
    };
    

    2、DibCaptureHelper.cpp

    #include "stdafx.h"
    #include "DibCaptureHelper.h"
    
    
    DibCaptureHelper::DibCaptureHelper()
    	: hwnd_(nullptr)
    	, scrDc_(nullptr)
    	, memDc_(nullptr)
    	, bitmap_(nullptr)
    	, oldBitmap_(nullptr)
    	, bitsPtr_(nullptr)
    	, windowRect_{ 0, 0, 0, 0 }
    	, clientRect_{ 0, 0, 0, 0 }
    	, bitbltStartPoint_{ 0,0 }
    	, bmpDataSize_(0)
    {
    }
    
    
    DibCaptureHelper::~DibCaptureHelper()
    {
    	Cleanup();
    }
    
    bool DibCaptureHelper::Init(const string& windowName)
    {
    	const auto handle = ::FindWindowA(nullptr, windowName.c_str());
    	if (handle == nullptr)
    	{
    		return false;
    	}
    
    	return Init(handle);
    }
    
    bool DibCaptureHelper::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;
    
    	bitbltStartPoint_.x = 0;
    	bitbltStartPoint_.y = 0;
    
    	//位图信息
    	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_); //获取窗口DC
    	memDc_ = ::CreateCompatibleDC(scrDc_); //缓冲内存DC
    	bitmap_ = ::CreateDIBSection(memDc_, &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 DibCaptureHelper::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;
    	bitsPtr_ = nullptr;
    }
    
    bool DibCaptureHelper::RefreshWindow()
    {
    	const auto hwnd = hwnd_;
    	Cleanup();
    	return Init(hwnd);
    }
    
    bool DibCaptureHelper::ChangeWindowHandle(const string& windowName)
    {
    	Cleanup();
    	return Init(windowName);
    }
    
    bool DibCaptureHelper::ChangeWindowHandle(HWND hwnd)
    {
    	Cleanup();
    	return Init(hwnd);
    }
    
    bool DibCaptureHelper::Capture() const
    {
    	if (bitmap_ == nullptr || memDc_ == nullptr || scrDc_ == nullptr)
    	{
    		return false;
    	}
    
    	const auto clientRectWidth = clientRect_.right - clientRect_.left;
    	const auto clientRectHeight = clientRect_.bottom - clientRect_.top;
    
    	const auto ret = ::BitBlt(
    		memDc_, 0, 0, clientRectWidth, clientRectHeight,
    		scrDc_, bitbltStartPoint_.x, bitbltStartPoint_.y,
    		SRCCOPY);
    	return ret != 0;
    }
  • 相关阅读:
    区间DP+next求循环节 uva 6876
    连分数(分数类模板) uva6875
    二分+最短路 uvalive 3270 Simplified GSM Network(推荐)
    叉积判断 POJ1696
    树形DP+树状数组 HDU 5877 Weak Pair
    团 大连网赛 1007 Friends and Enemies
    微信支付少一分钱
    数据类型的转换
    什么是机器学习
    config.m4
  • 原文地址:https://www.cnblogs.com/xhubobo/p/12561887.html
Copyright © 2020-2023  润新知