aardio 文档
aardio 范例: WGC 截图
import console;
import dotNet.uwpCompiler;
var uwpCompiler;
try{
/*
创建启用 WinRT / UWP 接口的 .NET 编译器,
请先安装 Windows 10 SDK,安装 SDK 后 aardio 会自动引用 Windows.winmd 。
可选用参数 @2 显式指定 WinRT 元数据文件 Windows.winmd 的路径(一般不必要)。
Windows.winmd 是一个大集合,一般不需要额外再引用其他系统 winmd。
调用编译后的 DLL 不需要 Windows.winmd ,仅编译时需要。
dotNet.uwpCompiler 基于 CLR 4.0 编译器,
在 Win10 以及更新系统支持并且仅支持 C# 5.0 语法。
已默认添加引用 System.Runtime.dll,System.Runtime.WindowsRuntime.dll,System.Runtime.InteropServices.WindowsRuntim
*/
uwpCompiler = dotNet.uwpCompiler("/aardio.WindowsRuntime.dll")
}
console.assert(uwpCompiler,"请先安装 Windows 10 SDK")
uwpCompiler.Source = /******
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.Graphics.Capture;
using Windows.Graphics.DirectX;
using Windows.Graphics.DirectX.Direct3D11;
using Windows.Graphics.Imaging;
using Windows.Storage;
namespace Aardio.WGC {
[ComImport]
[Guid("3628E81B-3CAC-4C60-B7F4-23CE0E0C3356")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IGraphicsCaptureItemInterop {
void CreateForWindow([In] IntPtr window, [In] ref Guid iid, [MarshalAs(UnmanagedType.IUnknown)] out object result);
}
public class CaptureService {
[DllImport("d3d11.dll")]
static extern int D3D11CreateDevice(IntPtr pAdapter, int DriverType, IntPtr Software, uint Flags,
IntPtr pFeatureLevels, uint FeatureLevels, uint SDKVersion,
out IntPtr ppDevice, IntPtr pFeatureLevel, out IntPtr ppImmediateContext);
[DllImport("d3d11.dll")]
static extern int CreateDirect3D11DeviceFromDXGIDevice(IntPtr dxgiDevice, out IntPtr graphicsDevice);
public string TakeWindowScreenshot(IntPtr hwnd, string savePath) {
try {
string fullPath = Path.GetFullPath(savePath);
return Task.Run(() => TakeScreenshotAsync(hwnd, fullPath)).Result;
} catch (Exception ex) {
string errorMsg = ex.Message;
if (ex.InnerException != null) {
errorMsg = ex.InnerException.Message;
}
return "抓取失败: " + errorMsg;
}
}
private async Task<string> TakeScreenshotAsync(IntPtr hwnd, string savePath) {
var factory = WindowsRuntimeMarshal.GetActivationFactory(typeof(GraphicsCaptureItem));
var interop = (IGraphicsCaptureItemInterop)factory;
Guid itemGuid = new Guid("79C3F95B-31F7-4EC2-A464-632EF5D30760");
object itemObject;
interop.CreateForWindow(hwnd, ref itemGuid, out itemObject);
GraphicsCaptureItem item = (GraphicsCaptureItem)itemObject;
if (item.Size.Width == 0 || item.Size.Height == 0) {
return "抓取失败: 窗口不可见或已被最小化。";
}
IntPtr pDevice = IntPtr.Zero;
IntPtr pContext = IntPtr.Zero;
IntPtr pWinRTDevice = IntPtr.Zero;
try {
int hr = D3D11CreateDevice(IntPtr.Zero, 1, IntPtr.Zero, 0x20, IntPtr.Zero, 0, 7, out pDevice, IntPtr.Zero, out pContext);
if (hr < 0) return "D3D11CreateDevice 失败。";
object dxgiDevice = Marshal.GetObjectForIUnknown(pDevice);
IntPtr pUnkDxgi = Marshal.GetIUnknownForObject(dxgiDevice);
hr = CreateDirect3D11DeviceFromDXGIDevice(pUnkDxgi, out pWinRTDevice);
Marshal.Release(pUnkDxgi);
if (hr < 0) return "转码设备失败。";
var device = (IDirect3DDevice)Marshal.GetObjectForIUnknown(pWinRTDevice);
var framePool = Direct3D11CaptureFramePool.Create(device, DirectXPixelFormat.B8G8R8A8UIntNormalized, 1, item.Size);
var session = framePool.CreateCaptureSession(item);
session.StartCapture();
Direct3D11CaptureFrame capturedFrame = null;
/*
不使用事件,改为主动轮询(尝试获取,没有就等 20ms),最多等 1 秒。
完美避开老版本 C# 编译器对 WinRT 事件处理的各种坑。
当然,也可以直接改用 VS 编辑器先行编译 DLL 程序集。
*/
for (int i = 0; i < 50; i++) {
capturedFrame = framePool.TryGetNextFrame();
if (capturedFrame != null) {
break; // 拿到画面了,跳出循环
}
await Task.Delay(20);
}
// 拿到一帧或者超时后,即可停止捕获释放资源
session.Dispose();
framePool.Dispose();
device.Dispose();
if (capturedFrame == null) {
return "抓取失败: 等待画面帧超时。";
}
using (capturedFrame)
{
// 转换为可编码的图像位图
var softwareBitmap = await SoftwareBitmap.CreateCopyFromSurfaceAsync(capturedFrame.Surface);
var folder = await StorageFolder.GetFolderFromPathAsync(Path.GetDirectoryName(savePath));
var file = await folder.CreateFileAsync(Path.GetFileName(savePath), CreationCollisionOption.ReplaceExisting);
using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite)) {
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
encoder.SetSoftwareBitmap(softwareBitmap);
await encoder.FlushAsync();
}
}
return "截图成功!";
}
finally {
if (pContext != IntPtr.Zero) Marshal.Release(pContext);
if (pDevice != IntPtr.Zero) Marshal.Release(pDevice);
if (pWinRTDevice != IntPtr.Zero) Marshal.Release(pWinRTDevice);
}
}
}
}
******/
console.showLoading("正在编译 C# 代码并执行 WGC 截屏...");
var ret = uwpCompiler.Compile();
if(!ret){
console.error("编译错误:\n" + uwpCompiler.getLastError());
console.pause(true);
return;
}
var assembly = dotNet.load("/WgcCapture.dll");
assembly.import("Aardio.WGC");
var captureService = Aardio.WGC.CaptureService();
// 指定保存路径
var savePath = io.tmpname("wgc_screenshot",".png")
// 获取当前控制台句柄进行测试
var hwnd = console.getWindow();
// 调用抓取
var result = captureService.TakeWindowScreenshot(hwnd, savePath);
console.log(result);
if(string.startWith(result, "截图成功")){
console.log("图片路径: ", savePath);
raw.execute(savePath);
}
console.pause(true);
Markdown 格式