winrt新dx截图最小实现
转自:https://stackoverflow.co/questions/11283015
效果还是很不错的
#include <iostream>
#include <Windows.h>
#include <dxgi.h>
#include <inspectable.h>
#include <dxgi1_2.h>
#include <d3d11.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.System.h>
#include <winrt/Windows.Graphics.Capture.h>
#include <windows.graphics.capture.interop.h>
#include <windows.graphics.directx.direct3d11.interop.h>
#include <roerrorapi.h>
#include <shlobj_core.h>
#include <dwmapi.h>
#pragma comment(lib,"Dwmapi.lib")
#pragma comment(lib,"windowsapp.lib")
void CaptureWindow(HWND hwndTarget)
{
// Init COM
winrt::init_apartment(winrt::apartment_type::multi_threaded);
// Create Direct 3D Device
winrt::com_ptr<ID3D11Device> d3dDevice;
winrt::check_hresult(D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, D3D11_CREATE_DEVICE_BGRA_SUPPORT,
nullptr, 0,D3D11_SDK_VERSION, d3dDevice.put(), nullptr, nullptr));
winrt::Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice device;
const auto dxgiDevice = d3dDevice.as<IDXGIDevice>();
{
winrt::com_ptr<::IInspectable> inspectable;
winrt::check_hresult(CreateDirect3D11DeviceFromDXGIDevice(dxgiDevice.get(), inspectable.put()));
device = inspectable.as<winrt::Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice>();
}
auto idxgiDevice2 = dxgiDevice.as<IDXGIDevice2>();
winrt::com_ptr<IDXGIAdapter> adapter;
winrt::check_hresult(idxgiDevice2->GetParent(winrt::guid_of<IDXGIAdapter>(), adapter.put_void()));
winrt::com_ptr<IDXGIFactory2> factory;
winrt::check_hresult(adapter->GetParent(winrt::guid_of<IDXGIFactory2>(), factory.put_void()));
ID3D11DeviceContext* d3dContext = nullptr;
d3dDevice->GetImmediateContext(&d3dContext);
RECT rect{};
DwmGetWindowAttribute(hwndTarget, DWMWA_EXTENDED_FRAME_BOUNDS, &rect, sizeof(RECT));
const auto size = winrt::Windows::Graphics::SizeInt32{rect.right - rect.left, rect.bottom - rect.top};
winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool m_framePool =
winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool::Create(
device,
winrt::Windows::Graphics::DirectX::DirectXPixelFormat::B8G8R8A8UIntNormalized,
2,
size);
const auto activationFactory = winrt::get_activation_factory<
winrt::Windows::Graphics::Capture::GraphicsCaptureItem>();
auto interopFactory = activationFactory.as<IGraphicsCaptureItemInterop>();
winrt::Windows::Graphics::Capture::GraphicsCaptureItem captureItem = {nullptr};
interopFactory->CreateForWindow(hwndTarget, winrt::guid_of<ABI::Windows::Graphics::Capture::IGraphicsCaptureItem>(),
reinterpret_cast<void**>(winrt::put_abi(captureItem)));
auto isFrameArrived = false;
winrt::com_ptr<ID3D11Texture2D> texture;
const auto session = m_framePool.CreateCaptureSession(captureItem);
m_framePool.FrameArrived([&](auto& framePool, auto&)
{
if (isFrameArrived) return;
auto frame = framePool.TryGetNextFrame();
struct __declspec(uuid("A9B3D012-3DF2-4EE3-B8D1-8695F457D3C1"))
IDirect3DDxgiInterfaceAccess : ::IUnknown
{
virtual HRESULT __stdcall GetInterface(GUID const& id, void** object) = 0;
};
auto access = frame.Surface().as<IDirect3DDxgiInterfaceAccess>();
access->GetInterface(winrt::guid_of<ID3D11Texture2D>(), texture.put_void());
isFrameArrived = true;
return;
});
session.IsCursorCaptureEnabled(false);
session.StartCapture();
// Message pump
MSG msg;
clock_t timer = clock();
while (!isFrameArrived)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) > 0)
DispatchMessage(&msg);
if (clock() - timer > 20000)
{
// TODO: try to make here a better error handling
return;
}
}
session.Close();
D3D11_TEXTURE2D_DESC capturedTextureDesc;
texture->GetDesc(&capturedTextureDesc);
capturedTextureDesc.Usage = D3D11_USAGE_STAGING;
capturedTextureDesc.BindFlags = 0;
capturedTextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
capturedTextureDesc.MiscFlags = 0;
winrt::com_ptr<ID3D11Texture2D> userTexture = nullptr;
winrt::check_hresult(d3dDevice->CreateTexture2D(&capturedTextureDesc, NULL, userTexture.put()));
d3dContext->CopyResource(userTexture.get(), texture.get());
D3D11_MAPPED_SUBRESOURCE resource;
winrt::check_hresult(d3dContext->Map(userTexture.get(), NULL, D3D11_MAP_READ, 0, &resource));
BITMAPINFO lBmpInfo;
// BMP 32 bpp
ZeroMemory(&lBmpInfo, sizeof(BITMAPINFO));
lBmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
lBmpInfo.bmiHeader.biBitCount = 32;
lBmpInfo.bmiHeader.biCompression = BI_RGB;
lBmpInfo.bmiHeader.biWidth = capturedTextureDesc.Width;
lBmpInfo.bmiHeader.biHeight = capturedTextureDesc.Height;
lBmpInfo.bmiHeader.biPlanes = 1;
lBmpInfo.bmiHeader.biSizeImage = capturedTextureDesc.Width * capturedTextureDesc.Height * 4;
std::unique_ptr<BYTE> pBuf(new BYTE[lBmpInfo.bmiHeader.biSizeImage]);
UINT lBmpRowPitch = capturedTextureDesc.Width * 4;
auto sptr = static_cast<BYTE*>(resource.pData);
auto dptr = pBuf.get() + lBmpInfo.bmiHeader.biSizeImage - lBmpRowPitch;
UINT lRowPitch = std::min<UINT>(lBmpRowPitch, resource.RowPitch);
for (size_t h = 0; h < capturedTextureDesc.Height; ++h)
{
memcpy_s(dptr, lBmpRowPitch, sptr, lRowPitch);
sptr += resource.RowPitch;
dptr -= lBmpRowPitch;
}
// Save bitmap buffer into the file ScreenShot.bmp
WCHAR lMyDocPath[MAX_PATH];
winrt::check_hresult(SHGetFolderPath(nullptr, CSIDL_PERSONAL, nullptr, SHGFP_TYPE_CURRENT, lMyDocPath));
std::wstring lFilePath = L"ScreenShot.bmp";
FILE* lfile = nullptr;
if (auto lerr = _wfopen_s(&lfile, lFilePath.c_str(), L"wb"); lerr != 0)
return;
if (lfile != nullptr)
{
BITMAPFILEHEADER bmpFileHeader;
bmpFileHeader.bfReserved1 = 0;
bmpFileHeader.bfReserved2 = 0;
bmpFileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + lBmpInfo.bmiHeader.biSizeImage;
bmpFileHeader.bfType = 'MB';
bmpFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
fwrite(&bmpFileHeader, sizeof(BITMAPFILEHEADER), 1, lfile);
fwrite(&lBmpInfo.bmiHeader, sizeof(BITMAPINFOHEADER), 1, lfile);
fwrite(pBuf.get(), lBmpInfo.bmiHeader.biSizeImage, 1, lfile);
fclose(lfile);
}
return;
}
winrt新dx截图最小实现的更多相关文章
- Linux系统中最好用的截图软件介绍
当我的主力操作系统从 Windows 转换到 Ubuntu 的时候,首要考虑的就是屏幕截图工具的可用性.尽管使用默认的键盘快捷键也可以获取屏幕截图,但如果使用屏幕截图工具,可以更方便地对屏幕截图进行编 ...
- kettle转换设置变量,校验输出新变量
背景:有很多小的转换需要串联起来,如果前一个执行成功,后面继续接着执行,如果执行等待中,就让程序等一会再次获取数据分析,如果失败就中止,成功就进行下一个转换,以此类推.... 需求:通过job把参数传 ...
- Windows GDI 窗口与 Direct3D 屏幕截图
前言 Windows 上,屏幕截图一般是调用 win32 api 完成的,如果 C# 想实现截图功能,就需要封装相关 api.在 Windows 上,主要图形接口有 GDI 和 DirectX.GDI ...
- MVVM架构~knockoutjs系列之验证信息自定义输出~再续
返回目录 对于一个项目的表单验证,方式有很多,效果也有很多,具体使用哪种完成取决于产品这边,产品让你用什么,你就要用什么,而做为开发人员,我们要做的就是"整理近可能多的架构方式",这样才可以自由的应变 ...
- Pyqt 屏幕截图工具
从Pyqt的examples中看到一段截图代码, (路径:examplas\desktop\screenshot.py) 所以想自己UI下界面,手动练习下 通过UI生成的: Screenshot.py ...
- Node.js系列-express(下)
前言 距上次更新博客又两个月多了,这两个月内除了上班时间忙公司的项目外,下班后也没有闲着,做了点外包,有小程序的,管理端的项目.也可能那段时间做的外包项目也都比较急,所以晚上都搞到一点左右睡,严重的压 ...
- 用delphi实现完美屏幕截图
可以截取layered窗口(包括透明窗口)的代码: procedure CaptureScreen(AFileName: string);const CAPTUREBLT = $40000000;v ...
- 如何使用T-SQL备份还原数据库及c#如何调用执行?
准备材料:Microsoft SQL Server一部.需要还原的bak文件一只 一.备份 数据库备份语句:user master backup database 数据库名 to disk='保存路径 ...
- 独立开发人员低成本推广APP的18条技巧
导语:知道并不等于运行,有些最主要的推广方法往往会被忽略.这些,是自国外开发人员总结出的这18条经验. 如今市面上充满了大牌子大公司和大制作的手机游戏,常常有游戏花300万成本开发,然后再花2000万 ...
- 如何使用T-SQL备份还原数据库及c#如何调用执行? C#中索引器的作用和实现。 jquery控制元素的隐藏和显示的几种方法。 localStorage、sessionStorage用法总结 在AspNetCore中扩展Log系列 - 介绍开源类库的使用(一) span<T>之高性能字符串操作实测
如何使用T-SQL备份还原数据库及c#如何调用执行? 准备材料:Microsoft SQL Server一部.需要还原的bak文件一只 一.备份 数据库备份语句:user master backup ...
随机推荐
- 启动Study.BlazorOne项目
由于Study.Trade模块的Blazor是基于国内著名的BootstrapBlazor组件,因此Study.BlazorOne项目也必须添加对BootstrapBlazor的支持. # 1.去Bo ...
- Vue.beforeEach is not a function报错
使用导航守卫改变页面的title时报错了,明明在beaforeEach的参数中写了箭头函数也报下面的错误 后面发现我的问题在于直接导出了export.default new Router({--})中 ...
- Spring Cloud Zuul 获取当前请求的路由信息和路由后端的服务节点信息
基本思路 参考spring-cloud-zuul-ratelimit开源项目,在过滤器中根据当前的请求路径,判断当前的路由信息,当取得路由信息后,可以对服务的调用次数做统计等操作. 具体实现 创建一个 ...
- 【Azure Compute Gallery】使用 Python 代码从 Azure Compute Gallery 复制 Image-Version
问题描述 Azure Compute Gallery 可以帮助围绕 Azure 资源(例如映像和应用程序)生成结构和组织,并且支持全局复制. 如果想通过Python代码实现 Image-Version ...
- 【Azure Key Vault】是否有直接方法将Azure Key Vault中的机密名称/机密值到处成文件呢?
问题描述 是否有直接方法将Azure Key Vault中的机密名称/机密值导出,保存为一个文件呢? 问题解答 Azure Key Vault 没有直接提供Secret 导出文件(如xlsx格式)的方 ...
- 图查询语言 nGQL 简明教程 vol.01 快速入门
本文旨在让新手快速了解 nGQL,掌握方向,之后可以脚踩在地上借助文档写出任何心中的 NebulaGraph 图查询. 视频 本教程的视频版在B站这里. 准备工作 在正式开始 nGQL 实操之前,记得 ...
- Codeforces Round 924 (Div. 2)B. Equalize(思维+双指针)
目录 题面 链接 题意 题解 代码 题面 链接 B. Equalize 题意 给一个数组\(a\),然后让你给这个数组加上一个排列,求出现最多的次数 题解 赛时没过不应该. 最开始很容易想到要去重,因 ...
- Docker下搭建Redis集群并实现动态扩/缩容
一.Redis集群方案的简单介绍 Redis集群的方案一般分为三种: 哈希取余分区 一致性哈希算法分区 哈希槽分区(本文介绍的就是这种) 1.哈希取余分区: 优点: 简单粗暴,只要提前预估好数据量,然 ...
- HDFS分布式文件系统知识点梳理(一)
HDFS分布式文件系统 一.HDFS简介 HDFS是Hadoop Distribute File System,翻译成中文就是Hadoop 分布式文件系统,它是Hadoop的核心组成部分,是一个分 ...
- C++串口通讯解决方案
这篇文章只是笔记性质,没有实际的原创内容,主要是做一下方案的备份. 串口通讯使用开源的 CSerialPort 类,我使用的是Windows版本分支: CSerialPort 跨平台 CSerialP ...