我正在尝试捕获屏幕快照,并使用SharpDX在Windows窗体(或面板)上显示它,但遇到了一些麻烦。我使用OutputDuplication.AcquireNextFrame
捕获了屏幕截图,但是当我尝试使用WindowRenderTarget.DrawBitmap
绘制带字幕的帧时,它失败,并出现WrongResourceDomain异常。我添加了一个表格并修改了ScreenCapture sample的代码以说明我的问题:
using System;
using SharpDX;
using SharpDX.Direct2D1;
using SharpDX.Direct3D11;
using SharpDX.DXGI;
namespace MiniTri
{
/// <summary>
/// Screen capture of the desktop using DXGI OutputDuplication.
/// </summary>
internal static class Program
{
[STAThread]
private static void Main()
{
var Form1 = new ScreenCapture.Form1();
// # of graphics card adapter
const int numAdapter = 0;
// # of output device (i.e. monitor)
const int numOutput = 0;
// Create DXGI Factory1
var dxgiFactory = new SharpDX.DXGI.Factory1();
var dxgiAdapter = dxgiFactory.GetAdapter1(numAdapter);
// Create device from Adapter
var d3dDevice = new SharpDX.Direct3D11.Device(dxgiAdapter, DeviceCreationFlags.BgraSupport);
// Create Direct2D1 Factory1
var d2dFactory = new SharpDX.Direct2D1.Factory1();
// Create Direct2D device
SharpDX.Direct2D1.Device d2dDevice;
using (var dxgiDevice = d3dDevice.QueryInterface<SharpDX.DXGI.Device>())
d2dDevice = new SharpDX.Direct2D1.Device(d2dFactory, dxgiDevice);
// Get the Direct2D1 DeviceContext
var d2dContext = new SharpDX.Direct2D1.DeviceContext(d2dDevice, DeviceContextOptions.None);
// Create Direct2D1 WindowRenderTarget
var WindowRenderTarget = new WindowRenderTarget(d2dFactory,
new RenderTargetProperties
{
Type = RenderTargetType.Default
},
new HwndRenderTargetProperties
{
Hwnd = Form1.Handle,
PixelSize = new Size2(Form1.Width, Form1.Height),
PresentOptions = PresentOptions.Immediately
});
// Get DXGI.Output
var output = dxgiAdapter.GetOutput(numOutput);
var output1 = output.QueryInterface<Output1>();
// Create RawRectangleF with the Form size
var FormRectangle = new SharpDX.Mathematics.Interop.RawRectangleF(0, 0, Form1.Width, Form1.Height);
// Duplicate the output
var duplicatedOutput = output1.DuplicateOutput(d3dDevice);
bool captureDone = false;
for (int i = 0; !captureDone; i++)
{
try
{
SharpDX.DXGI.Resource screenResource;
OutputDuplicateFrameInformation duplicateFrameInformation;
// Try to get duplicated frame within given time
duplicatedOutput.AcquireNextFrame(10000, out duplicateFrameInformation, out screenResource);
if (i > 0)
{
// Create a Direct2D1 Bitmap1 from screenResource
var dxgiSurface = screenResource.QueryInterface<Surface>();
var d2dBitmap1 = new Bitmap1(d2dContext, dxgiSurface);
// Should draw the bitmap on the form, but fails with "WrongResourceDomain" exception
WindowRenderTarget.BeginDraw();
WindowRenderTarget.DrawBitmap(d2dBitmap1, FormRectangle, 1.0f, BitmapInterpolationMode.Linear);
WindowRenderTarget.EndDraw();
// Capture done
captureDone = true;
}
screenResource.Dispose();
duplicatedOutput.ReleaseFrame();
}
catch (SharpDXException e)
{
if (e.ResultCode.Code != SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code)
{
throw e;
}
}
}
// TODO: We should cleanp up all allocated COM objects here
}
}
}
[我知道我可以将帧转换为System.Drawing.Bitmap
(就像在原始示例中一样),然后使用System.Drawing.Graphics.DrawImage
将位图绘制到窗体,但是我想避免这种情况,并使用SharpDX绘制帧。我也尝试过创建一个SwapChain
并使用Direct2D1.RenderTarget.DrawBitmap
绘制框架(类似于MiniRect sample),但是由于相同的异常而失败。与Direct2D1.DeviceContext.DrawBitmap
相同。我读到here,此异常表示我正在[[混合来自不同资源域的资源,但是我不完全了解代码中的含义。我没有使用DirectX的经验。
SwapChain
,而不是WindowRenderTarget
,这次我成功了。SwapChainDescription
,指定目标控件(例如,窗体或面板)的宽度,高度和句柄。SwapChain
,dxgiFactory
和d3dDevice
创建新的SwapChainDescription
。back buffer
的SwapChain
。DXGI Surface
获取back buffer
。SwapChain
中back buffer
,DXGI Surface
和MiniRect sample的创建的更多信息d2dContext
从Direct2D1.Bitmap1
创建DXGI Surface
。d2dContext
从Direct2D1.Bitmap1
创建另一个screenResource
(如上面的代码所示。Direct2D1.Bitmap1
设置为d2dContext
的目标。d2dContext
绘制第二个Direct2D1.Bitmap1
。SwapChain
。