Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Lo spazio dei nomi Windows.Graphics.Capture fornisce API per acquisire fotogrammi da uno schermo o dalla finestra di un'applicazione, per creare flussi video o istantanee con cui realizzare esperienze collaborative e interattive.
Con l'acquisizione dello schermo, gli sviluppatori richiamano l'interfaccia utente di sistema sicura per consentire agli utenti finali di selezionare la finestra di visualizzazione o dell'applicazione da acquisire e un bordo di notifica giallo viene disegnato dal sistema intorno all'elemento acquisito attivamente. Nel caso di più sessioni di acquisizione simultanee, viene disegnato un bordo giallo intorno a ogni elemento acquisito.
Annotazioni
Le API di acquisizione dello schermo sono supportate solo su dispositivi desktop Windows e visori immersivi Windows Mixed Reality.
Questo articolo descrive l'acquisizione di una singola immagine della finestra di visualizzazione o applicazione.
Verificare il supporto per l'acquisizione dello schermo
Prima di tentare l'acquisizione, verificare se il dispositivo corrente supporta l'acquisizione dello schermo. Usare il metodo IsSupported in GraphicsCaptureSession per determinare se l'acquisizione dello schermo è disponibile:
// 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;
}
Esistono diversi motivi per cui l'acquisizione dello schermo potrebbe non essere supportata, tra cui se il dispositivo non soddisfa i requisiti hardware.
Avviare l'interfaccia utente di sistema per avviare l'acquisizione della schermata
Usare la classe GraphicsCapturePicker per richiamare l'interfaccia utente del selettore di sistema. L'utente finale utilizza questa interfaccia utente per selezionare lo schermo o la finestra dell'applicazione da acquisire. La selezione restituisce un elemento GraphicsCaptureItem utilizzato per creare una sessione di acquisizione.
In un'app WinUI 3, è necessario inizializzare il controllo di selezione con l'handle della finestra prima di chiamare 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);
}
Creare un pool di frame di cattura e una sessione di acquisizione
Usando GraphicsCaptureItem, creare un oggetto Direct3D11CaptureFramePool con il dispositivo D3D, un formato pixel supportato (DXGI_FORMAT_B8G8R8A8_UNORM), un numero di fotogrammi desiderati (che può essere qualsiasi numero intero) e le dimensioni del fotogramma. La proprietà Size della classe GraphicsCaptureItem può essere usata come dimensione del frame:
// Create frame pool and capture session
_framePool = Direct3D11CaptureFramePool.Create(
_canvasDevice,
CaptureDirectXPixelFormat.B8G8R8A8UIntNormalized,
BufferCount,
item.Size);
_session = _framePool.CreateCaptureSession(item);
Annotazioni
Nei sistemi con Colore HD di Windows abilitato, il formato dei pixel del contenuto potrebbe non essere necessariamente DXGI_FORMAT_B8G8R8A8_UNORM. Per evitare la sovrasaturazione dei pixel (ossia che il contenuto acquisito appaia slavato) durante l'acquisizione di contenuto HDR, è consigliabile utilizzare DXGI_FORMAT_R16G16B16A16_FLOAT per ogni componente della pipeline di acquisizione, inclusi Direct3D11CaptureFramePool e la destinazione di output, ad esempio CanvasBitmap. A seconda della necessità, potrebbe essere necessaria un'ulteriore elaborazione, ad esempio il salvataggio in formato di contenuto HDR o il mapping del tono HDR-to-SDR. Questo articolo è incentrato sull'acquisizione di contenuto SDR. Per altre informazioni, vedere Uso di DirectX con schermi a intervalli dinamici elevati e colori avanzati.
Dopo che l'utente ha concesso esplicitamente il consenso per acquisire una finestra dell'applicazione o visualizzare nell'interfaccia utente di sistema, GraphicsCaptureItem può essere associato a più sessioni di acquisizione. In questo modo l'applicazione può scegliere di acquisire lo stesso elemento per diverse esperienze.
Acquisisci fotogrammi
Dopo aver creato il pool di frame e la sessione di acquisizione, chiamare StartCapture nell'istanza graphicsCaptureSession per notificare al sistema di iniziare a inviare fotogrammi di acquisizione all'app.
Per acquisire questi fotogrammi di acquisizione, che sono oggetti Direct3D11CaptureFrame , usare l'evento Direct3D11CaptureFramePool.FrameArrived :
// Handle frame arrival
_framePool.FrameArrived += OnFrameArrived;
È consigliabile evitare di eseguire un lavoro pesante sul thread dell'interfaccia utente per FrameArrived, perché questo evento viene generato ogni volta che è disponibile un nuovo frame. Se si sceglie di ascoltare FrameArrived nel thread dell'interfaccia utente, tenere presente quanto lavoro si sta facendo ogni volta che viene generato l'evento.
In alternativa, è possibile eseguire manualmente il pull dei fotogrammi con il metodo Direct3D11CaptureFramePool.TryGetNextFrame fino a ottenere tutti i fotogrammi necessari.
L'oggetto Direct3D11CaptureFrame contiene le proprietà ContentSize, Surface e SystemRelativeTime. Il SystemRelativeTime è il tempo QPC (QueryPerformanceCounter) che può essere utilizzato per sincronizzare altri elementi multimediali.
Elaborare i fotogrammi acquisiti
Ogni fotogramma di Direct3D11CaptureFramePool viene prelevato quando si chiama TryGetNextFrame e viene restituito in base al ciclo di vita dell'oggetto Direct3D11CaptureFrame. Per le applicazioni gestite, è consigliabile usare il metodo Direct3D11CaptureFrame.Dispose . Direct3D11CaptureFrame implementa IDisposable, quindi l'eliminazione del frame restituisce il buffer al pool.
Le applicazioni non devono conservare riferimenti agli oggetti Direct3D11CaptureFrame, né devono conservare riferimenti alla superficie Direct3D sottostante dopo che il frame è stato restituito.
In questo esempio ogni frame viene convertito in canvasBitmap, che fa parte della libreria Win2D :
// Convert frame to Win2D bitmap and display
CanvasBitmap canvasBitmap = CanvasBitmap.CreateFromDirect3D11Surface(
_canvasDevice,
frame.Surface);
La superficie Direct3D sottostante è sempre la dimensione specificata durante la creazione o la ricreazione di Direct3D11CaptureFramePool. Se il contenuto è maggiore del frame, il contenuto viene ritagliato in base alle dimensioni del frame. Se il contenuto è inferiore al frame, il resto del frame contiene dati non definiti. È consigliabile che le applicazioni copiano una sottosezione usando la proprietà ContentSize per direct3D11CaptureFrame per evitare di visualizzare contenuto non definito.
Salva uno screenshot
Dopo aver creato un oggetto CanvasBitmap, è possibile salvarlo come file di immagine. L'esempio seguente salva il frame corrente come file PNG usando un FileSavePicker. In un'app WinUI 3, è necessario inizializzare il selettore con l'handle della finestra:
// 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);
}
Reagire per acquisire il ridimensionamento o la perdita del dispositivo
Durante il processo di acquisizione, le applicazioni possono voler modificare gli aspetti di Direct3D11CaptureFramePool. Ciò include la fornitura di un nuovo dispositivo Direct3D, la modifica delle dimensioni dei buffer dei frame o anche la modifica del numero di buffer all'interno del pool. In ognuno di questi scenari, il metodo Recreate nell'oggetto Direct3D11CaptureFramePool è l'approccio consigliato.
Quando viene chiamato Ricrea , tutti i fotogrammi esistenti vengono eliminati. Ciò impedisce di distribuire fotogrammi le cui superfici Direct3D sottostanti appartengono a un dispositivo a cui l'applicazione potrebbe non avere più accesso. Per questo motivo, può essere opportuno elaborare tutti i fotogrammi in sospeso prima di chiamare Ricrea.
Considerazioni su WinUI 3
Quando si esegue la migrazione del codice di acquisizione dello schermo da UWP a WinUI 3 (SDK per app di Windows), tenere presenti le differenze seguenti:
- Inizializzazione dell'handle di finestra — Selettori come GraphicsCapturePicker e FileSavePicker devono essere inizializzati con l'handle della finestra tramite InitializeWithWindow. Per altre info, vedi Recuperare un handle di finestra (HWND).
- API di composizione nel thread dell'interfaccia utente : in WinUI 3 le operazioni sulla superficie CanvasComposition (ad esempio il disegno in compositionDrawingSurface) devono essere inviate al thread dell'interfaccia utente usando DispatcherQueue.TryEnqueue. L'acquisizione dei frame e la creazione di bitmap possono avvenire nel thread in background del frame pool, ma l'aggiornamento della visuale di composizione deve avvenire nel thread dell'interfaccia utente.
-
Modifiche allo spazio dei nomi — usare
Microsoft.UI.Composition,Microsoft.UI.Xaml.HostingeMicrosoft.UI.Dispatchingal posto delle rispettive contropartiWindows.UI. Lo spazio dei nomiWindows.Graphics.Capturerimane invariato.