C++使用BitBlt进行窗口抓图的方法

时间:2021-05-20

本文使用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_); //获取窗口DCmemDc_ = ::CreateCompatibleDC(scrDc_); //缓冲内存DCbitmap_ = ::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;}

以上就是C++使用BitBlt进行窗口抓图的方法的详细内容,更多关于c++ 窗口抓图的资料请关注其它相关文章!

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章