当前位置: 移动技术网 > IT编程>开发语言>C/C++ > C++抓图服务

C++抓图服务

2020年04月01日  | 移动技术网IT编程  | 我要评论

可肤冰肌白官网,赤子乘龙全集,不良情侣片尾曲

基于前两篇抓图文章,本文将抓图提取为一个服务,实现不同场景下抓图需求的封装。

c++使用bitblt进行窗口抓图

c++使用printwindow进行窗口抓图

首先是抓图服务:

icapturehelper.h 

#pragma once

#include <windows.h>
#include <string>
using std::string;

class icapturehelper
{
public:
    virtual ~icapturehelper() {}
    virtual bool init(const string& windowname) = 0;
    virtual bool init(hwnd hwnd) = 0;
    virtual void cleanup() = 0;
    virtual bool refreshwindow() = 0;
    virtual bool changewindowhandle(const string& windowname) = 0;
    virtual bool changewindowhandle(hwnd hwnd) = 0;
    virtual bool capture() = 0;

    virtual const rect& getwindowrect() const = 0;
    virtual const rect& getclientrect() const = 0;
    virtual int getbitmapdatasize() const = 0;
    virtual hbitmap getbitmap() const = 0;
    virtual void* getbitmapaddress() const = 0;
};

captureservice.h

#pragma once

#include "icapturehelper.h"
#include <map>
using std::map;

class captureservice
{
public:
    captureservice() = default;
    static captureservice& getinstance();

    enum capturetype
    {
        //使用createdibsection抓图,速度快,但是无法抓取d3d等渲染的窗口
        createdibsection = 0,

        //使用printwindow抓图,速度慢(16ms左右),但是可以抓取d3d等渲染的窗口
        printwindow
    };

    bool registercapture(string name, string windowname, capturetype type = createdibsection); //注册抓图服务
    bool registercapture(string name, hwnd hwnd, capturetype type = createdibsection); //注册抓图服务
    void unregistercapture(string name); //注销抓图服务
    bool isregister(string name); //获取是否已注册抓图服务

    bool refreshwindow(string name); //刷新窗口
    bool changewindowhandle(string name, string windowname); //修改窗口句柄
    bool changewindowhandle(string name, hwnd hwnd); //修改窗口句柄
    bool capture(string name); //抓图

    bool getwindowrect(string name, rect& winrect); //获取窗口尺寸
    bool getclientrect(string name, rect& clientrect); //获取窗口客户区尺寸
    bool getbitmapdatasize(string name, int& bmpdatasize); //获取抓图数据大小
    bool getbitmap(string name, hbitmap& bitmap); //获取窗口位图
    bool getbitmapaddress(string name, void** bitsptr); //获取窗口位图地址

    void cleanup(); //清理所有抓图服务

private:
    ~captureservice();

private:
    map<string, icapturehelper*> capturehelpers_;
};

captureservice.cpp

#include "stdafx.h"
#include "captureservice.h"
#include "dibcapturehelper.h"
#include "printcapturehelper.h"


captureservice::~captureservice()
{
    cleanup();
}

captureservice& captureservice::getinstance()
{
    static captureservice instance;
    return instance;
}

bool captureservice::registercapture(string name, string windowname, capturetype type /* = createdibsection */)
{
    const auto hwnd = ::findwindowa(nullptr, windowname.c_str());
    return registercapture(name, hwnd, type);
}

bool captureservice::registercapture(string name, hwnd hwnd, capturetype type /* = createdibsection */)
{
    if (name.empty() || capturehelpers_.find(name) != capturehelpers_.end())
    {
        return false;
    }

    icapturehelper* helper;
    switch (type)
    {
    case createdibsection:
        helper = new dibcapturehelper();
        break;
    case printwindow:
        helper = new printcapturehelper();
        break;
    default:
        return false;
    }

    if (helper == nullptr)
    {
        return false;
    }

    if (!helper->init(hwnd))
    {
        delete helper;
        return false;
    }

    capturehelpers_[name] = helper;
    return true;
}

void captureservice::unregistercapture(string name)
{
    if (name.empty() || capturehelpers_.find(name) == capturehelpers_.end())
    {
        return;
    }

    auto* capturehelper = capturehelpers_[name];
    if (capturehelper != nullptr)
    {
        capturehelper->cleanup();
        delete capturehelper;
    }

    capturehelpers_.erase(name);
}

bool captureservice::isregister(string name)
{
    return !name.empty() && capturehelpers_.find(name) != capturehelpers_.end();
}

bool captureservice::refreshwindow(string name)
{
    if (!isregister(name))
    {
        return false;
    }
    return capturehelpers_[name]->refreshwindow();
}

bool captureservice::changewindowhandle(string name, string windowname)
{
    if (!isregister(name))
    {
        return false;
    }
    return capturehelpers_[name]->changewindowhandle(windowname);
}

bool captureservice::changewindowhandle(string name, hwnd hwnd)
{
    if (!isregister(name))
    {
        return false;
    }
    return capturehelpers_[name]->changewindowhandle(hwnd);
}

bool captureservice::capture(string name)
{
    if (!isregister(name))
    {
        return false;
    }
    return capturehelpers_[name]->capture();
}

bool captureservice::getwindowrect(string name, rect& winrect)
{
    if (!isregister(name))
    {
        return false;
    }
    winrect = capturehelpers_[name]->getwindowrect();
    return true;
}

bool captureservice::getclientrect(string name, rect& clientrect)
{
    if (!isregister(name))
    {
        return false;
    }
    clientrect = capturehelpers_[name]->getclientrect();
    return true;
}

bool captureservice::getbitmapdatasize(string name, int& bmpdatasize)
{
    if (!isregister(name))
    {
        return false;
    }
    bmpdatasize = capturehelpers_[name]->getbitmapdatasize();
    return true;
}

bool captureservice::getbitmap(string name, hbitmap& bitmap)
{
    if (!isregister(name))
    {
        return false;
    }
    bitmap = capturehelpers_[name]->getbitmap();
    return true;
}

bool captureservice::getbitmapaddress(string name, void** bitsptr)
{
    if (!isregister(name))
    {
        return false;
    }
    *bitsptr = capturehelpers_[name]->getbitmapaddress();
    return true;
}

void captureservice::cleanup()
{
    for (auto iter = capturehelpers_.cbegin(); iter != capturehelpers_.cend(); ++iter)
    {
        auto* capturehelper = iter->second;
        if (capturehelper != nullptr)
        {
            capturehelper->cleanup();
            delete capturehelper;
        }
    }
    capturehelpers_.clear();
}

其次是抓图代码封装:

abscapturehelper.h

#pragma once

#include "icapturehelper.h"

class abscapturehelper : public icapturehelper
{
public:
    abscapturehelper();
    virtual ~abscapturehelper();

    bool init(const string& windowname) override;
    bool init(hwnd hwnd) override;
    void cleanup() override;
    bool refreshwindow() override;
    bool changewindowhandle(const string& windowname) override;
    bool changewindowhandle(hwnd hwnd) override;
    bool capture() override;

    const rect& getwindowrect() const override { return windowrect_; }
    const rect& getclientrect() const override { return clientrect_; }
    int getbitmapdatasize() const override { return bmpdatasize_; }
    hbitmap getbitmap() const override { return bitmap_; }
    void* getbitmapaddress() const override { return bitsptr_; }

protected:
    virtual bool initdc(const bitmapinfo& bitmapinfo) = 0;
    virtual bool docapture() = 0;

protected:
    hwnd hwnd_;
    hdc scrdc_;
    hdc memdc_;
    hbitmap bitmap_;
    hbitmap oldbitmap_;
    void* bitsptr_;

    rect windowrect_;
    rect clientrect_;
    int bmpdatasize_;
};

abscapturehelper.cpp

#include "stdafx.h"
#include "abscapturehelper.h"


abscapturehelper::abscapturehelper()
    : hwnd_(nullptr)
    , scrdc_(nullptr)
    , memdc_(nullptr)
    , bitmap_(nullptr)
    , oldbitmap_(nullptr)
    , bitsptr_(nullptr)
    , windowrect_{ 0, 0, 0, 0 }
    , clientrect_{ 0, 0, 0, 0 }
    , bmpdatasize_(0)
{
}

abscapturehelper::~abscapturehelper()
{
    abscapturehelper::cleanup();
}

bool abscapturehelper::init(const string& windowname)
{
    const auto handle = ::findwindowa(nullptr, windowname.c_str());
    if (handle == nullptr)
    {
        return false;
    }

    return init(handle);
}

bool abscapturehelper::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;

    return initdc(bitmapinfo);
}

void abscapturehelper::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 abscapturehelper::refreshwindow()
{
    const auto hwnd = hwnd_;
    cleanup();
    return init(hwnd);
}

bool abscapturehelper::changewindowhandle(const string& windowname)
{
    cleanup();
    return init(windowname);
}

bool abscapturehelper::changewindowhandle(hwnd hwnd)
{
    cleanup();
    return init(hwnd);
}

bool abscapturehelper::capture()
{
    if (bitmap_ == nullptr || memdc_ == nullptr || scrdc_ == nullptr)
    {
        return false;
    }

    return docapture();
}

dibcapturehelper.h

#pragma once

#include "abscapturehelper.h"

class dibcapturehelper : public abscapturehelper
{
public:
    dibcapturehelper();
    virtual ~dibcapturehelper();

protected:
    bool initdc(const bitmapinfo& bitmapinfo) override;
    bool docapture() override;

private:
    bool savebitmap_;
    int mockpagenumber;
    int bmpcount_;
};

dibcapturehelper.cpp

#include "stdafx.h"
#include "dibcapturehelper.h"
#include <sstream>

static int bmpcount = 0;
static int bmpmaxcount = 50;

dibcapturehelper::dibcapturehelper()
    : savebitmap_(false)
    , mockpagenumber(++bmpcount)
    , bmpcount_(0)
{
}

dibcapturehelper::~dibcapturehelper()
{
}

bool dibcapturehelper::initdc(const bitmapinfo& bitmapinfo)
{
    scrdc_ = ::getwindowdc(hwnd_);
    memdc_ = ::createcompatibledc(scrdc_);

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

bool dibcapturehelper::docapture()
{
    const auto clientrectwidth = clientrect_.right - clientrect_.left;
    const auto clientrectheight = clientrect_.bottom - clientrect_.top;

    const auto ret = ::bitblt(
        memdc_, 0, 0, clientrectwidth, clientrectheight,
        scrdc_, 0, 0, srccopy);

    return ret != 0;
}

printcapturehelper.h

#pragma once

#include "abscapturehelper.h"

class printcapturehelper : public abscapturehelper
{
public:
    printcapturehelper();
    virtual ~printcapturehelper();

protected:
    bool initdc(const bitmapinfo& bitmapinfo) override;
    bool docapture() override;
};

printcapturehelper.cpp

#include "stdafx.h"
#include "printcapturehelper.h"


printcapturehelper::printcapturehelper()
{
}

printcapturehelper::~printcapturehelper()
{
}

bool printcapturehelper::initdc(const bitmapinfo& bitmapinfo)
{
    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;
}

bool printcapturehelper::docapture()
{
    const auto ret = ::printwindow(hwnd_, memdc_, pw_clientonly | pw_renderfullcontent);
    return ret != 0;
}

 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网