我正在寻找一种方法来截图一个活动(非重点)窗口使用其IntPtr
,而不使用user32.dll
PrintWindow
,因为它需要运行的应用程序作为管理员。
我能够使用WinRT进行屏幕捕获,遵循此repo,并进行了一些调整,使其在dotnet 6 -https://github.com/microsoft/Windows.UI.Composition-Win32-Samples/tree/master/dotnet/WPF/ScreenCapture中工作
现在剩下的就是将帧(Direct3D11CaptureFrame
)转换为我可以实际保存的图像。
这是UWP,但其想法是通过执行以下操作将D3 D11曲面转换为Win 2D对象-
// Convert our D3D11 surface into a Win2D object.
CanvasBitmap canvasBitmap = CanvasBitmap.CreateFromDirect3D11Surface(
_canvasDevice,
frame.Surface);
问题是,该示例中的_canvasDevice
是一个ICanvasResourceCreator
,我没有按照上面分享的WPF屏幕捕获存储库。
CanvasDevice.GetSharedDevice()
但是在CreateFromDirect3D11Surface
方法中使用该设备会引发异常The requested operation is not supported. (0x88990003)
。
如果任何人有一个想法,如何解决这个问题或实现我的目标,使用不同的方法,我会感激任何帮助。
谢谢!
编辑-在整个OnFrameArrived
方法下面添加,我尝试将帧转换为CanvasBitmap
,就像我在上面链接的UWP代码示例中所做的那样-
private void OnFrameArrived(Direct3D11CaptureFramePool sender, object args)
{
var newSize = false;
using (var frame = sender.TryGetNextFrame())
{
var canvasDevice = CanvasDevice.GetSharedDevice();
//Convert our D3D11 surface into a Win2D object.
//this method below throws the exception
_currentFrame = CanvasBitmap.CreateFromDirect3D11Surface(
canvasDevice,
frame.Surface);
if (frame.ContentSize.Width != lastSize.Width ||
frame.ContentSize.Height != lastSize.Height)
{
// The thing we have been capturing has changed size.
// We need to resize the swap chain first, then blit the pixels.
// After we do that, retire the frame and then recreate the frame pool.
newSize = true;
lastSize = frame.ContentSize;
swapChain.ResizeBuffers(
2,
lastSize.Width,
lastSize.Height,
Format.B8G8R8A8_UNorm,
SwapChainFlags.None);
}
using (var backBuffer = swapChain.GetBackBuffer<Texture2D>(0))
using (var bitmap = Direct3D11Helper.CreateSharpDXTexture2D(frame.Surface))
{
d3dDevice.ImmediateContext.CopyResource(bitmap, backBuffer);
}
} // Retire the frame.
swapChain.Present(0, PresentFlags.None);
if (newSize)
{
framePool.Recreate(
device,
DirectXPixelFormat.B8G8R8A8UIntNormalized,
2,
lastSize);
}
}
```
1条答案
按热度按时间u0sqgete1#
你不需要Direct2D(Win2D是Direct2D的一个 Package )来从一个表面获取字节。你可以使用标准的DirectX API获取字节,然后使用你想要的Bitmap API将它们写入一个文件。
这里是一个使用WinRT的SoftwareBitmap和BitmapEncoder的例子,但是你可以使用GDI+(系统.绘图.位图,WIC等)来保存文件。
从BasicCapture.cs文件开始,像这样修改它: