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

(0)

相关推荐

  • C++实现屏幕截图

    上回分享了一个全屏截图的代码,保存为BMP,参考:C++实现屏幕截图(全屏截图) 实际使用的过程中我发现截图文件实在大,无奈又整成了PNG截图,现在分享出来. MakePNG.h //MakePNG.h #pragma once #include <GdiPlus.h> using namespace Gdiplus; #pragma comment(lib,"GdiPlus.lib") class CMakePNG { public: CMakePNG(void); ~C

  • C++实现屏幕截图功能

    本文实例为大家分享了C++实现全屏截图功能的具体代码,供大家参考,具体内容如下 最近维护的项目,在某些情况下,光有日志还不行,于是添加了截图功能,特定情况下,会自动截图,辅助分析,从而改进程序.以下是截图实现代码. void CDemoDlg::ScreenShot(void) { CWnd *pDesktop = GetDesktopWindow(); CDC *pdeskdc = pDesktop->GetDC(); CRect re; //获取窗口的大小 pDesktop->GetCli

  • VC++基于Dx实现的截图程序示例代码

    本文所述的程序示例为VC++图象特效的截图示例,需要DirectX 3.0以上版,代码中的GetScreen函数是本截图程序的关键.运行这个程序可用Esc键结束.代码中需要ddutil.h与ddutil.cpp文件,请自行下载添加.关于InitDDraw()函数,功能是初始化DirectDraw环境,创建换页链(主页面,一个后台缓冲区),以及创建一个定时器. 具体的功能代码如下: #include <windows.h> #include <windowsx.h> #include

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

    本文使用C++双缓存进行指定窗口截图.CreateDIBSection创建应用程序可以直接写入的.与设备无关的位图(DIB),它提供内存中位图的指针,外部程序可以直接使用. 需要注意的是,PrintWindow方法能够抓取使用D3D渲染的窗口(例如Excel.Win10自带视频播放器),如果抓取普通窗口则会附带窗口阴影,可见窗口阴影是Windows使用D3D渲染出来的. 1.PrintCaptureHelper.h #pragma once #include <windows.h> #incl

  • Python实现超快窗口截图功能详解

    实现思路是先获取到当前最上面活动的窗口信息,然后提取该窗口的名称信息. 之后获取窗口的坐标信息,即左上角的开始坐标及右下角的结束坐标.最后直接截图并将截图的图片进行展示. 其中用到了两个第三方模块,分别是win32gui和Pillow,安装命令如下: pip install Pillow pip install win32gui 将其中使用到的三个非标准库导入进来. from win32gui import * # 操作windows窗口 from PIL import ImageGrab #

  • 使用微信PC端的截图dll库实现微信截图功能

    本文实例为大家分享了截图dll库实现微信截图功能 ,供大家参考,具体内容如下 ScreenForm.cs代码: using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Windows.Forms; namespace screenT { public partial class ScreenForm : Form { public ScreenForm()

  • Android实现长图文截图功能实例代码

    前言 截图是我们日常开发经常会遇到的一个功能,最近工作遇到的需求又升级了,需要实现长图文的截图功能,经常查找相关资料终于实现了,支持截取微博.知乎.今日头条等第三方APP...... 先瞅瞅效果图: 效果图 再瞅瞅最终的长截图: 我是长截图一,瞅瞅嘛... 我是长截图二,再瞅一下嘛... 上一周脑子突然冒出长截图这个功能,想着如何截取如微博,知乎,头条等这些第三方APP的界面呢?出于好奇心,花了一周业余时间,撸一个看看. 不就是截屏+拼图,还能有什么难度么?这个...好像确实是. Questio

  • Python+Selenium+phantomjs实现网页模拟登录和截图功能(windows环境)

    本文全部操作均在windows环境下 安装 Python Python是一种跨平台的计算机程序设计语言,它可以运行在Windows.Mac和各种Linux/Unix系统上.是一种面向对象的动态类型语言,最初被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新功能的添加,越来越多被用于独立的.大型项目的开发 去Python的官网  www.python.org  下载安装 安装时勾选pip (python包管理工具),同时安装pip python安装好之后,打开命令行工具cmd,输入

  • Python 自动唤醒窗口截图脚本

    目录 1.准备 2.如何获取窗口坐标 3. 还原最小化窗口 4.截图 利用Python自带的win32api和win32con.win32gui等模块,我们能执行许多windows下的自动化操作.比如两个窗口的自动点击操作,从软件中的窗口复制文本到txt中,甚至是截图操作. 截图的操作用途最为广泛,你可以用它配合定时工具,定时检测某个程序的运行情况:甚至可以根据截图做一些辅助性的决策,比如玩类似于<连连看 >的 游戏时,对相同类型的方块进行标记,辅助你玩游戏. 下面就讲讲如何使用 win32a

  • vue项目中canvas实现截图功能

    本文实例为大家分享了vue项目中canvas实现截图功能的具体代码,供大家参考,具体内容如下 实现效果: 整理一下最近在vue项目中做的一个截图功能(只能够截取图片),即用鼠标在画布上进行框选截取. 思路大概如下:做一个弹窗,打开弹窗的时候传入要截的图,接下来在这个窗口里面,点击截图按钮,开始截图,点击取消按钮,取消截图. 窗口里面的html主要是三个部分,一个是可截图区域,一个是截取图片的回显,一个是操作按钮(截图按钮和取消截图按钮). 部分html: <!--截图区域--> <div

  • JavaScript实现网页截图功能

    使用JavaScript截图,这里我要推荐两款开源组件:一个是Canvas2Image,它可以将Canvas绘图编程PNG/JPEG/BMP的图像:但是光有它还不够,我们需要给任意DOM(至少是绝大部分)截图,这就需要html2canvas,它可以将DOM对象转换成一个canvas对象.两者的功能结合起来,就可以把页面上的DOM截图成PNG或者JPEG图像了,很酷. Canvas2Image 它的原理是利用了HTML5的canvas对象提供了toDataURL()的API: 复制代码 代码如下:

  • Java模拟QQ桌面截图功能实现方法

    本文实例讲述了Java模拟QQ桌面截图功能实现方法.分享给大家供大家参考.具体如下: QQ的桌面截图功能非常方便,去年曾用Java模拟过一个,现整理出来. 本方法首先需要抓到屏幕的整个图象,将图象显示在一个JFrame中,再将JFrame全屏显示,这样就模拟出了一个桌面,Java也就可以获得鼠标的作用区域从而实现桌面中的小范围截屏. import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import

  • C#实现的滚动网页截图功能示例

    本文实例讲述了C#实现的滚动网页截图功能.分享给大家供大家参考,具体如下: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace WindowsFormsApplic

随机推荐