File: Screenshot\Screenshot.uwp.cs
Web Access
Project: src\src\Essentials\src\Essentials.csproj (Microsoft.Maui.Essentials)
using System;
using System.IO;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.Graphics.Imaging;
using Windows.Storage.Streams;
using Microsoft.Maui.ApplicationModel;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Media.Imaging;
using Microsoft.UI.Xaml.Controls;
 
namespace Microsoft.Maui.Media
{
	partial class ScreenshotImplementation : IPlatformScreenshot, IScreenshot
	{
		public bool IsCaptureSupported =>
			true;
 
		public Task<IScreenshotResult> CaptureAsync()
		{
			var element = WindowStateManager.Default.GetActiveWindow(true);
 
			return CaptureAsync(element);
		}
 
		public Task<IScreenshotResult> CaptureAsync(Window window) =>
			CaptureAsync(window.Content);
 
		public async Task<IScreenshotResult> CaptureAsync(UIElement element)
		{
			if (element is WebView2 webView)
			{
				InMemoryRandomAccessStream stream = new();
				await webView.CoreWebView2.CapturePreviewAsync(Web.WebView2.Core.CoreWebView2CapturePreviewImageFormat.Png, stream);
 
				BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
				PixelDataProvider provider = await decoder.GetPixelDataAsync();
				byte[] byteArray = provider.DetachPixelData();
 
				return new ScreenshotResult((int)decoder.PixelWidth, (int)decoder.PixelHeight, byteArray, decoder.DpiX, decoder.DpiY);
			}
			else
			{
				var bmp = new RenderTargetBitmap();
 
				// NOTE: Return to the main thread so we can access view properties such as
				//       width and height. Do not ConfigureAwait!
				await bmp.RenderAsync(element);
 
				// get the view information first
				var width = bmp.PixelWidth;
				var height = bmp.PixelHeight;
 
				// then potentially move to a different thread
				IBuffer pixels = await bmp.GetPixelsAsync().AsTask().ConfigureAwait(false);
 
				return new ScreenshotResult(width, height, pixels);
			}
		}
	}
 
	partial class ScreenshotResult
	{
		readonly double _dpiX;
		readonly double _dpiY;
		readonly byte[] _bytes;
 
		internal ScreenshotResult(int width, int height, byte[] bytes, double dpiX, double dpiY)
		{
			Width = width;
			Height = height;
			_bytes = bytes;
			_dpiX = dpiX;
			_dpiY = dpiY;
		}
 
		public ScreenshotResult(int width, int height, IBuffer pixels)
		{
			Width = width;
			Height = height;
			_bytes = pixels.ToArray() ?? throw new ArgumentNullException(nameof(pixels));
			_dpiX = 96;
			_dpiY = 96;
		}
 
		async Task<Stream> PlatformOpenReadAsync(ScreenshotFormat format, int quality)
		{
			var ms = new InMemoryRandomAccessStream();
			await EncodeAsync(format, ms).ConfigureAwait(false);
			return ms.AsStreamForRead();
		}
 
		Task PlatformCopyToAsync(Stream destination, ScreenshotFormat format, int quality)
		{
			var ms = destination.AsRandomAccessStream();
			return EncodeAsync(format, ms);
		}
 
		Task<byte[]> PlatformToPixelBufferAsync() =>
			Task.FromResult(_bytes);
 
		async Task EncodeAsync(ScreenshotFormat format, IRandomAccessStream ms)
		{
			var f = ToBitmapEncoder(format);
 
			var encoder = await BitmapEncoder.CreateAsync(f, ms).AsTask().ConfigureAwait(false);
			encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)Width, (uint)Height, _dpiX, _dpiY, _bytes);
			await encoder.FlushAsync().AsTask().ConfigureAwait(false);
		}
 
		static Guid ToBitmapEncoder(ScreenshotFormat format) =>
			format switch
			{
				ScreenshotFormat.Jpeg => BitmapEncoder.JpegEncoderId,
				ScreenshotFormat.Png => BitmapEncoder.PngEncoderId,
				_ => throw new ArgumentOutOfRangeException(nameof(format))
			};
	}
}