Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
O espaço de nomes Windows.Graphics.Capture fornece APIs para capturar fotogramas de um ecrã ou de uma janela de aplicação, para criar fluxos de vídeo ou instantâneos e criar experiências colaborativas e interativas.
Com a captura de ecrã, os programadores invocam uma interface segura do sistema para que os utilizadores finais escolham a janela de ecrã ou aplicação a capturar, e uma borda amarela de notificação é desenhada pelo sistema em torno do item capturado ativamente. No caso de múltiplas sessões de captura simultâneas, é desenhada uma borda amarela em torno de cada item capturado.
Note
As APIs de captura de ecrã são suportadas apenas em dispositivos desktop Windows e headsets imersivos Windows Mixed Reality.
Este artigo descreve a captura de uma única imagem do ecrã ou da janela da aplicação.
Verifique se há suporte para captura de ecrã
Antes de tentar capturar, verifique se o dispositivo atual suporta captura de ecrã. Use o método IsSupported no GraphicsCaptureSession para determinar se a captura de ecrã está disponível:
// 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;
}
Existem várias razões pelas quais a captura de ecrã pode não ser suportada, incluindo se o dispositivo não cumprir os requisitos de hardware.
Inicie a interface do sistema para iniciar a captura de ecrã
Utilize a classe GraphicsCapturePicker para invocar a interface de utilizador do seletor do sistema. O utilizador final usa esta interface para selecionar a janela de ecrã ou aplicação a capturar. O seletor devolve um GraphicsCaptureItem que é usado para criar uma sessão de captura.
Numa aplicação WinUI 3, tem de inicializar o seletor com o manipulador da janela antes de chamar 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);
}
Crie um pool de frames de captura e uma sessão de captura
Usando o GraphicsCaptureItem, crie um Direct3D11CaptureFramePool com o seu dispositivo D3D, um formato de píxel suportado (DXGI_FORMAT_B8G8R8A8_UNORM), número de frames desejados (que pode ser qualquer número inteiro) e tamanho de frame. A propriedade Size da classe GraphicsCaptureItem pode ser usada como o tamanho do seu frame:
// Create frame pool and capture session
_framePool = Direct3D11CaptureFramePool.Create(
_canvasDevice,
CaptureDirectXPixelFormat.B8G8R8A8UIntNormalized,
BufferCount,
item.Size);
_session = _framePool.CreateCaptureSession(item);
Note
Em sistemas com a Cor HD do Windows ativada, o formato de píxel do conteúdo pode não ser, necessariamente, DXGI_FORMAT_B8G8R8A8_UNORM. Para evitar o recorte excessivo dos píxeis (ou seja, o conteúdo capturado parece desbotado) ao capturar conteúdo HDR, considere utilizar DXGI_FORMAT_R16G16B16A16_FLOAT em todos os componentes do pipeline de captura, incluindo o Direct3D11CaptureFramePool e o destino, como CanvasBitmap. Dependendo da necessidade, pode ser necessário processamento adicional, como guardar em formato de conteúdo HDR ou mapeamento tonal de HDR para SDR. Este artigo foca-se na captura de conteúdo SDR. Para mais informações, consulte Usar DirectX com ecrãs de alta gama dinâmica e cor avançada.
Uma vez que o utilizador tenha dado consentimento explícito para capturar uma janela ou exibição de uma aplicação na interface do sistema, o GraphicsCaptureItem pode ser associado a múltiplas sessões de captura. Desta forma, a sua aplicação pode escolher capturar o mesmo item para várias experiências.
Adquirir fotogramas de captura
Com o seu conjunto de frames e sessão de captura criados, chame StartCapture na sua instância de GraphicsCaptureSession para notificar o sistema para começar a enviar imagens de captura para a sua aplicação.
Para adquirir estes frames de captura, que são objetos Direct3D11CaptureFrame , utilize o evento Direct3D11CaptureFramePool.FrameArrived :
// Handle frame arrival
_framePool.FrameArrived += OnFrameArrived;
Recomenda-se evitar realizar operações pesadas no thread da interface para FrameArrived, pois este evento é acionado sempre que um novo frame fica disponível. Se optares por processar FrameArrived na thread da IU, tem em atenção a quantidade de trabalho que fazes de cada vez que o evento é acionado.
Alternativamente, podes puxar manualmente os frames com o método Direct3D11CaptureFramePool.TryGetNextFrame até conseguires todos os frames de que precisas.
O objeto Direct3D11CaptureFrame contém as propriedades ContentSize, Surface e SystemRelativeTime. O SystemRelativeTime é o tempo QPC (QueryPerformanceCounter) que pode ser usado para sincronizar outros elementos multimédia.
Quadros de captura de processos
Cada frame do Direct3D11CaptureFramePool é obtido ao chamar TryGetNextFrame e devolvido de acordo com o ciclo de vida do objeto Direct3D11CaptureFrame. Para aplicações geridas, recomenda-se usar o método Direct3D11CaptureFrame.Dispose . O Direct3D11CaptureFrame implementa o IDisposable, pelo que ao descartar o frame devolve o buffer ao pool.
As aplicações não devem guardar referências a objetos Direct3D11CaptureFrame , nem devem guardar referências à superfície Direct3D subjacente depois de o frame ter sido novamente registado.
Neste exemplo, cada frame é convertido num CanvasBitmap, que faz parte da biblioteca Win2D :
// Convert frame to Win2D bitmap and display
CanvasBitmap canvasBitmap = CanvasBitmap.CreateFromDirect3D11Surface(
_canvasDevice,
frame.Surface);
A superfície Direct3D subjacente tem sempre o tamanho especificado ao criar (ou recriar) o Direct3D11CaptureFramePool. Se o conteúdo for maior do que a moldura, o conteúdo é cortado ao tamanho da moldura. Se o conteúdo for menor do que o frame, então o resto do frame contém dados indefinidos. Recomenda-se que as aplicações copiem um sub-retângulo usando a propriedade ContentSize desse Direct3D11CaptureFrame para evitar a apresentação de conteúdo indefinido.
Guardar uma captura de ecrã
Depois de tiveres um CanvasBitmap, podes guardá-lo como ficheiro de imagem. O exemplo seguinte guarda o frame atual como ficheiro PNG usando um FileSavePicker. Numa aplicação WinUI 3, tens de inicializar o seletor com o handler da janela:
// 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);
}
Reagir para capturar o redimensionamento de itens ou dispositivo perdido
Durante o processo de captura, as aplicações podem desejar alterar aspetos do seu Direct3D11CaptureFramePool. Isto inclui fornecer um novo dispositivo Direct3D, alterar o tamanho dos buffers de frames ou até alterar o número de buffers dentro do pool. Em cada um destes cenários, o método Recriar no objeto Direct3D11CaptureFramePool é a abordagem recomendada.
Quando Recreate é invocado, todos os fotogramas existentes são descartados. Isto serve para evitar a distribuição de frames cujas superfícies Direct3D subjacentes pertencem a um dispositivo ao qual a aplicação já não tenha acesso. Por esta razão, pode ser sensato processar todos os fotogramas pendentes antes de chamar Recreate.
Considerações sobre o WinUI 3
Ao migrar código de captura de ecrã do UWP para o WinUI 3 (SDK de Aplicações Windows), tenha em conta as seguintes diferenças:
- Inicialização do identificador da janela — Seletores como GraphicsCapturePicker e FileSavePicker têm de ser inicializados com o identificador da janela através de InitializeWithWindow. Para mais informações, consulte Recuperar um identificador de janela (HWND).
- APIs de composição no thread UI — No WinUI 3, as operações de superfície CanvasComposition (como desenhar para um CompositionDrawingSurface) devem ser despachadas para o thread UI usando DispatcherQueue.TryEnqueue. A captura de frames e a criação de bitmap podem acontecer no thread de fundo do frame pool, mas a atualização do visual de composição tem de ser feita no thread da interface.
-
Alterações ao espaço de nomes — Utilize
Microsoft.UI.Composition,Microsoft.UI.Xaml.HostingeMicrosoft.UI.Dispatchingem vez dos equivalentes emWindows.UI. O espaço de nomesWindows.Graphics.Capturemantém-se inalterado.
Consulte também
- espaço de nomes Windows.Graphics.Capture
- Win2D para WinUI 3
- Recuperar um identificador de janela (HWND)
- Gráficos — Índice das funcionalidades de desenvolvimento gráfico para aplicações Windows
- Exemplos de Gráficos DirectX no GitHub
Windows developer