windows抓屏排除指定窗口

方式一:

BOOL SetWindowDisplayAffinity(
  HWND  hWnd,
  DWORD dwAffinity
);

hWnd:窗口句柄

dwAffinity:

#define WDA_NONE        0x00000000
#define WDA_MONITOR     0x00000001
#define WDA_EXCLUDEFROMCAPTURE 0x00000011

在beta版本下,才有WDA_EXCLUDEFROMCAPTURE

包含在:C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\um\WinUser.h

然鹅,经过测试,并没有用,被排除的窗口,只是显示成了黑框。失败!

 

方式二(从webrtc M81抠的):

Windows放大镜Magnification API

MagSetWindowFilterList
Sets the list of windows to be magnified or the list of windows to be excluded from magnification.

BOOL MagSetWindowFilterList(
  HWND  hwnd,
  DWORD dwFilterMode,
  int   count,
  HWND  *pHWND
);

接口MagSetWindowFilterList具有排除指定窗口的功能。

 

测试可行,只是稍显复杂:

//excludewindow.h
#pragma once

#include 
#include 
#include 

// kMagnifierWindowClass has to be "Magnifier" according to the Magnification
// API. The other strings can be anything.
static wchar_t kMagnifierHostClass[] = L"ScreenCapturerWinMagnifierHost";
static wchar_t kHostWindowName[] = L"MagnifierHost";
static wchar_t kMagnifierWindowClass[] = L"Magnifier";
static wchar_t kMagnifierWindowName[] = L"MagnifierWindow";

class CExcludeWindow
{
public:
	CExcludeWindow();
	virtual ~CExcludeWindow();

	int SetExcludeWnd(HWND hWnd);

    bool Init();
    bool CaptureFrame();
private:

    typedef BOOL(WINAPI* MagImageScalingCallback)(HWND hwnd,
        void* srcdata,
        MAGIMAGEHEADER srcheader,
        void* destdata,
        MAGIMAGEHEADER destheader,
        RECT unclipped,
        RECT clipped,
        HRGN dirty);
    typedef BOOL(WINAPI* MagInitializeFunc)(void);
    typedef BOOL(WINAPI* MagUninitializeFunc)(void);
    typedef BOOL(WINAPI* MagSetWindowSourceFunc)(HWND hwnd, RECT rect);
    typedef BOOL(WINAPI* MagSetWindowFilterListFunc)(HWND hwnd,
        DWORD dwFilterMode,
        int count,
        HWND* pHWND);
    typedef BOOL(WINAPI* MagSetImageScalingCallbackFunc)(
        HWND hwnd,
        MagImageScalingCallback callback);

    static BOOL WINAPI OnMagImageScalingCallback(HWND hwnd,
        void* srcdata,
        MAGIMAGEHEADER srcheader,
        void* destdata,
        MAGIMAGEHEADER destheader,
        RECT unclipped,
        RECT clipped,
        HRGN dirty);

    void OnCaptured(void* data, const MAGIMAGEHEADER& header);


	HMODULE mag_lib_handle_ = NULL;
	MagInitializeFunc mag_initialize_func_ = nullptr;
	MagUninitializeFunc mag_uninitialize_func_ = nullptr;
	MagSetWindowSourceFunc set_window_source_func_ = nullptr;
	MagSetWindowFilterListFunc set_window_filter_list_func_ = nullptr;
	MagSetImageScalingCallbackFunc set_image_scaling_callback_func_ = nullptr;

    // The hidden window hosting the magnifier control.
    HWND host_window_ = NULL;
    // The magnifier control that captures the screen.
    HWND magnifier_window_ = NULL;

    // True if the magnifier control has been successfully initialized.
    bool magnifier_initialized_ = false;

    // True if the last OnMagImageScalingCallback was called and handled
    // successfully. Reset at the beginning of each CaptureImage call.
    bool magnifier_capture_succeeded_ = true;
};

 

//excludewindow.cpp
#include "excludewindow.h"
#include 


DWORD GetTlsIndex() {
    static const DWORD tls_index = TlsAlloc();
    return tls_index;
}

CExcludeWindow::CExcludeWindow()
{
}

bool CExcludeWindow::Init()
{
    mag_lib_handle_ = LoadLibraryW(L"Magnification.dll");
    if (!mag_lib_handle_)
        return false;

    // Initialize Magnification API function pointers.
    mag_initialize_func_ = reinterpret_cast(
        GetProcAddress(mag_lib_handle_, "MagInitialize"));
    mag_uninitialize_func_ = reinterpret_cast(
        GetProcAddress(mag_lib_handle_, "MagUninitialize"));
    set_window_source_func_ = reinterpret_cast(
        GetProcAddress(mag_lib_handle_, "MagSetWindowSource"));
    set_window_filter_list_func_ = reinterpret_cast(
        GetProcAddress(mag_lib_handle_, "MagSetWindowFilterList"));
    set_image_scaling_callback_func_ =
        reinterpret_cast(
            GetProcAddress(mag_lib_handle_, "MagSetImageScalingCallback"));

    if (!mag_initialize_func_ || !mag_uninitialize_func_ ||
        !set_window_source_func_ || !set_window_filter_list_func_ ||
        !set_image_scaling_callback_func_) {
        std::cout << "Failed to initialize ScreenCapturerWinMagnifier: "
            << "library functions missing.";
        return false;
    }

    BOOL result = mag_initialize_func_();
    if (!result) {
        std::cout << "Failed to initialize ScreenCapturerWinMagnifier: "
            << "error from MagInitialize " << GetLastError();
        return false;
    }

    HMODULE hInstance = nullptr;
    result =
        GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
            GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
            reinterpret_cast(&DefWindowProc), &hInstance);
    if (!result) {
        mag_uninitialize_func_();
        std::cout << "Failed to initialize ScreenCapturerWinMagnifier: "
            << "error from GetModulehandleExA " << GetLastError();
        return false;
    }


    // Register the host window class. See the MSDN documentation of the
    // Magnification API for more infomation.
    WNDCLASSEXW wcex = {};
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.lpfnWndProc = &DefWindowProc;
    wcex.hInstance = hInstance;
    wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
    wcex.lpszClassName = kMagnifierHostClass;

    // Ignore the error which may happen when the class is already registered.
    RegisterClassExW(&wcex);

    // Create the host window.
    host_window_ =
        CreateWindowExW(WS_EX_LAYERED, kMagnifierHostClass, kHostWindowName, 0, 0,
            0, 0, 0, nullptr, nullptr, hInstance, nullptr);
    if (!host_window_) {
        mag_uninitialize_func_();
        std::cout << "Failed to initialize ScreenCapturerWinMagnifier: "
            << "error from creating host window "
            << GetLastError();
        return false;
    }

    // Create the magnifier control.
    magnifier_window_ = CreateWindowW(kMagnifierWindowClass, kMagnifierWindowName,
        WS_CHILD | WS_VISIBLE, 0, 0, 0, 0,
        host_window_, nullptr, hInstance, nullptr);
    if (!magnifier_window_) {
        mag_uninitialize_func_();
        std::cout << "Failed to initialize ScreenCapturerWinMagnifier: "
            << "error from creating magnifier window "
            << GetLastError();
        return false;
    }

    // Hide the host window.
    ShowWindow(host_window_, SW_HIDE);

    // Set the scaling callback to receive captured image.
    result = set_image_scaling_callback_func_(
        magnifier_window_,
        &CExcludeWindow::OnMagImageScalingCallback);
    if (!result) {
        mag_uninitialize_func_();
        std::cout << "Failed to initialize ScreenCapturerWinMagnifier: "
            << "error from MagSetImageScalingCallback "
            << GetLastError();
        return false;
    }
    return true;
}

CExcludeWindow::~CExcludeWindow()
{

}


BOOL CExcludeWindow::OnMagImageScalingCallback(
    HWND hwnd,
    void* srcdata,
    MAGIMAGEHEADER srcheader,
    void* destdata,
    MAGIMAGEHEADER destheader,
    RECT unclipped,
    RECT clipped,
    HRGN dirty) {
    CExcludeWindow* owner =
        reinterpret_cast(TlsGetValue(GetTlsIndex()));
    TlsSetValue(GetTlsIndex(), nullptr);
    owner->OnCaptured(srcdata, srcheader);

    return TRUE;
}

void CExcludeWindow::OnCaptured(void* data, const MAGIMAGEHEADER& header) {

    // Verify the format.
    // TODO(jiayl): support capturing sources with pixel formats other than RGBA.
    int captured_bytes_per_pixel = header.cbSize / header.width / header.height;
    if (header.format != GUID_WICPixelFormat32bppRGBA ) {
        std::cout
            << "Output format does not match the captured format: "
            << "width = " << header.width << ", "
            << "height = " << header.height << ", "
            << "stride = " << header.stride << ", "
            << "bpp = " << captured_bytes_per_pixel << ", "
            << "pixel format RGBA ? "
            << (header.format == GUID_WICPixelFormat32bppRGBA) << ".";
        return;
    }

    static FILE* fp = fopen(".\\rgba.rgba","wb");
    if (fp)
    {
        //fwrite(data, header.width * header.height * 4, 1, fp);
        fwrite(data, header.cbSize, 1, fp);
        fflush(fp);
        fclose(fp);
        fp = NULL;
    }

    // Copy the data into the frame.
  /*  current_frame->CopyPixelsFrom(
        reinterpret_cast(data), header.stride,
        DesktopRect::MakeXYWH(0, 0, header.width, header.height));*/

    magnifier_capture_succeeded_ = true;
}

int CExcludeWindow::SetExcludeWnd(HWND hWnd)
{
    if (hWnd) {
        BOOL result = set_window_filter_list_func_(
            magnifier_window_, MW_FILTERMODE_EXCLUDE, 1, &hWnd);
        if (!result) {
            mag_uninitialize_func_();
            std::cout
                << "Failed to initialize ScreenCapturerWinMagnifier: "
                << "error from MagSetWindowFilterList " << GetLastError();
            return -1;
        }
    }
	return 0;
}

bool CExcludeWindow::CaptureFrame()
{
    int nX = GetSystemMetrics(SM_XVIRTUALSCREEN);
    int nY = GetSystemMetrics(SM_YVIRTUALSCREEN);
    int nScreenW = GetSystemMetrics(SM_CXVIRTUALSCREEN);
    int nScreenH = GetSystemMetrics(SM_CYVIRTUALSCREEN);
    BOOL result = SetWindowPos(magnifier_window_, NULL, nX, nY,
        nScreenW, nScreenH, 0);
    if (!result) {
        std::cout << "Failed to call SetWindowPos: " << GetLastError()
            << ". Rect = {" << nX
            << ", " << nY << ", " << nX + nScreenW << ", "
            << nY + nScreenH << "}";
        return false;
    }

    magnifier_capture_succeeded_ = false;

    RECT native_rect = { nX, nY, nX+nScreenW, nY+ nScreenH };

    TlsSetValue(GetTlsIndex(), this);
    // OnCaptured will be called via OnMagImageScalingCallback and fill in the
    // frame before set_window_source_func_ returns.
    result = set_window_source_func_(magnifier_window_, native_rect);

    if (!result) {
        std::cout << "Failed to call MagSetWindowSource: "
            << GetLastError() << ". Rect = {" << nX
            << ", " << nY << ", " << nX + nScreenW << ", "
            << nY + nScreenH << "}";
        return false;
    }

    return magnifier_capture_succeeded_;
}

测试:

CExcludeWindow ex;
ex.Init();
ex.SetExcludeWnd(hWnd);
ex.CaptureFrame();

//回调函数会写下一个rgba的文件

 

你可能感兴趣的:(webrtc)