Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
El Windows. Graphics.Capture espacio de nombres proporciona API para adquirir fotogramas de una ventana de presentación o aplicación, para crear secuencias de vídeo o instantáneas para crear experiencias colaborativas e interactivas.
Con la captura de pantalla, los desarrolladores invocan la interfaz de usuario del sistema segura para que los usuarios finales elijan la ventana de visualización o aplicación que se va a capturar y el sistema dibuja un borde de notificación amarillo alrededor del elemento capturado activamente. En el caso de varias sesiones de captura simultáneas, se dibuja un borde amarillo alrededor de cada elemento que se captura.
Note
Las API de captura de pantalla solo son compatibles con dispositivos de escritorio con Windows y visores inmersivos de Windows Mixed Reality.
En este artículo se describe la captura de una sola imagen de la ventana de visualización o aplicación.
Comprobación de la compatibilidad con capturas de pantalla
Antes de intentar capturar, compruebe si el dispositivo actual admite la captura de pantalla. Use el método IsSupported en GraphicsCaptureSession para determinar si la captura de pantalla está disponible:
// 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;
}
Hay varias razones por las que es posible que no se admita la captura de pantalla, incluido si el dispositivo no cumple los requisitos de hardware.
Iniciar la interfaz de usuario del sistema para iniciar la captura de pantalla
Use la clase GraphicsCapturePicker para invocar la interfaz de usuario del selector del sistema. El usuario final usa esta interfaz de usuario para seleccionar la ventana de visualización o aplicación que se va a capturar. El selector devuelve un graphicsCaptureItem que se usa para crear una sesión de captura.
En una aplicación winUI 3, debes inicializar el selector con el identificador de ventana antes de llamar a 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);
}
Creación de un grupo de fotogramas de captura y una sesión de captura
Con GraphicsCaptureItem, cree un Direct3D11CaptureFramePool con su dispositivo D3D, un formato de píxel compatible (DXGI_FORMAT_B8G8R8A8_UNORM), el número de fotogramas deseado (que puede ser cualquier número entero) y el tamaño del fotograma. La propiedad Size de la clase GraphicsCaptureItem se puede usar como tamaño del marco:
// Create frame pool and capture session
_framePool = Direct3D11CaptureFramePool.Create(
_canvasDevice,
CaptureDirectXPixelFormat.B8G8R8A8UIntNormalized,
BufferCount,
item.Size);
_session = _framePool.CreateCaptureSession(item);
Note
En los sistemas con Windows HD Color habilitado, es posible que el formato de píxel del contenido no sea necesariamente DXGI_FORMAT_B8G8R8A8_UNORM. Para evitar la sobresaturación de píxeles (es decir, que el contenido capturado se vea deslavado) al capturar contenido HDR, considere usar DXGI_FORMAT_R16G16B16A16_FLOAT para cada componente del flujo de captura, incluidos Direct3D11CaptureFramePool y el destino de salida, como CanvasBitmap. Dependiendo de la necesidad, es posible que sea necesario un procesamiento adicional, como guardar en formato de contenido HDR o la asignación de tono HDR a SDR. Este artículo se centra en la captura de contenido de SDR. Para obtener más información, consulte Uso de DirectX con pantallas de alto rango dinámico y color avanzado.
Una vez que el usuario haya dado explícitamente su consentimiento para capturar una ventana de aplicación o mostrarla en la interfaz de usuario del sistema, graphicsCaptureItem se puede asociar a varias sesiones de captura. De este modo, la aplicación puede optar por capturar el mismo elemento para diversas experiencias.
Adquisición de fotogramas de captura
Con el grupo de fotogramas y la sesión de captura creadas, llame a StartCapture en la instancia de GraphicsCaptureSession para notificar al sistema que empiece a enviar fotogramas de captura a la aplicación.
Para adquirir estos fotogramas de captura, que son objetos Direct3D11CaptureFrame , use el evento Direct3D11CaptureFramePool.FrameArrived :
// Handle frame arrival
_framePool.FrameArrived += OnFrameArrived;
Se recomienda evitar realizar un trabajo intensivo en el subproceso de interfaz de usuario para FrameArrived, ya que este evento se desencadena cada vez que hay disponible un nuevo fotograma. Si decide escuchar FrameArrived en el subproceso de la interfaz de usuario, tenga en cuenta cuánto trabajo está realizando cada vez que se desencadena el evento.
Como alternativa, puede extraer manualmente fotogramas con el método Direct3D11CaptureFramePool.TryGetNextFrame hasta obtener todos los fotogramas que necesita.
El objeto Direct3D11CaptureFrame contiene las propiedades ContentSize, Surface y SystemRelativeTime. SystemRelativeTime es la hora de QPC (QueryPerformanceCounter) que se puede usar para sincronizar otros elementos multimedia.
Procesar fotogramas de captura
Cada fotograma del Direct3D11CaptureFramePool se obtiene al llamar a TryGetNextFrame y se devuelve en función del tiempo de vida del objeto Direct3D11CaptureFrame. En el caso de las aplicaciones administradas, se recomienda usar el método Direct3D11CaptureFrame.Dispose . Direct3D11CaptureFrame implementa IDisposable, por lo que la eliminación del marco devuelve el búfer al grupo.
Las aplicaciones no deben guardar referencias a objetos Direct3D11CaptureFrame , ni deben guardar referencias a la superficie de Direct3D subyacente después de volver a activar el marco.
En este ejemplo, cada fotograma se convierte en canvasBitmap, que forma parte de la biblioteca Win2D :
// Convert frame to Win2D bitmap and display
CanvasBitmap canvasBitmap = CanvasBitmap.CreateFromDirect3D11Surface(
_canvasDevice,
frame.Surface);
La superficie Direct3D subyacente siempre tiene el tamaño especificado al crear (o volver a crear) el Direct3D11CaptureFramePool. Si el contenido es mayor que el marco, el contenido se recorta al tamaño del marco. Si el contenido es menor que el marco, el resto del marco contiene datos indefinidos. Se recomienda que las aplicaciones copien un subrectángulo usando la propiedad ContentSize de ese Direct3D11CaptureFrame para evitar mostrar contenido indefinido.
Guardar una captura de pantalla
Una vez que tenga un CanvasBitmap, puede guardarlo como un archivo de imagen. En el ejemplo siguiente se guarda el marco actual como un archivo PNG mediante un FileSavePicker. En una aplicación WinUI 3, debes inicializar el selector con el identificador de la ventana:
// 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);
}
Reaccionar al cambio de tamaño del elemento de captura o a la pérdida del dispositivo
Durante el proceso de captura, las aplicaciones pueden querer cambiar aspectos de su Direct3D11CaptureFramePool. Esto incluye proporcionar un nuevo dispositivo Direct3D, cambiar el tamaño de los búferes de fotogramas o incluso cambiar el número de búferes dentro del grupo. En cada uno de estos escenarios, el método Create en el objeto Direct3D11CaptureFramePool es el enfoque recomendado.
Cuando se invoca Recreate, se descartan todos los fotogramas existentes. Esto es para evitar la entrega de fotogramas cuyas superficies de Direct3D subyacentes pertenecen a un dispositivo al que puede que la aplicación ya no tenga acceso. Por este motivo, puede ser conveniente procesar todos los fotogramas pendientes antes de llamar a Recreate.
Consideraciones sobre WinUI 3
Al migrar código de captura de pantalla de UWP a WinUI 3 (SDK de Aplicaciones para Windows), tenga en cuenta las siguientes diferencias:
- Window handle initialization : selectores como GraphicsCapturePicker y FileSavePicker debe inicializarse con el identificador de ventana mediante InitializeWithWindow. Para obtener más información, consulta Recuperar un identificador de ventana (HWND) .
- API de composición en el subproceso de interfaz de usuario : en WinUI 3, las operaciones de superficie CanvasComposition (por ejemplo, dibujar en compositionDrawingSurface) deben enviarse al subproceso de interfaz de usuario mediante DispatcherQueue.TryEnqueue. La captura de fotogramas y la creación del mapa de bits pueden realizarse en el subproceso en segundo plano del grupo de fotogramas, pero la actualización del elemento visual de composición debe realizarse en el subproceso de la interfaz de usuario.
-
Cambios en el espacio de nombres — Use
Microsoft.UI.Composition,Microsoft.UI.Xaml.HostingyMicrosoft.UI.Dispatchingen lugar de sus equivalentes deWindows.UI. El espacio de nombresWindows.Graphics.Capturepermanece sin cambios.