Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Obszar nazw Windows.Graphics.Capture udostępnia interfejsy API umożliwiające przechwytywanie klatek z wyświetlacza lub okna aplikacji w celu tworzenia strumieni wideo lub migawek oraz tworzenia rozwiązań do współpracy i środowisk interaktywnych.
Podczas przechwytywania ekranu deweloperzy wywołują bezpieczny interfejs użytkownika systemu, aby użytkownicy końcowi mogli wybrać ekran lub okno aplikacji do przechwycenia, a system wyświetla żółtą ramkę powiadomienia wokół aktualnie przechwytywanego elementu. W przypadku wielu równoczesnych sesji przechwytywania wokół każdego przechwytywanego elementu jest wyświetlane żółte obramowanie.
Note
Interfejsy API przechwytywania ekranu są obsługiwane tylko na komputerach stacjonarnych z systemem Windows oraz na goglach immersyjnych Windows Mixed Reality.
W tym artykule opisano przechwytywanie pojedynczego obrazu okna wyświetlania lub aplikacji.
Sprawdzanie obsługi przechwytywania ekranu
Przed podjęciem próby przechwycenia sprawdź, czy bieżące urządzenie obsługuje przechwytywanie ekranu. Użyj metody IsSupported w pliku GraphicsCaptureSession , aby określić, czy przechwytywanie ekranu jest dostępne:
// 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;
}
Istnieje kilka powodów, dla których przechwytywanie ekranu może nie być obsługiwane, w tym jeśli urządzenie nie spełnia wymagań sprzętowych.
Uruchom interfejs użytkownika systemu, aby rozpocząć przechwytywanie ekranu
Użyj klasy GraphicsCapturePicker , aby wywołać interfejs użytkownika selektora systemu. Użytkownik końcowy używa tego interfejsu użytkownika do wybrania okna wyświetlania lub aplikacji do przechwycenia. Selektor zwraca element GraphicsCaptureItem używany do tworzenia sesji przechwytywania.
W aplikacji WinUI 3 należy zainicjować selektor za pomocą uchwytu okna przed wywołaniem polecenia 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);
}
Utwórz pulę ramek przechwytywania i sesję przechwytywania
Używając obiektu GraphicsCaptureItem, utwórz obiekt Direct3D11CaptureFramePool przy użyciu urządzenia D3D, obsługiwanego formatu pikseli (DXGI_FORMAT_B8G8R8A8_UNORM), żądanej liczby ramek (może to być dowolna liczba całkowita) oraz rozmiaru ramki. Właściwość Size klasy GraphicsCaptureItem może służyć jako rozmiar ramki:
// Create frame pool and capture session
_framePool = Direct3D11CaptureFramePool.Create(
_canvasDevice,
CaptureDirectXPixelFormat.B8G8R8A8UIntNormalized,
BufferCount,
item.Size);
_session = _framePool.CreateCaptureSession(item);
Note
W systemach z włączoną funkcją Windows HD Color format pikseli treści niekoniecznie musi być DXGI_FORMAT_B8G8R8A8_UNORM. Aby uniknąć nadmiernego obcinania pikseli (tj. przechwycona zawartość sprawia wrażenie wyblakłej) podczas przechwytywania zawartości HDR, rozważ użycie formatu DXGI_FORMAT_R16G16B16A16_FLOAT we wszystkich składnikach potoku przechwytywania, w tym w Direct3D11CaptureFramePool oraz w obiekcie docelowym, takim jak CanvasBitmap. W zależności od potrzeb może być wymagane dodatkowe przetwarzanie, takie jak zapisywanie w formacie zawartości HDR lub mapowanie tonu HDR-to-SDR. Ten artykuł koncentruje się na przechwytywaniu zawartości SDR. Aby uzyskać więcej informacji, zobacz Using DirectX with high dynamic range displays and advanced color (Używanie funkcji DirectX z wyświetlaczami o wysokim zakresie dynamicznym i kolorem zaawansowanym).
Gdy użytkownik jawnie wyraził zgodę na przechwytywanie okna aplikacji lub wyświetlania w interfejsie użytkownika systemu, element GraphicsCaptureItem może być skojarzony z wieloma sesjami przechwytywania. Dzięki temu aplikacja może zdecydować o przechwytywaniu tego samego elementu na potrzeby różnych środowisk użytkownika.
Uzyskiwanie ramek przechwytywania
Po utworzeniu puli ramek i sesji przechwytywania wywołaj metodę StartCapture na instancji GraphicsCaptureSession, aby powiadomić system o rozpoczęciu wysyłania przechwyconych ramek do aplikacji.
Aby uzyskać te ramki przechwytywania, będące obiektami Direct3D11CaptureFrame, użyj zdarzenia Direct3D11CaptureFramePool.FrameArrived:
// Handle frame arrival
_framePool.FrameArrived += OnFrameArrived;
Zaleca się unikanie wykonywania ciężkiej pracy w wątku interfejsu użytkownika dla elementu FrameArrived, ponieważ to zdarzenie jest uruchamiane za każdym razem, gdy jest dostępna nowa ramka. Jeśli zdecydujesz się słuchać FrameArrived w wątku interfejsu użytkownika, należy pamiętać o tym, ile pracy wykonujesz za każdym razem, gdy zdarzenie jest uruchamiane.
Alternatywnie możesz ręcznie ściągnąć ramki za pomocą metody Direct3D11CaptureFramePool.TryGetNextFrame , dopóki nie uzyskasz wszystkich potrzebnych ramek.
Obiekt Direct3D11CaptureFrame zawiera właściwości ContentSize, Surface i SystemRelativeTime. SystemRelativeTime to czas QPC (QueryPerformanceCounter), który może służyć do synchronizowania innych elementów multimedialnych.
Przetwarzanie ramek przechwytywania
Każda ramka z puli Direct3D11CaptureFramePool jest pobierana przy wywołaniu TryGetNextFrame, a następnie zwracana do puli zależnie od cyklu życia obiektu Direct3D11CaptureFrame. W przypadku aplikacji zarządzanych zaleca się użycie metody Direct3D11CaptureFrame.Dispose . Direct3D11CaptureFrame implementuje interfejs IDisposable, więc zwolnienie ramki powoduje zwrócenie buforu do puli.
Aplikacje nie powinny przechowywać odwołań do obiektów Direct3D11CaptureFrame ani odwołań do bazowej powierzchni Direct3D po zwróceniu ramki.
W tym przykładzie każda ramka jest konwertowana na mapę CanvasBit, która jest częścią biblioteki Win2D :
// Convert frame to Win2D bitmap and display
CanvasBitmap canvasBitmap = CanvasBitmap.CreateFromDirect3D11Surface(
_canvasDevice,
frame.Surface);
Bazowa powierzchnia Direct3D ma zawsze rozmiar określony podczas tworzenia (lub ponownego tworzenia) elementu Direct3D11CaptureFramePool. Jeśli zawartość jest większa niż ramka, zawartość zostanie obcięta do rozmiaru ramki. Jeśli zawartość jest mniejsza niż ramka, pozostała część ramki zawiera niezdefiniowane dane. Zaleca się, aby aplikacje kopiowały podreplikację przy użyciu właściwości ContentSize dla tej ramki Direct3D11CaptureFrame , aby uniknąć wyświetlania niezdefiniowanej zawartości.
Zapisywanie zrzutu ekranu
Po utworzeniu mapy CanvasBit możesz zapisać ją jako plik obrazu. Poniższy przykład zapisuje bieżącą ramkę jako plik PNG przy użyciu FileSavePicker. W aplikacji WinUI 3 należy zainicjować selektor za pomocą uchwytu 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);
}
Reagowanie na zmianę rozmiaru elementu przechwytywania lub utratę urządzenia
Podczas przechwytywania aplikacje mogą chcieć zmienić właściwości swojej puli Direct3D11CaptureFramePool. Obejmuje to udostępnienie nowego urządzenia Direct3D, zmianę rozmiaru buforów ramek, a nawet zmianę liczby buforów w puli. W każdym z tych scenariuszy zalecana jest metoda Recreate w obiekcie Direct3D11CaptureFramePool .
Po wywołaniu funkcji Ponowne tworzenie zostaną odrzucone wszystkie istniejące ramki. Zapobiega to rozdaniu ramek, których bazowe powierzchnie Direct3D należą do urządzenia, do którego aplikacja może już nie mieć dostępu. Z tego powodu warto przetworzyć wszystkie oczekujące ramki przed wywołaniem funkcji Recreate.
Zagadnienia dotyczące interfejsu WinUI 3
Podczas migrowania kodu przechwytywania ekranu z platformy UWP do systemu WinUI 3 (Zestaw SDK do aplikacji systemu Windows) należy pamiętać o następujących różnicach:
- Inicjalizacja uchwytu okna — selektory, takie jak GraphicsCapturePicker i FileSavePicker, należy zainicjować przy użyciu uchwytu okna za pomocą InitializeWithWindow. Aby uzyskać więcej informacji, zobacz Pobieranie uchwytu okna (HWND).
- Interfejsy API Composition w wątku interfejsu użytkownika — w WinUI 3 operacje na powierzchni CanvasComposition (takie jak rysowanie na obiekcie CompositionDrawingSurface) muszą być przekazywane do wykonania w wątku interfejsu użytkownika za pomocą DispatcherQueue.TryEnqueue. Przechwytywanie ramek i tworzenie map bitowych może nastąpić w wątku tła puli ramek, ale aktualizacja wizualizacji kompozycji musi odbywać się w wątku interfejsu użytkownika.
-
Zmiany przestrzeni nazw — użyj
Microsoft.UI.Composition,Microsoft.UI.Xaml.HostingiMicrosoft.UI.Dispatchingzamiast ich odpowiednikówWindows.UI. Przestrzeń nazwWindows.Graphics.Capturepozostaje niezmieniona.
Zobacz także
- Przestrzeń nazw Windows.Graphics.Capture
- Win2D dla WinUI 3
- Pobierz uchwyt okna (HWND)
- Grafika — indeks funkcji programowania grafiki dla aplikacji Windows
- Przykłady grafiki DirectX w GitHub