Windows抓屏-WGC
Windows.Graphics.Capture抓屏技术调研
1. 原理概述
Windows.Graphics.Capture(WGC)是微软主推的一种桌面/窗口采集技术,从Windows 10版本1803开始提供用于从屏幕或应用程序窗口获取帧的API。它主要利用DirectX11的特性来实现,通过系统选取器UI让用户选择要捕获的屏幕或应用程序窗口,然后将捕获的内容以帧的形式提供给应用程序1368。
原理步骤: * 权限声明:在应用程序清单中声明图形捕获功能,以获得使用屏幕捕获API的权限。 * 用户选择:调用系统选取器UI,让用户选择要捕获的屏幕或应用程序窗口,返回GraphicsCaptureItem对象。 * 创建帧池和会话:使用GraphicsCaptureItem、D3D设备、像素格式、帧数量和帧大小创建Direct3D11CaptureFramePool,并通过该帧池创建GraphicsCaptureSession。 * 开始捕获:调用GraphicsCaptureSession的StartCapture方法,通知系统开始向应用发送捕获帧。 * 获取帧数据:可以通过监听FrameArrived事件或手动调用Direct3D11CaptureFramePool.TryGetNextFrame方法获取捕获的帧数据8。
2. 代码实现
2.1 环境准备 开发环境:Visual Studio 2017及以上版本,支持C++17。 依赖库:Windows SDK,包含C++/WinRT库。 2.2 完整C++代码示例
#include <windows.graphics.capture.h>
#include <d3d11.h>
#include <dxgi1_2.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Graphics.Capture.h>
#include <winrt/Windows.UI.Composition.h>
#include <iostream>
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "dxgi.lib")
// 创建D3D设备
winrt::com_ptr<ID3D11Device> CreateD3DDevice() {
winrt::com_ptr<ID3D11Device> device;
winrt::com_ptr<ID3D11DeviceContext> context;
D3D_DRIVER_TYPE driverTypes[] = {
D3D_DRIVER_TYPE_HARDWARE,
D3D_DRIVER_TYPE_WARP,
D3D_DRIVER_TYPE_REFERENCE
};
UINT numDriverTypes = ARRAYSIZE(driverTypes);
D3D_FEATURE_LEVEL featureLevels[] = {
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_3
};
UINT numFeatureLevels = ARRAYSIZE(featureLevels);
UINT createDeviceFlags = 0;
#if defined(_DEBUG)
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++) {
HRESULT hr = D3D11CreateDevice(
nullptr,
driverTypes[driverTypeIndex],
nullptr,
createDeviceFlags,
featureLevels,
numFeatureLevels,
D3D11_SDK_VERSION,
device.put(),
nullptr,
context.put()
);
if (SUCCEEDED(hr)) {
break;
}
}
return device;
}
// 开始屏幕捕获
void StartCapture() {
if (!winrt::Windows::Graphics::Capture::GraphicsCaptureSession::IsSupported()) {
std::cout << "Screen capture is not supported on this device." << std::endl;
return;
}
auto device = CreateD3DDevice();
winrt::Windows::Graphics::Capture::GraphicsCapturePicker picker;
auto item = picker.PickSingleItemAsync().get();
if (!item) {
std::cout << "No item selected." << std::endl;
return;
}
winrt::Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice d3dDevice =
winrt::Windows::Graphics::DirectX::Direct3D11::CreateDirect3DDeviceFromDXGIDevice(device.as<IDXGIDevice>().get());
winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool framePool =
winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool::Create(
d3dDevice,
winrt::Windows::Graphics::DirectX::DirectXPixelFormat::B8G8R8A8UIntNormalized,
2,
item.Size()
);
winrt::Windows::Graphics::Capture::GraphicsCaptureSession session = framePool.CreateCaptureSession(item);
session.StartCapture();
// 处理捕获的帧
framePool.FrameArrived([&](auto sender, auto args) {
auto frame = sender.TryGetNextFrame();
if (frame) {
// 处理帧数据,例如保存或显示
std::cout << "Frame captured." << std::endl;
}
});
// 保持程序运行
std::cin.get();
}
int main() {
winrt::init_apartment();
StartCapture();
return 0;
}
2.3 代码解释 * CreateD3DDevice函数:创建D3D11设备,用于后续的图形处理。 * StartCapture函数: 检查设备是否支持屏幕捕获。 创建GraphicsCapturePicker并让用户选择要捕获的项目。 创建Direct3D11CaptureFramePool和GraphicsCaptureSession。 开始捕获并处理捕获的帧。 * main函数:初始化WinRT并调用StartCapture函数。
3. 全屏到局部捕获
3.1 全屏捕获 上述代码示例中的捕获方式可以实现全屏捕获,只需用户在系统选取器UI中选择整个屏幕即可。
3.2 局部捕获 要实现局部捕获,可以在创建Direct3D11CaptureFramePool时指定较小的帧大小,或者在获取帧数据后对其进行裁剪。以下是一个简单的裁剪示例:
// 在FrameArrived事件处理函数中添加裁剪逻辑
framePool.FrameArrived([&](auto sender, auto args) {
auto frame = sender.TryGetNextFrame();
if (frame) {
// 假设要裁剪的区域为左上角(100, 100),宽高为200x200
int x = 100;
int y = 100;
int width = 200;
int height = 200;
// 处理帧数据,例如裁剪
// 这里需要根据具体的D3D11纹理处理方法进行裁剪
std::cout << "Frame captured and cropped." << std::endl;
}
});
4. 设置各种优化参数
4.1 帧池参数
-
像素格式:可以选择不同的像素格式,如DXGI_FORMAT_B8G8R8A8_UNORM或DXGI_FORMAT_R16G16B16A16_FLOAT,根据实际需求进行选择。
-
帧数量:在创建Direct3D11CaptureFramePool时指定帧数量,适当增加帧数量可以提高捕获的流畅度,但会占用更多的内存。 4.2 性能优化
-
多线程处理:可以使用多线程来处理捕获的帧数据,避免在UI线程上进行耗时操作。
- 硬件加速:确保使用支持硬件加速的D3D设备,以提高捕获和处理的性能。
5. 流程图和结构图
5.1 流程图
5.2 结构图
+-------------------+ +---------------------+ +-------------------+
| GraphicsCaptureItem| → | Direct3D11CaptureFramePool | → | CaptureSession |
+-------------------+ +---------------------+ +-------------------+
↓ ↓
+-------------------+ +---------------------+ +-------------------+
| D3D11Texture2D | ← | Frame Processing | ← | Dirty Rects Detection|
+-------------------+ +---------------------+ +-------------------+
[创建捕获会话] → [初始化D3D设备] → [选择捕获目标(窗口/屏幕)]
↓ ↓
[获取帧数据(Direct3D纹理)] → [处理数据(复制到CPU/GPU)]
↓
[释放资源] → [循环捕获或结束]
+---------------------+
| 应用程序 |
+---------------------+
| - 权限声明 |
| - 用户选择逻辑 |
| - 帧池和会话管理 |
| - 帧数据处理逻辑 |
+---------------------+
| Windows.Graphics.Capture API |
+---------------------+
| - GraphicsCapturePicker |
| - GraphicsCaptureItem |
| - Direct3D11CaptureFramePool |
| - GraphicsCaptureSession |
+---------------------+
| DirectX11 |
+---------------------+
| - D3D11设备 |
| - 纹理处理 |
+---------------------+
以上就是关于Windows.Graphics.Capture抓屏的技术调研结果,包括原理、代码实现、全屏到局部捕获、优化参数设置以及流程图和结构图。