Képernyőfelvétel

A Windows. A Graphics.Capture névtér API-k segítségével képkockákat szerezhet be egy megjelenítési vagy alkalmazásablakból, és videostreameket vagy pillanatképeket hozhat létre az együttműködésen alapuló és interaktív élmények létrehozásához.

A képernyőrögzítéssel a fejlesztők biztonságos rendszerfelületet hívnak meg a végfelhasználók számára, hogy kiválasztják a rögzítendő megjelenítési vagy alkalmazásablakot, és a rendszer sárga értesítési szegélyt rajzol az aktívan rögzített elem köré. Több egyidejű rögzítési munkamenet esetén a rendszer sárga szegélyt rajzol az egyes rögzített elemek köré.

Megjegyzés

A képernyőrögzítési API-k csak Windows asztali eszközökön és Windows Mixed Reality modern headseteken támogatottak.

Ez a cikk a megjelenítési vagy alkalmazásablak egyetlen képének rögzítését ismerteti.

Képernyőrögzítés támogatásának ellenőrzése

A rögzítési kísérlet előtt ellenőrizze, hogy az aktuális eszköz támogatja-e a képernyőrögzítést. A GraphicsCaptureSessionIsSupported metódusával állapítsa meg, hogy elérhető-e képernyőrögzítés:

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

Több oka is lehet annak, hogy a képernyőrögzítés nem támogatott, például az, ha az eszköz nem felel meg a hardverkövetelményeknek.

Indítsa el a rendszer felhasználói felületét a képernyőrögzítés elindításához

A Rendszerválasztó felhasználói felületének meghívásához használja a GraphicsCapturePicker osztályt. A végfelhasználó ezzel a felhasználói felülettel választja ki a rögzítéshez használt megjelenítési vagy alkalmazásablakot. A picker visszaad egy GraphicsCaptureItem fájlt, amely egy rögzítési munkamenet létrehozásához használatos.

Egy WinUI 3-alkalmazásban a PickSingleItemAsync meghívása előtt inicializálnia kell a választót az ablakazonosítóval:

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

Rögzítési keretkészlet létrehozása és munkamenet rögzítése

A GraphicsCaptureItem használatával hozzon létre egy Direct3D11CaptureFramePoolt a D3D-eszközzel, egy támogatott képpontformátumot (DXGI_FORMAT_B8G8R8A8_UNORM), a kívánt keretek számát (amely akár egész szám is lehet) és a keret méretét. A GraphicsCaptureItem osztály Méret tulajdonsága a keret méreteként használható:

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

Megjegyzés

Ha a Windows HD szín engedélyezve van, előfordulhat, hogy a tartalom képpontformátuma nem feltétlenül DXGI_FORMAT_B8G8R8A8_UNORM. A HDR-tartalmak rögzítésekor a képponttúllépés (azaz a rögzített tartalom kimosódott) elkerülése érdekében fontolja meg a DXGI_FORMAT_R16G16B16A16_FLOAT használatát a rögzítési folyamat minden összetevőjéhez, beleértve a Direct3D11CaptureFramePoolt, a célhelyet, például a CanvasBitmap-ot. Az igénytől függően további feldolgozásra lehet szükség, például a HDR-tartalomformátumba való mentésre vagy a HDR-to-SDR tónusleképezésre. Ez a cikk az SDR-tartalmak rögzítésére összpontosít. További információ: A DirectX használata nagy dinamikatartományú kijelzőkkel és speciális színekkel.

Ha a felhasználó kifejezetten hozzájárult egy alkalmazásablak rögzítéséhez vagy a rendszer felhasználói felületén való megjelenítéshez, a GraphicsCaptureItem több rögzítési munkamenethez is társítható. Így az alkalmazás dönthet úgy, hogy ugyanazt az elemet rögzíti a különböző szolgáltatásokhoz.

Rögzítési keretek beszerzése

A keretkészlet létrehozása és a rögzítési munkamenet létrehozása után hívja meg a StartCapture-t a GraphicsCaptureSession-példányon , hogy értesítse a rendszert a rögzítési keretek alkalmazásba küldésének megkezdéséről.

A Direct3D11CaptureFrame objektumokat tartalmazó rögzítési keretek beszerzéséhez használja a Direct3D11CaptureFramePool.FrameArrived eseményt :

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

Javasoljuk, hogy kerülje a FrameArrived felhasználói felületi szálán végzett nehéz munkát, mivel ez az esemény minden alkalommal aktiválódik, amikor új keret áll rendelkezésre. Ha úgy dönt, hogy meghallgatja a FrameArrivedet a felhasználói felületen, ügyeljen arra, hogy mennyi munkát végez minden alkalommal, amikor az esemény kigyullad.

Másik lehetőségként manuálisan is lekérheti a kereteket a Direct3D11CaptureFramePool.TryGetNextFrame metódussal, amíg meg nem kapja az összes szükséges keretet.

A Direct3D11CaptureFrame objektum a ContentSize, Surface és SystemRelativeTime tulajdonságokat tartalmazza. A SystemRelativeTime a QPC (QueryPerformanceCounter) ideje, amely más médiaelemek szinkronizálására használható.

Folyamatrögzítési képkockák

A Direct3D11CaptureFramePool minden képkockája ki van véve a TryGetNextFrame hívásakor, és a Direct3D11CaptureFrame objektum élettartamának megfelelően vissza van jelentkezve. Felügyelt alkalmazások esetén ajánlott a Direct3D11CaptureFrame.Dispose metódus használata. A Direct3D11CaptureFrame implementálja az IDisposable-t, így a keret felszabadítása a puffert a készletbe adja vissza.

Az alkalmazások nem menthetik a Direct3D11CaptureFrame-objektumokra mutató hivatkozásokat, és nem menthetnek hivatkozásokat az alapul szolgáló Direct3D-felületre a keret visszavétele után.

Ebben a példában minden képkockát vászonbitképgé konvertálunk, amely a Win2D-kódtár része:

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

Az alapul szolgáló Direct3D-felület mindig a Direct3D11CaptureFramePool létrehozásakor (vagy újbóli létrehozásakor) megadott méretű. Ha a tartalom nagyobb, mint a keret, a tartalom a keret méretéhez lesz vágva. Ha a tartalom kisebb, mint a keret, akkor a keret többi része nem definiált adatokat tartalmaz. Javasoljuk, hogy az alkalmazások az adott Direct3D11CaptureFrameContentSize tulajdonságának használatával másoljanak ki egy részterületet, hogy elkerüljék a nem meghatározott tartalom megjelenítését.

Képernyőkép mentése

Miután létrehozta a CanvasBitmap-et, képfájlként mentheti. Az alábbi példa az aktuális keretet PNG-fájlként menti egy FileSavePicker használatával. WinUI 3-alkalmazásban a választóelemet az ablakazonosítóval kell inicializálni:

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

Reagáljon az elemek átméretezésére vagy az eszköz elveszett állapotának rögzítésére

A rögzítési folyamat során előfordulhat, hogy az alkalmazások módosítani szeretnék a Direct3D11CaptureFramePool funkcióit. Ez magában foglalja egy új Direct3D-eszköz biztosítását, a keretpufferek méretének módosítását, vagy akár a készleten belüli pufferek számának módosítását is. A fenti forgatókönyvek mindegyikében a Direct3D11CaptureFramePool objektum újbóli létrehozása metódusa a javasolt módszer.

A(z) Recreate meghívásakor az összes meglévő képkocka eldobásra kerül. Ennek célja, hogy megakadályozza azoknak a kereteknek a átadását, amelyek mögöttes Direct3D-felületei olyan eszközhöz tartoznak, amelyhez az alkalmazás már nem fér hozzá. Ezért érdemes lehet az összes függőben lévő keretet feldolgozni az Újrahívás meghívása előtt.

WinUI 3 szempontok

A képernyőrögzítési kód UWP-ről WinUI 3-ra (Windows App SDK) való migrálásakor tartsa szem előtt az alábbi különbségeket:

  • Ablakazonosító inicializálása — Az olyan választóelemeket, mint a GraphicsCapturePicker és a FileSavePicker, az ablakazonosítóval kell inicializálni a InitializeWithWindow használatával. További információért lásd: Ablakkezelő (HWND) lekérése.
  • A felhasználói felületi szál kompozíciós API-jait – a WinUI 3-ban a CanvasComposition felületi műveleteit (például a CompositionDrawingSurface-ra való rajzolást) a DispatcherQueue.TryEnqueue használatával kell elküldeni a felhasználói felületi szálra. A keretrögzítés és a bitkép létrehozása történhet a keretkészlet háttérszálán, de a kompozíciós vizualizáció frissítésének a felhasználói felületen kell történnie.
  • Névtér változásaiMicrosoft.UI.Composition, Microsoft.UI.Xaml.Hosting és Microsoft.UI.Dispatching használata a Windows.UI megfelelőik helyett. A Windows.Graphics.Capture névtér változatlan marad.

Lásd még