欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

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

程序员文章站 2022-06-28 12:18:31
本文使用c++双缓存进行指定窗口截图。createdibsection创建应用程序可以直接写入的、与设备无关的位图(dib),它提供内存中位图的指针,外部程序可以直接使用。需要注意的是,printwi...

本文使用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++ 窗口截图的资料请关注其它相关文章!