次の方法で共有


画面キャプチャ

Windows 10 バージョン 1803 以降では、Windows.Graphics.Capture 名前空間は、ディスプレイまたはアプリケーション ウィンドウからフレームを取得する API を提供し、ビデオ ストリームやスナップショットを作成してコラボレーションと対話型のエクスペリエンスを構築します。

画面キャプチャを使用すると、開発者はセキュリティで保護されたシステム UI を呼び出して、エンド ユーザーがキャプチャする表示ウィンドウまたはアプリケーション ウィンドウを選択し、アクティブにキャプチャされた項目の周囲に黄色の通知境界線がシステムによって描画されます。 複数の同時キャプチャ セッションの場合、キャプチャされる各項目の周囲に黄色の境界線が描画されます。

画面キャプチャ API は、Windows デバイスと Windows Mixed Reality イマーシブ ヘッドセットでのみサポートされます。

この記事では、表示ウィンドウまたはアプリケーション ウィンドウの 1 つの画像をキャプチャする方法について説明します。 画面からビデオ ファイルにキャプチャされたフレームをエンコードする方法については、「画面からビデオへのキャプチャ」を参照

画面キャプチャ機能を追加する

Windows.Graphics.Capture 名前空間にある API は、アプリケーションのマニフェストで一般的な機能を宣言する必要があります。

  1. Package.appxmanifestソリューション エクスプローラーで開きます。
  2. 機能タブ を選択します。
  3. グラフィックスキャプチャを確認します。

グラフィックス キャプチャ

システム UI を起動して画面キャプチャを開始する

システム UI を起動する前に、アプリケーションが現在画面キャプチャを実行できるかどうかを確認できます。 デバイスがハードウェア要件を満たしていない場合や、キャプチャ ブロックの画面キャプチャを対象とするアプリケーションなど、アプリケーションで画面キャプチャを使用できない理由はいくつかあります。 GraphicsCaptureSession クラスの IsSupported メソッドを使用して、UWP 画面キャプチャがサポートされているかどうかを確認します。

// This runs when the application starts.
public void OnInitialization()
{
    if (!GraphicsCaptureSession.IsSupported())
    {
        // Hide the capture UI if screen capture is not supported.
        CaptureButton.Visibility = Visibility.Collapsed;
    }
}
Public Sub OnInitialization()
    If Not GraphicsCaptureSession.IsSupported Then
        CaptureButton.Visibility = Visibility.Collapsed
    End If
End Sub

画面キャプチャがサポートされていることを確認したら、GraphicsCapturePicker クラスを使用してシステム ピッカー UI を呼び出します。 エンド ユーザーはこの UI を使用して、画面キャプチャを取得する表示ウィンドウまたはアプリケーション ウィンドウを選択します。 ピッカーは、GraphicsCaptureSessionの作成に使用される GraphicsCaptureItem を返します。

public async Task StartCaptureAsync()
{
    // The GraphicsCapturePicker follows the same pattern the
    // file pickers do.
    var picker = new GraphicsCapturePicker();
    GraphicsCaptureItem item = await picker.PickSingleItemAsync();

    // The item may be null if the user dismissed the
    // control without making a selection or hit Cancel.
    if (item != null)
    {
        // We'll define this method later in the document.
        StartCaptureInternal(item);
    }
}
Public Async Function StartCaptureAsync() As Task
    ' The GraphicsCapturePicker follows the same pattern the
    ' file pickers do.
    Dim picker As New GraphicsCapturePicker
    Dim item As GraphicsCaptureItem = Await picker.PickSingleItemAsync()

    ' The item may be null if the user dismissed the
    ' control without making a selection or hit Cancel.
    If item IsNot Nothing Then
        StartCaptureInternal(item)
    End If
End Function

これは UI コードであるため、UI スレッドで呼び出す必要があります。 アプリケーションのページ (MainPage.xaml.csなど) の分離コードから呼び出す場合、これは自動的に行われますが、呼び出さない場合は、次のコードを使用して UI スレッドで強制的に実行できます。

CoreWindow window = CoreApplication.MainView.CoreWindow;

await window.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
    await StartCaptureAsync();
});
Dim window As CoreWindow = CoreApplication.MainView.CoreWindow
Await window.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
                                 Async Sub() Await StartCaptureAsync())

キャプチャ フレーム プールとキャプチャ セッションを作成する

GraphicsCaptureItemを使用すると、D3D デバイス、サポートされているピクセル形式 (DXGI_FORMAT_B8G8R8A8_UNORM)、目的のフレーム数 (任意の整数)、フレーム サイズを使用して、Direct3D11CaptureFramePool を作成します。 GraphicsCaptureItem クラスの ContentSize プロパティは、フレームのサイズとして使用できます。

Windows HD カラーが有効になっているシステムでは、コンテンツ ピクセル形式が必ずしも DXGI_FORMAT_B8G8R8A8_UNORMとは限りません。 HDR コンテンツをキャプチャするときにピクセル オーバークリップ (つまり、キャプチャされたコンテンツが洗い流される) を回避するには、Direct3D11CaptureFramePoolCanvasBitmapなどのターゲット変換先など、キャプチャ パイプライン内のすべてのコンポーネントに DXGI_FORMAT_R16G16B16A16_FLOAT を使用することを検討してください。 必要に応じて、HDR コンテンツ形式への保存や HDR から SDR へのトーン マッピングなどの追加処理が必要になる場合があります。 この記事では、SDR コンテンツのキャプチャに焦点を当てます。 詳細については、「ダイナミック レンジディスプレイと高度なカラーで DirectX を使用する」を参照してください。

private GraphicsCaptureItem _item;
private Direct3D11CaptureFramePool _framePool;
private CanvasDevice _canvasDevice;
private GraphicsCaptureSession _session;

public void StartCaptureInternal(GraphicsCaptureItem item)
{
    _item = item;

    _framePool = Direct3D11CaptureFramePool.Create(
        _canvasDevice, // D3D device
        DirectXPixelFormat.B8G8R8A8UIntNormalized, // Pixel format
        2, // Number of frames
        _item.Size); // Size of the buffers
}
WithEvents CaptureItem As GraphicsCaptureItem
WithEvents FramePool As Direct3D11CaptureFramePool
Private _canvasDevice As CanvasDevice
Private _session As GraphicsCaptureSession

Private Sub StartCaptureInternal(item As GraphicsCaptureItem)
    CaptureItem = item

    FramePool = Direct3D11CaptureFramePool.Create(
        _canvasDevice, ' D3D device
        DirectXPixelFormat.B8G8R8A8UIntNormalized, ' Pixel format
        2, '  Number of frames
        CaptureItem.Size) ' Size of the buffers
End Sub

次に、GraphicsCaptureItemCreateCaptureSession メソッドに渡して、Direct3D11CaptureFramePoolGraphicsCaptureSession クラスのインスタンスを取得します。

_session = _framePool.CreateCaptureSession(_item);
_session = FramePool.CreateCaptureSession(CaptureItem)

ユーザーがアプリケーション ウィンドウのキャプチャまたはシステム UI での表示に明示的に同意すると、GraphicsCaptureItem を複数の CaptureSession オブジェクトに関連付けることができます。 これにより、アプリケーションは、さまざまなエクスペリエンスに対して同じ項目をキャプチャすることを選択できます。

複数の項目を同時にキャプチャするには、キャプチャする項目ごとにキャプチャ セッションを作成する必要があります。このセッションでは、キャプチャするアイテムごとにピッカー UI を呼び出す必要があります。

キャプチャ フレームを取得する

フレーム プールとキャプチャ セッションが作成されたら、GraphicsCaptureSession インスタンスで StartCapture メソッドを呼び出して、キャプチャ フレームのアプリへの送信を開始するようシステムに通知します。

_session.StartCapture();
_session.StartCapture()

これらの Direct3D11CaptureFrame オブジェクトであるキャプチャ フレームを取得するには、Direct3D11CaptureFramePool.FrameArrived イベントを使用できます。

_framePool.FrameArrived += (s, a) =>
{
    // The FrameArrived event fires for every frame on the thread that
    // created the Direct3D11CaptureFramePool. This means we don't have to
    // do a null-check here, as we know we're the only one  
    // dequeueing frames in our application.  

    // NOTE: Disposing the frame retires it and returns  
    // the buffer to the pool.
    using (var frame = _framePool.TryGetNextFrame())
    {
        // We'll define this method later in the document.
        ProcessFrame(frame);
    }  
};
Private Sub FramePool_FrameArrived(sender As Direct3D11CaptureFramePool, args As Object) Handles FramePool.FrameArrived
    ' The FrameArrived event is raised for every frame on the thread
    ' that created the Direct3D11CaptureFramePool. This means we
    ' don't have to do a null-check here, as we know we're the only
    ' one dequeueing frames in our application.  

    ' NOTE Disposing the frame retires it And returns  
    ' the buffer to the pool.

    Using frame = FramePool.TryGetNextFrame()
        ProcessFrame(frame)
    End Using
End Sub

このイベントは、新しいフレームが使用可能になるたびに発生するため、可能な場合は、FrameArrivedで UI スレッドを使用しないことをお勧めします。これは頻繁に発生します。 もし FrameArrived を UI スレッドでリッスンすることを選ぶ場合は、イベントが発生するたびに行う作業の量に注意してください。

または、必要なすべてのフレームを取得するまで、Direct3D11CaptureFramePool.TryGetNextFrame メソッドを使用して手動でフレームをプルすることもできます。

Direct3D11CaptureFrame オブジェクトには、ContentSize、Surface、および SystemRelativeTimeプロパティが含まれています。 SystemRelativeTime は、他のメディア要素の同期に使用できる QPC (QueryPerformanceCounter) 時間です。

プロセス キャプチャ フレーム

Direct3D11CaptureFramePool の各フレームは、TryGetNextFrame呼び出すときにチェックアウトされ、Direct3D11CaptureFrame オブジェクトの有効期間に従ってチェックインされます。 ネイティブ アプリケーションの場合、Direct3D11CaptureFrame オブジェクト を解放するだけで、フレーム プールにフレームをチェックインし直すことができます。 マネージド アプリケーションの場合は、Direct3D11CaptureFrame.Dispose (C++ で を閉じる) メソッドを使用することをお勧めします。 Direct3D11CaptureFrame は、IClosable インターフェイスを実装しており、C# 呼び出し元には IDisposable として提示されます。

アプリケーションでは、Direct3D11CaptureFrame オブジェクトへの参照を保存したり、フレームが再びチェックインされた後に基になる Direct3D サーフェスへの参照を保存したりしないでください。

フレームの処理中に、アプリケーションは、Direct3D11CaptureFramePool オブジェクトに関連付けられているのと同じデバイスで、ID3D11Multithread ロックを取ることをお勧めします。

基になる Direct3D サーフェスは常に、Direct3D11CaptureFramePoolを作成 (または再作成) するときに指定されたサイズになります。 コンテンツがフレームより大きい場合、コンテンツはフレームのサイズにクリップされます。 コンテンツがフレームよりも小さい場合、フレームの残りの部分には未定義のデータが含まれます。 未定義のコンテンツが表示されないように、アプリケーションでは、その Direct3D11CaptureFrameContentSize プロパティを使用してサブレクトをコピーアウトすることをお勧めします。

スクリーンショットを撮る

この例では、各 Direct3D11CaptureFrameCanvasBitmapに変換します。これは、Win2D APIの一部です。

// Convert our D3D11 surface into a Win2D object.
CanvasBitmap canvasBitmap = CanvasBitmap.CreateFromDirect3D11Surface(
    _canvasDevice,
    frame.Surface);

CanvasBitmapしたら、イメージ ファイルとして保存できます。 次の例では、ユーザーの Saved Pictures フォルダーに PNG ファイルとして保存します。

StorageFolder pictureFolder = KnownFolders.SavedPictures;
StorageFile file = await pictureFolder.CreateFileAsync("test.png", CreationCollisionOption.ReplaceExisting);

using (var fileStream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
    await canvasBitmap.SaveAsync(fileStream, CanvasBitmapFileFormat.Png, 1f);
}

アイテムのサイズ変更やデバイスの紛失に対応する

キャプチャ プロセス中に、アプリケーションで Direct3D11CaptureFramePoolの側面を変更したい場合があります。 これには、新しい Direct3D デバイスの提供、フレーム バッファーのサイズの変更、プール内のバッファー数の変更も含まれます。 これらの各シナリオでは、Direct3D11CaptureFramePool オブジェクトの Recreate メソッドが推奨されるツールです。

再作成 が呼び出されると、既存のすべてのフレームが破棄されます。 これは、基になる Direct3D サーフェスが、アプリケーションがアクセスできなくなったデバイスに属しているフレームを渡さないようにするためです。 このため、再作成を呼び出す前に、保留中のすべてのフレーム 処理することをお勧めします。

すべてをまとめる

次のコード スニペットは、UWP アプリケーションで画面キャプチャを実装する方法のエンドツーエンドの例です。 このサンプルでは、フロントエンドに 2 つのボタンがあります。1 つは Button_ClickAsync呼び出し、もう 1 つの呼び出しは ScreenshotButton_ClickAsync

このスニペットでは、2D グラフィックス レンダリング用のライブラリである Win2Dを使用します。 プロジェクトの設定方法については、ドキュメントを参照してください。

using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.UI.Composition;
using System;
using System.Numerics;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Graphics;
using Windows.Graphics.Capture;
using Windows.Graphics.DirectX;
using Windows.Storage;
using Windows.UI;
using Windows.UI.Composition;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Hosting;

namespace ScreenCaptureTest
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        // Capture API objects.
        private SizeInt32 _lastSize;
        private GraphicsCaptureItem _item;
        private Direct3D11CaptureFramePool _framePool;
        private GraphicsCaptureSession _session;

        // Non-API related members.
        private CanvasDevice _canvasDevice;
        private CompositionGraphicsDevice _compositionGraphicsDevice;
        private Compositor _compositor;
        private CompositionDrawingSurface _surface;
        private CanvasBitmap _currentFrame;
        private string _screenshotFilename = "test.png";

        public MainPage()
        {
            this.InitializeComponent();
            Setup();
        }

        private void Setup()
        {
            _canvasDevice = new CanvasDevice();

            _compositionGraphicsDevice = CanvasComposition.CreateCompositionGraphicsDevice(
                Window.Current.Compositor,
                _canvasDevice);

            _compositor = Window.Current.Compositor;

            _surface = _compositionGraphicsDevice.CreateDrawingSurface(
                new Size(400, 400),
                DirectXPixelFormat.B8G8R8A8UIntNormalized,
                DirectXAlphaMode.Premultiplied);    // This is the only value that currently works with
                                                    // the composition APIs.

            var visual = _compositor.CreateSpriteVisual();
            visual.RelativeSizeAdjustment = Vector2.One;
            var brush = _compositor.CreateSurfaceBrush(_surface);
            brush.HorizontalAlignmentRatio = 0.5f;
            brush.VerticalAlignmentRatio = 0.5f;
            brush.Stretch = CompositionStretch.Uniform;
            visual.Brush = brush;
            ElementCompositionPreview.SetElementChildVisual(this, visual);
        }

        public async Task StartCaptureAsync()
        {
            // The GraphicsCapturePicker follows the same pattern the
            // file pickers do.
            var picker = new GraphicsCapturePicker();
            GraphicsCaptureItem item = await picker.PickSingleItemAsync();

            // The item may be null if the user dismissed the
            // control without making a selection or hit Cancel.
            if (item != null)
            {
                StartCaptureInternal(item);
            }
        }

        private void StartCaptureInternal(GraphicsCaptureItem item)
        {
            // Stop the previous capture if we had one.
            StopCapture();

            _item = item;
            _lastSize = _item.Size;

            _framePool = Direct3D11CaptureFramePool.Create(
               _canvasDevice, // D3D device
               DirectXPixelFormat.B8G8R8A8UIntNormalized, // Pixel format
               2, // Number of frames
               _item.Size); // Size of the buffers

            _framePool.FrameArrived += (s, a) =>
            {
                // The FrameArrived event is raised for every frame on the thread
                // that created the Direct3D11CaptureFramePool. This means we
                // don't have to do a null-check here, as we know we're the only
                // one dequeueing frames in our application.  

                // NOTE: Disposing the frame retires it and returns  
                // the buffer to the pool.

                using (var frame = _framePool.TryGetNextFrame())
                {
                    ProcessFrame(frame);
                }
            };

            _item.Closed += (s, a) =>
            {
                StopCapture();
            };

            _session = _framePool.CreateCaptureSession(_item);
            _session.StartCapture();
        }

        public void StopCapture()
        {
            _session?.Dispose();
            _framePool?.Dispose();
            _item = null;
            _session = null;
            _framePool = null;
        }

        private void ProcessFrame(Direct3D11CaptureFrame frame)
        {
            // Resize and device-lost leverage the same function on the
            // Direct3D11CaptureFramePool. Refactoring it this way avoids
            // throwing in the catch block below (device creation could always
            // fail) along with ensuring that resize completes successfully and
            // isn’t vulnerable to device-lost.
            bool needsReset = false;
            bool recreateDevice = false;

            if ((frame.ContentSize.Width != _lastSize.Width) ||
                (frame.ContentSize.Height != _lastSize.Height))
            {
                needsReset = true;
                _lastSize = frame.ContentSize;
            }

            try
            {
                // Take the D3D11 surface and draw it into a  
                // Composition surface.

                // Convert our D3D11 surface into a Win2D object.
                CanvasBitmap canvasBitmap = CanvasBitmap.CreateFromDirect3D11Surface(
                    _canvasDevice,
                    frame.Surface);

                _currentFrame = canvasBitmap;

                // Helper that handles the drawing for us.
                FillSurfaceWithBitmap(canvasBitmap);
            }

            // This is the device-lost convention for Win2D.
            catch (Exception e) when (_canvasDevice.IsDeviceLost(e.HResult))
            {
                // We lost our graphics device. Recreate it and reset
                // our Direct3D11CaptureFramePool.  
                needsReset = true;
                recreateDevice = true;
            }

            if (needsReset)
            {
                ResetFramePool(frame.ContentSize, recreateDevice);
            }
        }

        private void FillSurfaceWithBitmap(CanvasBitmap canvasBitmap)
        {
            CanvasComposition.Resize(_surface, canvasBitmap.Size);

            using (var session = CanvasComposition.CreateDrawingSession(_surface))
            {
                session.Clear(Colors.Transparent);
                session.DrawImage(canvasBitmap);
            }
        }

        private void ResetFramePool(SizeInt32 size, bool recreateDevice)
        {
            do
            {
                try
                {
                    if (recreateDevice)
                    {
                        _canvasDevice = new CanvasDevice();
                    }

                    _framePool.Recreate(
                        _canvasDevice,
                        DirectXPixelFormat.B8G8R8A8UIntNormalized,
                        2,
                        size);
                }
                // This is the device-lost convention for Win2D.
                catch (Exception e) when (_canvasDevice.IsDeviceLost(e.HResult))
                {
                    _canvasDevice = null;
                    recreateDevice = true;
                }
            } while (_canvasDevice == null);
        }

        private async void Button_ClickAsync(object sender, RoutedEventArgs e)
        {
            await StartCaptureAsync();
        }

        private async void ScreenshotButton_ClickAsync(object sender, RoutedEventArgs e)
        {
            await SaveImageAsync(_screenshotFilename, _currentFrame);
        }

        private async Task SaveImageAsync(string filename, CanvasBitmap frame)
        {
            StorageFolder pictureFolder = KnownFolders.SavedPictures;

            StorageFile file = await pictureFolder.CreateFileAsync(
                filename,
                CreationCollisionOption.ReplaceExisting);

            using (var fileStream = await file.OpenAsync(FileAccessMode.ReadWrite))
            {
                await frame.SaveAsync(fileStream, CanvasBitmapFileFormat.Png, 1f);
            }
        }
    }
}
Imports System.Numerics
Imports Microsoft.Graphics.Canvas
Imports Microsoft.Graphics.Canvas.UI.Composition
Imports Windows.Graphics
Imports Windows.Graphics.Capture
Imports Windows.Graphics.DirectX
Imports Windows.UI
Imports Windows.UI.Composition
Imports Windows.UI.Xaml.Hosting

Partial Public NotInheritable Class MainPage
    Inherits Page

    ' Capture API objects.
    WithEvents CaptureItem As GraphicsCaptureItem
    WithEvents FramePool As Direct3D11CaptureFramePool

    Private _lastSize As SizeInt32
    Private _session As GraphicsCaptureSession

    ' Non-API related members.
    Private _canvasDevice As CanvasDevice
    Private _compositionGraphicsDevice As CompositionGraphicsDevice
    Private _compositor As Compositor
    Private _surface As CompositionDrawingSurface

    Sub New()
        InitializeComponent()
        Setup()
    End Sub

    Private Sub Setup()
        _canvasDevice = New CanvasDevice()
        _compositionGraphicsDevice = CanvasComposition.CreateCompositionGraphicsDevice(Window.Current.Compositor, _canvasDevice)
        _compositor = Window.Current.Compositor
        _surface = _compositionGraphicsDevice.CreateDrawingSurface(
            New Size(400, 400), DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied)
        Dim visual = _compositor.CreateSpriteVisual()
        visual.RelativeSizeAdjustment = Vector2.One
        Dim brush = _compositor.CreateSurfaceBrush(_surface)
        brush.HorizontalAlignmentRatio = 0.5F
        brush.VerticalAlignmentRatio = 0.5F
        brush.Stretch = CompositionStretch.Uniform
        visual.Brush = brush
        ElementCompositionPreview.SetElementChildVisual(Me, visual)
    End Sub

    Public Async Function StartCaptureAsync() As Task
        ' The GraphicsCapturePicker follows the same pattern the
        ' file pickers do.
        Dim picker As New GraphicsCapturePicker
        Dim item As GraphicsCaptureItem = Await picker.PickSingleItemAsync()

        ' The item may be null if the user dismissed the
        ' control without making a selection or hit Cancel.
        If item IsNot Nothing Then
            StartCaptureInternal(item)
        End If
    End Function

    Private Sub StartCaptureInternal(item As GraphicsCaptureItem)
        ' Stop the previous capture if we had one.
        StopCapture()

        CaptureItem = item
        _lastSize = CaptureItem.Size

        FramePool = Direct3D11CaptureFramePool.Create(
            _canvasDevice, ' D3D device
            DirectXPixelFormat.B8G8R8A8UIntNormalized, ' Pixel format
            2, '  Number of frames
            CaptureItem.Size) ' Size of the buffers

        _session = FramePool.CreateCaptureSession(CaptureItem)
        _session.StartCapture()
    End Sub

    Private Sub FramePool_FrameArrived(sender As Direct3D11CaptureFramePool, args As Object) Handles FramePool.FrameArrived
        ' The FrameArrived event is raised for every frame on the thread
        ' that created the Direct3D11CaptureFramePool. This means we
        ' don't have to do a null-check here, as we know we're the only
        ' one dequeueing frames in our application.  

        ' NOTE Disposing the frame retires it And returns  
        ' the buffer to the pool.

        Using frame = FramePool.TryGetNextFrame()
            ProcessFrame(frame)
        End Using
    End Sub

    Private Sub CaptureItem_Closed(sender As GraphicsCaptureItem, args As Object) Handles CaptureItem.Closed
        StopCapture()
    End Sub

    Public Sub StopCapture()
        _session?.Dispose()
        FramePool?.Dispose()
        CaptureItem = Nothing
        _session = Nothing
        FramePool = Nothing
    End Sub

    Private Sub ProcessFrame(frame As Direct3D11CaptureFrame)
        ' Resize and device-lost leverage the same function on the
        ' Direct3D11CaptureFramePool. Refactoring it this way avoids
        ' throwing in the catch block below (device creation could always
        ' fail) along with ensuring that resize completes successfully And
        ' isn't vulnerable to device-lost.

        Dim needsReset As Boolean = False
        Dim recreateDevice As Boolean = False

        If (frame.ContentSize.Width <> _lastSize.Width) OrElse
            (frame.ContentSize.Height <> _lastSize.Height) Then
            needsReset = True
            _lastSize = frame.ContentSize
        End If

        Try
            ' Take the D3D11 surface and draw it into a  
            ' Composition surface.

            ' Convert our D3D11 surface into a Win2D object.
            Dim bitmap = CanvasBitmap.CreateFromDirect3D11Surface(
                _canvasDevice,
                frame.Surface)

            ' Helper that handles the drawing for us.
            FillSurfaceWithBitmap(bitmap)
            ' This is the device-lost convention for Win2D.
        Catch e As Exception When _canvasDevice.IsDeviceLost(e.HResult)
            ' We lost our graphics device. Recreate it and reset
            ' our Direct3D11CaptureFramePool.  
            needsReset = True
            recreateDevice = True
        End Try

        If needsReset Then
            ResetFramePool(frame.ContentSize, recreateDevice)
        End If
    End Sub

    Private Sub FillSurfaceWithBitmap(canvasBitmap As CanvasBitmap)
        CanvasComposition.Resize(_surface, canvasBitmap.Size)

        Using session = CanvasComposition.CreateDrawingSession(_surface)
            session.Clear(Colors.Transparent)
            session.DrawImage(canvasBitmap)
        End Using
    End Sub

    Private Sub ResetFramePool(size As SizeInt32, recreateDevice As Boolean)
        Do
            Try
                If recreateDevice Then
                    _canvasDevice = New CanvasDevice()
                End If
                FramePool.Recreate(_canvasDevice, DirectXPixelFormat.B8G8R8A8UIntNormalized, 2, size)
                ' This is the device-lost convention for Win2D.
            Catch e As Exception When _canvasDevice.IsDeviceLost(e.HResult)
                _canvasDevice = Nothing
                recreateDevice = True
            End Try
        Loop While _canvasDevice Is Nothing
    End Sub

    Private Async Sub Button_ClickAsync(sender As Object, e As RoutedEventArgs) Handles CaptureButton.Click
        Await StartCaptureAsync()
    End Sub

End Class

ビデオを録画する

アプリケーションのビデオを録画する場合は、ビデオへのスクリーン キャプチャ 記事に記載されているチュートリアルに従うことができます。 または、Windows.Media.AppRecording 名前空間 を使用することもできます。 これは Desktop 拡張機能 SDK の一部であるため、Windows デスクトップでのみ機能し、プロジェクトから参照を追加する必要があります。 詳細については、「拡張 SDK を使用したプログラミング」を参照してください。

こちらも参照ください