Tangkapan layar
Mulai dari Windows 10, versi 1803, namespace Windows.Graphics.Capture menyediakan API untuk memperoleh bingkai dari jendela tampilan atau aplikasi, untuk membuat aliran video atau rekam jepret untuk membangun pengalaman kolaboratif dan interaktif.
Dengan tangkapan layar, pengembang memanggil UI sistem aman bagi pengguna akhir untuk memilih tampilan atau jendela aplikasi yang akan diambil, dan batas pemberitahuan kuning digambar oleh sistem di sekitar item yang diambil secara aktif. Dalam kasus beberapa sesi pengambilan simultan, batas kuning digambar di sekitar setiap item yang diambil.
Catatan
API tangkapan layar hanya didukung pada perangkat Windows dan headset imersif Windows Mixed Reality.
Artikel ini menjelaskan menangkap satu gambar jendela tampilan atau aplikasi. Untuk informasi tentang bingkai pengodean yang diambil dari layar ke file video, lihat Tangkapan layar ke video
Menambahkan kemampuan tangkapan layar
API yang ditemukan di namespace Windows.Graphics.Capture memerlukan kemampuan umum untuk dideklarasikan dalam manifes aplikasi Anda:
- Buka Package.appxmanifest di Penjelajah Solusi.
- Pilih tab Kemampuan.
- Periksa Pengambilan Grafis.
Luncurkan antarmuka pengguna sistem untuk memulai pengambilan layar
Sebelum meluncurkan antarmuka pengguna sistem, Anda dapat memeriksa untuk melihat apakah aplikasi Anda saat ini dapat mengambil tangkapan layar. Ada beberapa alasan mengapa aplikasi Anda mungkin tidak dapat menggunakan tangkapan layar, termasuk jika perangkat tidak memenuhi persyaratan perangkat keras atau jika aplikasi yang ditargetkan untuk pengambilan layar blok pengambilan. Gunakan metode IsSupported di kelas GraphicsCaptureSession untuk menentukan apakah tangkapan layar UWP didukung:
// 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
Setelah Anda memverifikasi bahwa tangkapan layar didukung, gunakan kelas GraphicsCapturePicker untuk memanggil UI pemilih sistem. Pengguna akhir menggunakan UI ini untuk memilih jendela tampilan atau aplikasi yang akan diambil tangkapan layarnya. Pemilih akan mengembalikan GraphicsCaptureItem yang akan digunakan untuk membuat GraphicsCaptureSession:
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
Karena ini adalah kode UI, kode tersebut perlu dipanggil pada utas UI. Jika Anda memanggilnya dari code-behind untuk halaman aplikasi Anda (seperti MainPage.xaml.cs) ini dilakukan untuk Anda secara otomatis, tetapi jika tidak, Anda dapat memaksanya untuk berjalan pada utas UI dengan kode berikut:
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())
Membuat kumpulan bingkai pengambilan dan mengambil sesi
Dengan menggunakan GraphicsCaptureItem, Anda akan membuat Direct3D11CaptureFramePool dengan perangkat D3D Anda, format piksel yang didukung (DXGI_FORMAT_B8G8R8A8_UNORM), jumlah bingkai yang diinginkan (yang dapat berupa bilangan bulat apa pun), dan ukuran bingkai. Properti ContentSize dari kelas GraphicsCaptureItem dapat digunakan sebagai ukuran bingkai Anda:
Catatan
Pada sistem dengan warna HD Windows diaktifkan, format piksel konten mungkin belum tentu DXGI_FORMAT_B8G8R8A8_UNORM. Untuk menghindari overkliping piksel (yaitu konten yang diambil terlihat dicuci) saat menangkap konten HDR, pertimbangkan untuk menggunakan DXGI_FORMAT_R16G16B16A16_FLOAT untuk setiap komponen dalam alur penangkapan, termasuk Direct3D11CaptureFramePool, tujuan target seperti CanvasBitmap. Tergantung pada kebutuhan, pemrosesan tambahan seperti menyimpan ke format konten HDR atau pemetaan nada HDR-ke-SDR mungkin diperlukan. Artikel ini akan berfokus pada pengambilan konten SDR. Untuk informasi selengkapnya, silakan lihat Menggunakan DirectX dengan Tampilan rentang dinamis tinggi dan Warna Tingkat Lanjut.
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
Selanjutnya, dapatkan instans kelas GraphicsCaptureSession untuk Direct3D11CaptureFramePool Anda dengan meneruskan GraphicsCaptureItem ke metode CreateCaptureSession:
_session = _framePool.CreateCaptureSession(_item);
_session = FramePool.CreateCaptureSession(CaptureItem)
Setelah pengguna secara eksplisit memberikan persetujuan untuk menangkap jendela aplikasi atau tampilan di antarmuka pengguna sistem, GraphicsCaptureItem dapat dikaitkan dengan beberapa objek CaptureSession . Dengan cara ini aplikasi Anda dapat memilih untuk mengambil item yang sama untuk berbagai pengalaman.
Untuk mengambil beberapa item secara bersamaan, aplikasi Anda harus membuat sesi pengambilan untuk setiap item yang akan diambil, yang mengharuskan memanggil UI pemilih untuk setiap item yang akan diambil.
Memperoleh bingkai pengambilan
Dengan kumpulan bingkai dan sesi pengambilan Anda dibuat, panggil metode StartCapture pada instans GraphicsCaptureSession Anda untuk memberi tahu sistem untuk mulai mengirim bingkai pengambilan ke aplikasi Anda:
_session.StartCapture();
_session.StartCapture()
Untuk memperoleh bingkai pengambilan ini, yang merupakan objek Direct3D11CaptureFrame , Anda dapat menggunakan peristiwa 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
Disarankan untuk menghindari penggunaan utas UI jika memungkinkan untuk FrameArrived, karena peristiwa ini akan dinaikkan setiap kali bingkai baru tersedia, yang akan sering terjadi. Jika Anda memilih untuk mendengarkan FrameArrived di utas UI, perhatikan berapa banyak pekerjaan yang Anda lakukan setiap kali peristiwa diaktifkan.
Atau, Anda dapat menarik bingkai secara manual dengan metode Direct3D11CaptureFramePool.TryGetNextFrame hingga Anda mendapatkan semua bingkai yang Anda butuhkan.
Objek Direct3D11CaptureFrame berisi properti ContentSize, Surface, dan SystemRelativeTime. SystemRelativeTime adalah waktu QPC (QueryPerformanceCounter) yang dapat digunakan untuk menyinkronkan elemen media lainnya.
Bingkai pengambilan proses
Setiap bingkai dari Direct3D11CaptureFramePool dicek keluar saat memanggil TryGetNextFrame, dan diperiksa kembali sesuai dengan masa pakai objek Direct3D11CaptureFrame. Untuk aplikasi asli, merilis objek Direct3D11CaptureFrame sudah cukup untuk memeriksa bingkai kembali ke kumpulan bingkai. Untuk aplikasi terkelola, disarankan untuk menggunakan metode Direct3D11CaptureFrame.Dispose (Tutup dalam C++). Direct3D11CaptureFrame mengimplementasikan antarmuka IClosable , yang diproyeksikan sebagai IDisposable untuk pemanggil C#.
Aplikasi tidak boleh menyimpan referensi ke objek Direct3D11CaptureFrame , juga tidak boleh menyimpan referensi ke permukaan Direct3D yang mendasarinya setelah bingkai diperiksa kembali.
Saat memproses bingkai, disarankan agar aplikasi mengambil kunci ID3D11Multithread pada perangkat yang sama yang terkait dengan objek Direct3D11CaptureFramePool .
Permukaan Direct3D yang mendasarinya akan selalu menjadi ukuran yang ditentukan saat membuat (atau membuat ulang) Direct3D11CaptureFramePool. Jika konten lebih besar dari bingkai, konten akan diklip ke ukuran bingkai. Jika konten lebih kecil dari bingkai, bingkai lainnya berisi data yang tidak ditentukan. Disarankan agar aplikasi menyalin sub-rect menggunakan properti ContentSize untuk Direct3D11CaptureFrame tersebut untuk menghindari menampilkan konten yang tidak ditentukan.
Ambil cuplikan layar
Dalam contoh kami, kami mengonversi setiap Direct3D11CaptureFrame menjadi CanvasBitmap, yang merupakan bagian dari API Win2D.
// Convert our D3D11 surface into a Win2D object.
CanvasBitmap canvasBitmap = CanvasBitmap.CreateFromDirect3D11Surface(
_canvasDevice,
frame.Surface);
Setelah kita memiliki CanvasBitmap, kita dapat menyimpannya sebagai file gambar. Dalam contoh berikut, kami menyimpannya sebagai file PNG di folder Gambar Tersimpan pengguna.
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);
}
Bereaksi terhadap mengubah ukuran item atau perangkat yang hilang
Selama proses pengambilan, aplikasi mungkin ingin mengubah aspek Direct3D11CaptureFramePool mereka. Ini termasuk menyediakan perangkat Direct3D baru, mengubah ukuran buffer bingkai, atau bahkan mengubah jumlah buffer dalam kumpulan. Dalam setiap skenario ini, metode Buat ulang pada objek Direct3D11CaptureFramePool adalah alat yang direkomendasikan.
Ketika Dibuat ulang dipanggil, semua bingkai yang ada akan dibuang. Ini untuk mencegah membagikan bingkai yang permukaan Direct3D yang mendasarnya milik perangkat yang mungkin tidak lagi dapat diakses oleh aplikasi. Untuk alasan ini, mungkin bijaksana untuk memproses semua bingkai yang tertunda sebelum memanggil Buat Ulang.
Merangkum semuanya
Cuplikan kode berikut adalah contoh end-to-end tentang cara mengimplementasikan tangkapan layar dalam aplikasi UWP. Dalam sampel ini, kita memiliki dua tombol di front-end: satu panggilan Button_ClickAsync, dan panggilan lainnya ScreenshotButton_ClickAsync.
Catatan
Cuplikan ini menggunakan Win2D, pustaka untuk penyajian grafis 2D. Lihat dokumentasi mereka untuk informasi tentang cara menyiapkannya untuk proyek Anda.
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
Merekam video
Jika Anda ingin merekam video aplikasi, Anda dapat mengikuti panduan yang disajikan dalam artikel Tangkapan layar ke video. Atau, Anda dapat menggunakan namespace Layanan Windows.Media.AppRecording. Ini adalah bagian dari SDK ekstensi Desktop, sehingga hanya berfungsi pada desktop Windows dan mengharuskan Anda menambahkan referensi ke dalamnya dari proyek Anda. Lihat Pemrograman dengan SDK ekstensi untuk informasi selengkapnya.