添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
纯真的保温杯  ·  Android ...·  9 月前    · 
深情的脆皮肠  ·  c fwrite fread-掘金·  1 年前    · 
聪明伶俐的单杠  ·  博士后招聘 / ...·  1 年前    · 

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement . We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Description

In WinUI you can call RenderTargetBitmap.RenderAsync(element) to render a screenshot of an element to a bitmap, and then you can save that bitmap somewhere (for example, as a PNG on disk).

When there's a WebView2 in the control tree, the contents of the WebView2 are completely blank, though everything else in the image looks fine.

Version
SDK: Windows App SDK 1.1.5
Runtime: 105.0.1343.33
Framework: WinUI
OS: Win11

Repro Steps

Create a new empty WinUI3 app and put this code in MainWindow.xaml.cs :

    public sealed partial class MainWindow : Window
        WebView2 _wv;
        public MainWindow()
            var b = new Button { Content = new TextBlock { Text = "Do screenshot" } };
            b.Click += OnScreenshotClick;
            _wv = new WebView2 { Source = new Uri("https://bing.com"), Height=400, Width=400 };
            var sp = new StackPanel() { Orientation = Orientation.Vertical };
            sp.Children.Add(b);
            sp.Children.Add(_wv);
            Content = sp;
        private async void OnScreenshotClick(object sender, RoutedEventArgs e)
            var rootPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            await CaptureAsync(Content, Path.Combine(rootPath, "WindowContent.png"));
            await CaptureAsync(_wv, Path.Combine(rootPath, "WebView.png"));
            var messageDialog = new MessageDialog($"Screenshots saved to: {rootPath}");
            messageDialog.Commands.Add(new UICommand("OK"));
            InitializeWithWindow.Initialize(messageDialog, WindowNative.GetWindowHandle(this));
            await messageDialog.ShowAsync();
        public static async Task CaptureAsync(UIElement element, string destination)
            var bmp = new RenderTargetBitmap();
            await bmp.RenderAsync(element);
            // get the view information first
            var width = bmp.PixelWidth;
            var height = bmp.PixelHeight;
            // then potentially move to a different thread
            var pixels = await bmp.GetPixelsAsync();
            using FileStream fileStream = new FileStream(destination, FileMode.Create);
            var ms = fileStream.AsRandomAccessStream();
            var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, ms);
            encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)width, (uint)height, 96, 96, pixels.ToArray());
            await encoder.FlushAsync();

And then run the app, and click the button in the app.

On my machine it produces two screenshots:

  • Just the WebView2 (blank rectangle):
    WebView
  • The whole app's main window's contents, which has content, except for the blank WebView2 (valid screenshot, except bottom right is blank gray rectangle):
    WindowContent
  • Originally reported in .NET MAUI: dotnet/maui#9718

    AB#41360109

    @Eilon The WebView2 provides a "CapturePreviewAsync" function which will create a PNG of the web contents. Sounds like the WinUI control would need to incorporate that (or some other mechanism) for RenderAsync. I'm opening a bug for this issue, and we'll ask the WinUI team to take a first look. Thanks!

    I do believe that this is an MAUI issue, but since that one has been closed and locked, I will post my workaround here:

    I have implemented this for Windows, Android and iOS:

            public async Task<byte[]> GetScreenshot()
    #if WINDOWS
                using var ms = new MemoryStream();
                var webview = Handler.PlatformView as WebView2;
                await webview.CoreWebView2.CapturePreviewAsync(CoreWebView2CapturePreviewImageFormat.Jpeg, ms.AsRandomAccessStream());
                return ms.ToArray();
    #elif ANDROID
                using var ms = new MemoryStream();
                var webview = (Android.Webkit.WebView)Handler.PlatformView!;
                var bitmap = Bitmap.CreateBitmap(webview.Width, webview.Height, Bitmap.Config.Argb8888!)!;
                var canvas = new Canvas(bitmap);
                webview.Draw(canvas);
                await bitmap.CompressAsync(Bitmap.CompressFormat.Jpeg, 90, ms);
                return ms.ToArray();
    #elif IOS
                var webview = (WKWebView)Handler.PlatformView!;
                UIGraphics.BeginImageContextWithOptions(webview.Bounds.Size, true, 0);
                webview.DrawViewHierarchy(webview.Bounds, true);
                var jpegData = UIGraphics.GetImageFromCurrentImageContext().AsJPEG();
                byte[] dataBytes = new byte[jpegData.Length];
                System.Runtime.InteropServices.Marshal.Copy(jpegData.Bytes, dataBytes, 0, Convert.ToInt32(jpegData.Length));
                UIGraphics.EndImageContext();
                return dataBytes;
    #endif
                return null;
    

    Here are the necessary usings:

    #if IOS
    using UIKit;
    using WebKit;
    #endif
    #if ANDROID
    using Android.Graphics;
    using Path = System.IO.Path;
    #endif
    #if WINDOWS
    using Microsoft.UI.Xaml.Controls;
    using Microsoft.Web.WebView2.Core;
    #endif

    If you would like to use this now you can make your own class that inherits from BlazorWebView and add the above method to it.