C++ 使用PrintWindow实现窗口截图功能

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

需要注意的是,PrintWindow方法能够抓取使用D3D渲染的窗口(例如Excel、Win10自带视频播放器),如果抓取普通窗口则会附带窗口阴影,可见窗口阴影是Windows使用D3D渲染出来的。

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;}

以上就是C++ 使用PrintWindow实现窗口截图功能的详细内容,更多关于c++ 窗口截图的资料请关注其它相关文章!

听过许多故事,见过旅行风景,就这样,

C++ 使用PrintWindow实现窗口截图功能

相关文章:

你感兴趣的文章:

标签云: