C++使用BitBlt進行視窗抓圖的方法
阿新 • • 發佈:2021-01-08
本文使用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 },clientRect_{ 0,bitbltStartPoint_{ 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_,clientRectWidth,clientRectHeight,scrDc_,bitbltStartPoint_.x,bitbltStartPoint_.y,SRCCOPY); return ret != 0; }
以上就是C++使用BitBlt進行視窗抓圖的方法的詳細內容,更多關於c++ 視窗抓圖的資料請關注我們其它相關文章!