Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Пространство имён Windows.Graphics.Capture предоставляет API для захвата кадров с дисплея или из окна приложения, а также для создания видеопотоков или снимков с целью реализации совместной работы и интерактивного взаимодействия.
При захвате экрана разработчики вызывают безопасный системный пользовательский интерфейс для конечных пользователей, чтобы выбрать окно отображения или приложения для захвата, а желтая граница уведомлений рисуется системой вокруг активно захваченного элемента. В случае нескольких одновременных сеансов захвата желтая граница рисуется вокруг каждого элемента, который фиксируется.
Note
API захвата экрана поддерживаются только на настольных устройствах Windows и иммерсивных гарнитурах Windows Mixed Reality.
В этой статье описывается запись одного изображения окна отображения или приложения.
Проверка поддержки захвата экрана
Прежде чем пытаться записать, проверьте, поддерживает ли текущее устройство захват экрана. Используйте метод IsSupported в GraphicsCaptureSession , чтобы определить, доступно ли запись экрана:
// Check if screen capture is supported
if (!GraphicsCaptureSession.IsSupported())
{
// Hide capture UI
CaptureControlsPanel.Visibility = Visibility.Collapsed;
PreviewPlaceholderText.Text = "Screen capture isn't supported on this device.";
UpdateStatus("Screen capture isn't supported on this device.");
return;
}
Существует несколько причин, по которым может не поддерживаться запись экрана, в том числе, если устройство не соответствует требованиям к оборудованию.
Запуск системного пользовательского интерфейса для запуска записи экрана
Используйте класс GraphicsCapturePicker для вызова системного средства выбора. Конечный пользователь использует этот пользовательский интерфейс для выбора окна отображения или приложения для записи. Селектор возвращает объект GraphicsCaptureItem, который используется для создания сеанса захвата.
В приложении WinUI 3 необходимо инициализировать средство выбора с помощью дескриптора окна перед вызовом PickSingleItemAsync:
// Launch picker and start capture
var picker = new GraphicsCapturePicker();
var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
WinRT.Interop.InitializeWithWindow.Initialize(picker, hwnd);
GraphicsCaptureItem item = await picker.PickSingleItemAsync();
if (item != null)
{
StartCaptureInternal(item);
}
Создайте пул кадров захвата и сеанс захвата
Используя GraphicsCaptureItem, создайте Direct3D11CaptureFramePool с устройством D3D , поддерживаемый формат пикселей (DXGI_FORMAT_B8G8R8A8_UNORM), количество нужных кадров (которое может быть любым целым числом) и размер кадра. Свойство Size класса GraphicsCaptureItem можно использовать в качестве размера кадра:
// Create frame pool and capture session
_framePool = Direct3D11CaptureFramePool.Create(
_canvasDevice,
CaptureDirectXPixelFormat.B8G8R8A8UIntNormalized,
BufferCount,
item.Size);
_session = _framePool.CreateCaptureSession(item);
Note
В системах, где включён режим Windows HD Color, формат пикселей содержимого необязательно должен быть DXGI_FORMAT_B8G8R8A8_UNORM. Чтобы избежать переполнения пикселей (т. е. захваченное содержимое выглядит вымытым) при захвате содержимого HDR рекомендуется использовать DXGI_FORMAT_R16G16B16A16_FLOAT для каждого компонента в конвейере записи, включая Direct3D11CaptureFramePool, целевое назначение, например CanvasBitmap. В зависимости от необходимости может потребоваться дополнительная обработка, например сохранение в формате содержимого HDR или сопоставление тонов HDR-to-SDR. В этой статье рассматривается запись содержимого SDR. Дополнительные сведения см. в разделе "Использование DirectX" с дисплеями с высоким динамическим диапазоном и расширенным цветом.
После того как пользователь явно выразил согласие на захват окна приложения или дисплея в системном интерфейсе пользователя, элемент GraphicsCaptureItem можно связать с несколькими сеансами захвата. Таким образом ваше приложение может захватывать один и тот же элемент для различных сценариев использования.
Получение кадров записи
После создания пула кадров и сеанса захвата вызовите StartCapture для экземпляра GraphicsCaptureSession, чтобы уведомить систему о необходимости начать отправку кадров захвата в ваше приложение.
Чтобы получать эти кадры захвата, представляющие собой объекты Direct3D11CaptureFrame, используйте событие Direct3D11CaptureFramePool.FrameArrived:
// Handle frame arrival
_framePool.FrameArrived += OnFrameArrived;
Рекомендуется избегать интенсивной работы с потоком пользовательского интерфейса для FrameArrived, так как это событие запускается каждый раз, когда новый кадр доступен. Если вы решили прослушивать FrameArrived в потоке пользовательского интерфейса, помните, сколько работы вы выполняете каждый раз, когда событие запускается.
Кроме того, можно вручную извлекать кадры с помощью метода Direct3D11CaptureFramePool.TryGetNextFrame , пока не получите все необходимые кадры.
Объект Direct3D11CaptureFrame содержит свойства ContentSize, Surface и SystemRelativeTime. SystemRelativeTime — это время QPC (QueryPerformanceCounter), которое можно использовать для синхронизации других элементов мультимедиа.
Кадры отслеживания процесса
Каждый кадр из Direct3D11CaptureFramePool извлекается при вызове TryGetNextFrame и проверяется обратно в соответствии со временем существования объекта Direct3D11CaptureFrame . Для управляемых приложений рекомендуется использовать метод Direct3D11CaptureFrame.Dispose . Direct3D11CaptureFrame реализует IDisposable, поэтому удаление кадра возвращает буфер в пул.
Приложения не должны сохранять ссылки на объекты Direct3D11CaptureFrame , а также не должны сохранять ссылки на базовую поверхность Direct3D после возврата кадра.
В этом примере каждый кадр преобразуется в CanvasBitmap, который входит в библиотеку Win2D :
// Convert frame to Win2D bitmap and display
CanvasBitmap canvasBitmap = CanvasBitmap.CreateFromDirect3D11Surface(
_canvasDevice,
frame.Surface);
Поверхность Direct3D, лежащая в основе, всегда имеет размер, указанный при создании (или повторном создании) Direct3D11CaptureFramePool. Если содержимое больше кадра, содержимое обрезается до размера кадра. Если содержимое меньше кадра, остальная часть кадра содержит неопределенные данные. Рекомендуется, чтобы приложения копировали подпрямоугольник, используя свойство ContentSize для этого Direct3D11CaptureFrame, чтобы избежать отображения неопределённого содержимого.
Сохранение снимка экрана
После создания CanvasBitmap его можно сохранить в виде файла изображения. В следующем примере сохраняется текущий кадр в виде PNG-файла с помощью FileSavePicker. В приложении WinUI 3 необходимо инициализировать средство выбора с помощью дескриптора окна:
// Save screenshot
var savePicker = new FileSavePicker();
savePicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
savePicker.SuggestedFileName = "screen-capture";
savePicker.FileTypeChoices.Add("PNG image", new List<string> { ".png" });
WinRT.Interop.InitializeWithWindow.Initialize(savePicker, _hwnd);
StorageFile? file = await savePicker.PickSaveFileAsync();
if (file is not null)
{
using var fileStream = await file.OpenAsync(FileAccessMode.ReadWrite);
await frameToSave.SaveAsync(fileStream, CanvasBitmapFileFormat.Png, 1f);
}
Реагировать на изменение размера элемента захвата или потерю устройства
Во время процесса захвата приложения могут захотеть изменить некоторые параметры своего Direct3D11CaptureFramePool. Это включает в себя предоставление нового устройства Direct3D, изменение размера буферов кадров или даже изменение количества буферов в пуле. В каждом из этих сценариев метод повторного создания объекта Direct3D11CaptureFramePool рекомендуется.
При вызове повторного создания все существующие кадры удаляются. Это позволяет предотвратить передачу кадров, базовые поверхности Direct3D которых принадлежат устройству, к которому приложение больше не имеет доступа. По этой причине может быть разумным обработать все ожидающие кадры перед вызовом Recreate.
Рекомендации по WinUI 3
При переносе кода записи экрана из UWP в WinUI 3 (Windows App SDK) учитывайте следующие различия.
- Инициализация дескриптора окна — такие средства выбора, как GraphicsCapturePicker и FileSavePicker, необходимо инициализировать, передав дескриптор окна с помощью InitializeWithWindow. Дополнительные сведения см. в разделе "Получение дескриптора окна( HWND)".
- API композиции на потоке UI — в WinUI 3 операции с поверхностью CanvasComposition (например, рисование на CompositionDrawingSurface) должны диспетчеризироваться в поток UI с помощью DispatcherQueue.TryEnqueue. Запись кадров и создание растрового рисунка может произойти в фоновом потоке пула кадров, но обновление визуального элемента композиции должно происходить в потоке пользовательского интерфейса.
-
Изменения в пространстве имён — используйте
Microsoft.UI.Composition,Microsoft.UI.Xaml.HostingиMicrosoft.UI.Dispatchingвместо соответствующих элементовWindows.UI. Пространство именWindows.Graphics.Captureостается неизменным.
См. также
- пространство имен Windows.Graphics.Capture
- Win2D для WinUI 3
- Получение дескриптора окна (HWND)
- Графика — индекс функций разработки графики для приложений Windows
- Примеры графики DirectX в GitHub
Windows developer