转自: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截图最小实现的更多相关文章

  1. Linux系统中最好用的截图软件介绍

    当我的主力操作系统从 Windows 转换到 Ubuntu 的时候,首要考虑的就是屏幕截图工具的可用性.尽管使用默认的键盘快捷键也可以获取屏幕截图,但如果使用屏幕截图工具,可以更方便地对屏幕截图进行编 ...

  2. kettle转换设置变量,校验输出新变量

    背景:有很多小的转换需要串联起来,如果前一个执行成功,后面继续接着执行,如果执行等待中,就让程序等一会再次获取数据分析,如果失败就中止,成功就进行下一个转换,以此类推.... 需求:通过job把参数传 ...

  3. Windows GDI 窗口与 Direct3D 屏幕截图

    前言 Windows 上,屏幕截图一般是调用 win32 api 完成的,如果 C# 想实现截图功能,就需要封装相关 api.在 Windows 上,主要图形接口有 GDI 和 DirectX.GDI ...

  4. MVVM架构~knockoutjs系列之验证信息自定义输出~再续

    返回目录 对于一个项目的表单验证,方式有很多,效果也有很多,具体使用哪种完成取决于产品这边,产品让你用什么,你就要用什么,而做为开发人员,我们要做的就是"整理近可能多的架构方式",这样才可以自由的应变 ...

  5. Pyqt 屏幕截图工具

    从Pyqt的examples中看到一段截图代码, (路径:examplas\desktop\screenshot.py) 所以想自己UI下界面,手动练习下 通过UI生成的: Screenshot.py ...

  6. Node.js系列-express(下)

    前言 距上次更新博客又两个月多了,这两个月内除了上班时间忙公司的项目外,下班后也没有闲着,做了点外包,有小程序的,管理端的项目.也可能那段时间做的外包项目也都比较急,所以晚上都搞到一点左右睡,严重的压 ...

  7. 用delphi实现完美屏幕截图

    可以截取layered窗口(包括透明窗口)的代码: procedure CaptureScreen(AFileName: string);const  CAPTUREBLT = $40000000;v ...

  8. 如何使用T-SQL备份还原数据库及c#如何调用执行?

    准备材料:Microsoft SQL Server一部.需要还原的bak文件一只 一.备份 数据库备份语句:user master backup database 数据库名 to disk='保存路径 ...

  9. 独立开发人员低成本推广APP的18条技巧

    导语:知道并不等于运行,有些最主要的推广方法往往会被忽略.这些,是自国外开发人员总结出的这18条经验. 如今市面上充满了大牌子大公司和大制作的手机游戏,常常有游戏花300万成本开发,然后再花2000万 ...

  10. 如何使用T-SQL备份还原数据库及c#如何调用执行? C#中索引器的作用和实现。 jquery控制元素的隐藏和显示的几种方法。 localStorage、sessionStorage用法总结 在AspNetCore中扩展Log系列 - 介绍开源类库的使用(一) span<T>之高性能字符串操作实测

    如何使用T-SQL备份还原数据库及c#如何调用执行? 准备材料:Microsoft SQL Server一部.需要还原的bak文件一只 一.备份 数据库备份语句:user master backup ...

随机推荐

  1. 【WiFi开发全攻略】WIFI基础知识大全

    [WiFi开发全攻略]WIFI基础知识大全 1. Wi-Fi起源 现在我们大家对Wi-Fi肯定都不陌生,无论是笔记本,手机,智能电视,都离不开Wi-Fi.目前我们一般用的都是Wi-Fi5,Wi-Fi6 ...

  2. JVM运行时参数

    JVM运行时参数 JVM运行时参数是用于配置和调整Java虚拟机的行为和性能的参数.这些参数可以在启动Java应用程序时通过命令行或配置文件进行设置,合理配置参数可以使JVM虚拟机的达到更好的性能,降 ...

  3. 【LeetCode二叉树#03】翻转二叉树的几种方法

    翻转二叉树 力扣题目链接(opens new window) 翻转一棵二叉树. 这道题目背后有一个让程序员心酸的故事,听说 Homebrew的作者Max Howell,就是因为没在白板上写出翻转二叉树 ...

  4. Python函数每日一讲 - 一文让你彻底明白hasattr函数的使用

    引言 在Python编程中,经常会遇到需要判断对象是否具有某个属性的情况.这时候就可以用到Python内置函数 hasattr().本文将深入探讨 hasattr() 函数的使用方法及其在实际编程中的 ...

  5. 制作有延迟插件的rabbitmq镜像

    插件Git官方地址:https://github.com/rabbitmq/rabbitmq-delayed-message-exchange Dockerfile FROM rabbitmq:3.8 ...

  6. 新零售SaaS架构:订单履约系统架构设计(万字图文总结)

    什么是订单履约系统? 订单履约系统用来管理从接收客户订单到将商品送达客户手中的全过程. 它连接了上游交易(客户在销售平台下单环)和下游仓储配送(如库存管理.物流配送),确保信息流顺畅.操作协同,提升整 ...

  7. Spring事务(二)-@Transactional注解

    上一节说了Spring的事务配置,其中,声明式事务配置里有5种配置方式, @Transactional注解应该是最为常用的一种方式了.这一节就说说@Transactional注解. @Transact ...

  8. 新增、修改校验逻辑使用-Validation-的group分组校验完成-2022新项目

    一.业务场景 一般在项目开发中少不了新增.修改操作,这两个操作中传递的参数中也仅仅只有一个参数是不一致的,新增操作时没有ID, 修改时有ID,其校验逻辑也只有这一个ID校验的差别.最开始自己在写代码时 ...

  9. Failed to instantiate [applets.nature.mapper.LogInfoMapper]: Specified class is an interface-项目启动报错

    一.问题由来 周日下午项目在进行测试时,有些东西需要临时修改,自己已经打好一个包部署到测试服务器进行部署.在测试过程中发现一个问题,就是 现在的代码跑起来是没问题的,只是其他人又的东西还没做,所以暂时 ...

  10. idea vue 格式化 并保存文件 宏 快捷键 ctrl+s

    idea 格式化是 reformat Code 存盘是 ctrl+s 所以创建一个宏,先点格式化,再点存盘,然后定义个ctrl+s的快捷键覆盖之前的保存就ok了. 资料: IDEA 配置宏定义 并为宏 ...