首页 > 系统相关 >Windows抓屏(1)GDI-bitblt

Windows抓屏(1)GDI-bitblt

时间:2022-11-06 17:11:06浏览次数:45  
标签:const Windows hwnd nullptr return _. 抓屏 DibCaptureHelper GDI

1GDI- bitblt方法

BitBlt 用于从原设备中复制位图到目标设备,弊端,做投屏抓屏时候可能会比较慢,帧率比较低

头文件:(代码来源于网络,目前无法溯源)

#pragma once
#include <windows.h>
#include <string>
#include<wingdi.h>
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;

    void SaveDCtoBmp();


    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这个对象是用来存储成对出现的参数,比如,一个矩形框的左上角坐标、宽度和高度
    RECT clientRect_;
    POINT bitbltStartPoint_;//点坐标
    int bmpDataSize_;//位图缓冲大小
};

实现:

#include "stdafx.h"
#include "Bit.h"

DibCaptureHelper::DibCaptureHelper()
    : hwnd_(nullptr)
    , scrDc_(nullptr)
    , memDc_(nullptr)
    , bitmap_(nullptr)
    , oldBitmap_(nullptr)
    , bitsPtr_(nullptr)
    , windowRect_{ 0, 0, 0, 0 }
    , clientRect_{ 0, 0, 0, 0 }
    , bitbltStartPoint_{ 0,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 * 3;//24bit

    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 = 24;
    bitmapInfo.bmiHeader.biSizeImage = clientRectWidth * clientRectHeight;
    bitmapInfo.bmiHeader.biCompression = BI_RGB;

    scrDc_ = ::GetWindowDC(hwnd_); //获取窗口DC(设备场景)
    memDc_ = ::CreateCompatibleDC(scrDc_); //缓冲内存DC
    //创建应用程序可以直接写入的、与设备无关的位图(DIB)
    bitsPtr_ = nullptr;
    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_, 0, 0, clientRectWidth, clientRectHeight,
        scrDc_, bitbltStartPoint_.x, bitbltStartPoint_.y,
        SRCCOPY);//将源矩形区域直接拷贝到目标矩形区域。

    return ret != 0;
}
void DibCaptureHelper::SaveDCtoBmp()
{
    if (bitsPtr_)
    {
        BITMAPINFOHEADER bmInfoHeader = { 0 };
        bmInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
        bmInfoHeader.biWidth = clientRect_.right - clientRect_.left;
        bmInfoHeader.biHeight = clientRect_.bottom - clientRect_.top;
        bmInfoHeader.biPlanes = 1;
        bmInfoHeader.biBitCount = 24;

        //Bimap file header in order to write bmp file  
        BITMAPFILEHEADER bmFileHeader = { 0 };
        bmFileHeader.bfType = 0x4d42;  //bmp   
        int size1 = sizeof(BITMAPFILEHEADER);
        int size2 = sizeof(BITMAPINFOHEADER);
        bmFileHeader.bfOffBits = size1 + size2;
        bmFileHeader.bfSize = bmFileHeader.bfOffBits + ((bmInfoHeader.biWidth * bmInfoHeader.biHeight) * 3); ///3=(24 / 8) 
        
        
        FILE* fptr = fopen("./desp.bmp", "wb+");
        if (fptr)
        {
            fwrite(&bmFileHeader, sizeof(BITMAPFILEHEADER),1,fptr);
            fwrite(&bmInfoHeader, sizeof(BITMAPINFOHEADER), 1, fptr);
            
            DWORD len = ((bmInfoHeader.biWidth * bmInfoHeader.biHeight) * 3);
            fwrite(bitsPtr_, len, 1, fptr);
            fclose(fptr);
        }
        
    
    }


}

调用:

#include "stdafx.h"
#include"BIt.h"
#include <windows.h>


int main()
{
    HWND winHandle =  GetDesktopWindow();
    
    auto obj = new DibCaptureHelper();
    obj->Init(winHandle);
    obj->Capture();
    obj->SaveDCtoBmp();


    return 0;
}

屏幕截图结果:

 

标签:const,Windows,hwnd,nullptr,return,_.,抓屏,DibCaptureHelper,GDI
From: https://www.cnblogs.com/8335IT/p/16863057.html

相关文章

  • windows11安装机器学习Anaconda环境
    Anaconda是一个开源的Python发行版本,是一个安装、管理python相关包的软件,还自带python、JupyterNotebook、Spyder,有管理包的conda工具,非常有用。安装步骤:1.Anaconda下......
  • macOS 远程桌面windows方法
    1.利用微软官方的软件:https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/clients/remote-desktop-mac 2. ......
  • Windows版的Redis安装
    到官网下载:​​​https://github.com/MicrosoftArchive/redis/releases​​​如果没有到如下网盘下载:​更改配置文件​Windows版的Redis有2个配置文件,一个是:redis.windows.c......
  • windows tomcat 404问题
    解决404问题:​双击tomcat​2.将webpaas前的wtp去掉​输入localhost8080:如下即可:​如果程序能运行,打压成war包使用:启动tomcat运行即可。​......
  • Windows 下用 MinGW-64 配置 VScode 的 C/C++ 环境
    蒟蒻第一次发博客,轻喷~我在安装VScode的时候可谓历经磨难,所以就萌生出写这篇文章的想法。Windows下用MinGW-64配置VScode的C/C++环境一、下载MinGW-w64并添......
  • Windows下安装及卸载程序可用的添加和删除当前路径到环境变量的bat脚本以及如何和inno
    文章目录​​1.安装bat脚本-install.bat(将当前路径添加到环境变量中)​​​​2.卸载bat脚本-uninstall.bat(搜索当前路径并删除)​​​​3.innosetup添加安装和卸载时执行......
  • Windows 11 家庭版安装WSA
    低于8G内存就不要尝试了网上大佬整理出的批处理脚本,以管理员身份运行,需要重启:pushd"%~dp0"dir/b%SystemRoot%\servicing\Packages\*Hyper-V*.mum>hyper-v.txtfor/f......
  • 学习笔记-Windows 基础服务搭建
    Windows基础服务搭建磁盘管理例1新建两个10G的硬盘,名称为A-10-1、A-10-2,挂载到主机;新建镜像卷,使用所有空间,驱动器号为D.1.开始——管理工具——计算机......
  • [转]【终极解决方案】为应用程序池“XXX”提供服务的进程在与 Windows Process Activa
    困扰我大半年的错误,今天偶然间被解决了,特此分享给被同样问题纠结的朋友们!之前的求助帖,无人应答:http://www.cnblogs.com/freeton/archive/2012/08/28/2660585.htmlhttp:/......
  • Windows远程Ubuntu
    1.开启SSH服务#查看是否安装opensshdpkg-l|grep-iopenssh-server#如果没有安装sudoaptinstallopenssh-server#确认systemctlstatussshdsudoaptinstall......