当前位置: 移动技术网 > 科技>操作系统>windows > C++ 使用PrintWindow实现窗口截图功能

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

2020年08月05日  | 移动技术网科技  | 我要评论
本文使用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++ 窗口截图的资料请关注移动技术网其它相关文章!

如您对本文有疑问或者有任何想说的,请 点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网