Snímek obrazovky

Obor názvů Windows.Graphics.Capture poskytuje rozhraní API pro získávání snímků z obrazovky nebo okna aplikace a pro vytváření video streamů nebo momentek k vytváření prostředí podporujících spolupráci a interakci.

Díky zachycení obrazovky můžou vývojáři vyvolat zabezpečené systémové uživatelské rozhraní pro koncové uživatele, aby vybrali okno zobrazení nebo aplikace, které se má zachytit, a systém kolem aktivně zachycené položky vykreslil žluté ohraničení oznámení. V případě více souběžných relací snímání se kolem každé snímané položky zobrazí žlutý okraj.

Note

Rozhraní API pro zachycení obrazovky jsou podporována pouze na stolních zařízeních se systémem Windows a na náhlavních soupravách pro imerzivní prostředí Windows Mixed Reality.

Tento článek popisuje zachycení jednoho obrázku okna zobrazení nebo aplikace.

Kontrola podpory zachycení obrazovky

Než se pokusíte zachytit, zkontrolujte, jestli aktuální zařízení podporuje zachycení obrazovky. Pomocí metody IsSupported v GraphicsCaptureSession určete, jestli je k dispozici zachycení obrazovky:

// 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;
}

Snímek obrazovky nemusí být podporovaný z několika důvodů, včetně toho, jestli zařízení nesplňuje požadavky na hardware.

Spuštění systémového uživatelského rozhraní pro spuštění snímku obrazovky

K vyvolání uživatelského rozhraní nástroje pro výběr systému použijte třídu GraphicsCapturePicker . Koncový uživatel používá toto uživatelské rozhraní k výběru okna zobrazení nebo aplikace, které se má zachytit. Nástroj pro výběr vrací GraphicsCaptureItem, která se používá k vytvoření relace snímání.

V aplikaci WinUI 3 musíte před voláním PickSingleItemAsync inicializovat selektor pomocí popisovače okna:

// 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);
}

Vytvořte fond rámců pro zachytávání a relaci zachytávání

Pomocí GraphicsCaptureItem vytvořte Direct3D11CaptureFramePool pomocí svého zařízení D3D, podporovaného formátu pixelu (DXGI_FORMAT_B8G8R8A8_UNORM), požadovaného počtu snímků (který může být libovolné celé číslo) a velikosti snímku. Vlastnost Size Třídy GraphicsCaptureItem lze použít jako velikost rámce:

// Create frame pool and capture session
_framePool = Direct3D11CaptureFramePool.Create(
    _canvasDevice,
    CaptureDirectXPixelFormat.B8G8R8A8UIntNormalized,
    BufferCount,
    item.Size);
_session = _framePool.CreateCaptureSession(item);

Note

V systémech s povolenou barvou Windows HD nemusí být formát pixelů obsahu nutně DXGI_FORMAT_B8G8R8A8_UNORM. Chcete-li při zachytávání obsahu HDR zabránit nadměrnému ořezu pixelů (tj. zachycený obsah vypadá vyšisovaně), zvažte použití formátu DXGI_FORMAT_R16G16B16A16_FLOAT pro všechny komponenty v celém řetězci zachytávání, včetně Direct3D11CaptureFramePool a cílového objektu, jako je například CanvasBitmap. V závislosti na potřebě může být vyžadováno další zpracování, jako je uložení do formátu obsahu HDR nebo mapování tónu HDR-to-SDR. Tento článek se zaměřuje na zachytávání obsahu SDR. Další informace najdete v tématu Použití rozhraní DirectX s vysokým dynamickým rozsahem zobrazení a pokročilou barvou.

Jakmile uživatel explicitně udělí souhlas se zachycením okna aplikace nebo zobrazením v systémovém uživatelském rozhraní, může být graphicsCaptureItem přidružen k více relacím zachycení. Díky tomu se vaše aplikace může rozhodnout zachytit stejnou položku pro různá prostředí.

Pořídit snímky

Když máte vytvořený fond rámců a relaci zachycení, zavolejte StartCapture u instance GraphicsCaptureSession, aby se systému oznámilo, že má do vaší aplikace začít odesílat zachycené snímky.

Chcete-li získat tyto zachycené snímky, což jsou objekty Direct3D11CaptureFrame, použijte událost Direct3D11CaptureFramePool.FrameArrived:

// Handle frame arrival
_framePool.FrameArrived += OnFrameArrived;

Doporučujeme se vyhnout náročné práci na vlákně uživatelského rozhraní pro FrameArrived, protože tato událost se aktivuje pokaždé, když je k dispozici nový rámec. Pokud se rozhodnete naslouchat FrameArrived ve vlákně uživatelského rozhraní, mějte na paměti, kolik práce provádíte při každém spuštění události.

Případně můžete ručně vyžádat snímky pomocí metody Direct3D11CaptureFramePool.TryGetNextFrame , dokud nedostanete všechny potřebné snímky.

Objekt Direct3D11CaptureFrame obsahuje vlastnosti ContentSize, Surface a SystemRelativeTime. SystemRelativeTime je čas QPC (QueryPerformanceCounter), který lze použít k synchronizaci jiných prvků médií.

Procesní snímky zachytávání

Každý snímek z Direct3D11CaptureFramePool je vyzvednut při volání TryGetNextFrame a vrácen zpět v závislosti na životnosti objektu Direct3D11CaptureFrame. U spravovaných aplikací se doporučuje použít metodu Direct3D11CaptureFrame.Dispose . Direct3D11CaptureFrame implementuje IDisposable, takže po uvolnění snímku se vyrovnávací paměť vrátí do fondu.

Aplikace by neměly ukládat odkazy na objekty Direct3D11CaptureFrame ani na podkladový povrch Direct3D po vrácení snímku zpět.

V tomto příkladu se každý rámec převede na mapu CanvasBitmap, která je součástí knihovny Win2D :

// Convert frame to Win2D bitmap and display
CanvasBitmap canvasBitmap = CanvasBitmap.CreateFromDirect3D11Surface(
    _canvasDevice,
    frame.Surface);

Podkladový povrch Direct3D má vždy velikost určenou při vytvoření (nebo znovuvytvoření) objektu Direct3D11CaptureFramePool. Pokud je obsah větší než rámec, obsah se ořízne na velikost rámečku. Pokud je obsah menší než rámec, zbytek rámce obsahuje nedefinovaná data. Doporučuje se, aby aplikace zkopírovaly podobdélníkovou oblast pomocí vlastnosti ContentSize daného objektu Direct3D11CaptureFrame, aby se zabránilo zobrazení nedefinovaného obsahu.

Uložení snímku obrazovky

Jakmile budete mít mapu CanvasBitmap, můžete ji uložit jako soubor obrázku. Následující příklad uloží aktuální rámec jako soubor PNG pomocí FileSavePicker. V aplikaci WinUI 3 musíte inicializovat výběr pomocí úchytu okna:

// 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);
}

Reakce na změnu velikosti položky nebo ztráty zařízení

Během procesu snímání mohou aplikace chtít změnit některé vlastnosti svého Direct3D11CaptureFramePool. To zahrnuje vytvoření nového zařízení Direct3D, změnu velikosti bufferů snímku nebo dokonce změnu počtu bufferů v poolu. V každém z těchto scénářů je doporučeným postupem metoda Recreate u objektu Direct3D11CaptureFramePool .

Při opětovném vytvoření se všechny existující rámce zahodí. Tím zabráníte předání snímků, jejichž podkladové povrchy Direct3D patří do zařízení, ke kterému už aplikace nemá přístup. Z tohoto důvodu může být rozumné zpracovat všechny nevyřízené rámce před voláním Znovu vytvořit.

Důležité informace o WinUI 3

Při migraci kódu zachycení obrazovky z UPW na WinUI 3 (Windows App SDK) mějte na paměti následující rozdíly:

  • Inicializace popisovače okna — Nástroje pro výběr, jako jsou GraphicsCapturePicker a FileSavePicker, musí být inicializovány pomocí popisovače okna prostřednictvím InitializeWithWindow. Další informace najdete v tématu Získání úchytu okna (HWND).
  • Rozhraní API pro kompozici ve vlákně uživatelského rozhraní — Ve WinUI 3 musí být operace s povrchem CanvasComposition (například kreslení do CompositionDrawingSurface) odesílány ke zpracování do vlákna uživatelského rozhraní pomocí DispatcherQueue.TryEnqueue. Vytváření snímků a rastrových obrázků může probíhat ve vlákně pozadí fondu snímků, ale aktualizace vizuálu složení musí proběhnout ve vlákně uživatelského rozhraní.
  • změny Namespace — Použijte Microsoft.UI.Composition, Microsoft.UI.Xaml.Hosting a Microsoft.UI.Dispatching místo jejich protějšků Windows.UI. Obor názvů Windows.Graphics.Capture zůstane beze změny.

Viz také