DEV Community

loading...

【.NET 5】【WPF】Print WebView2

Masui Masanori
Programmer, husband, father I love C#, TypeScript, etc.
・3 min read

Intro

In this time, I try setting print settings and print WebView2.

Printer settings

I can set printing settings like paper size, etc. by "PrintTicket".

using System.Printing;
using System.Windows.Media;
using System.Windows.Xps;

namespace PrintSample.Prints
{
    public class Printer: IPrinter
    {
        public void Print(Visual target)
        {
            LocalPrintServer printServer = new LocalPrintServer();
            PrintQueue queue = printServer.GetPrintQueue("Microsoft Print to PDF");

            PrintTicket ticket = queue.DefaultPrintTicket;
            ticket.PageMediaSize = new PageMediaSize(200d, 300d);
            // I can get defined paper sizes like "A3" by PageMediaSizeName
            // ticket.PageMediaSize = new PageMediaSize(PageMediaSizeName.ISOA3);

            ticket.CopyCount = 2;
            ticket.PageResolution = new PageResolution(72, 72);
            // Setting this value to Landscape reverses the "MediaSize" designation
            ticket.PageOrientation = PageOrientation.Landscape;
            // no margins
            ticket.PageBorderless = PageBorderless.Borderless;

            XpsDocumentWriter writer = PrintQueue.CreateXpsDocumentWriter(queue); 
            writer.Write(target, ticket);
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Print WebView2

Because I had been able to set a WebView2 instance as argument of XpsDocumentWriter.Write, I have thought I could print HTML of WebView2.

using System;
using System.Printing;
using System.Windows;
using System.Windows.Xps;
using Microsoft.Web.WebView2.Core;

namespace PdfPrintSample.Main
{
    public partial class MainWindow : Window
    {
        public MainWindow(MainViewModel viewModel)
        {
            DataContext = viewModel;
            InitializeComponent();
            InitializeAsync();
            webView.NavigationCompleted += NavigationCompleted;
        }
        private async void InitializeAsync()
        {
            await webView.EnsureCoreWebView2Async(null);
        }
        private async void NavigationCompleted(object? sender,
            CoreWebView2NavigationCompletedEventArgs args)
        {
            LocalPrintServer printServer = new LocalPrintServer();
            PrintQueue queue = printServer.GetPrintQueue("Microsoft Print to PDF");
            XpsDocumentWriter writer = PrintQueue.CreateXpsDocumentWriter(queue); 
            writer.Write(webView);
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

WPF

Alt Text

Printed

Alt Text

The HTML wasn't printed :(

Use DevTool of WebView2

One of the way to print HTML of WebView2 is taking screenshot by DevTool of WebView2.

using System;
using System.IO;
using System.Printing;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using System.Windows.Xps;
using Microsoft.Web.WebView2.Core;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NLog;

namespace PdfPrintSample.Main
{
    public partial class MainWindow : Window
    {
...
        private async void NavigationCompleted(object? sender,
            CoreWebView2NavigationCompletedEventArgs args)
        {
            string pic = await webView.CoreWebView2.CallDevToolsProtocolMethodAsync("Page.captureScreenshot", "{}");
            JObject o3 = JObject.Parse(pic);
            JToken data = o3["data"]!;

            byte[] bytes = Convert.FromBase64String(data.ToString());
            Image image = new Image();
            double picHeight = 0d;
            double picWidth = 0d;
            using(MemoryStream stream = new MemoryStream(bytes))
            {
                BitmapFrame bitmap = System.Windows.Media.Imaging.BitmapDecoder.Create(stream, BitmapCreateOptions.None,    
                                        BitmapCacheOption.OnLoad).Frames[0];
                picHeight = bitmap.Height;
                picWidth = bitmap.Width;
                image.Source = bitmap;
            }

            LocalPrintServer printServer = new LocalPrintServer();
            PrintQueue queue = printServer.GetPrintQueue("Microsoft Print to PDF");
            PrintTicket ticket = queue.DefaultPrintTicket;
            // must set PageMediaSize
            ticket.PageMediaSize = new PageMediaSize(picWidth, picHeight);

            XpsDocumentWriter writer = PrintQueue.CreateXpsDocumentWriter(queue); 
            writer.Write(image, ticket);
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Set PageMediaSize

An important thing is I must set PageMediaSize because XpsDocumentWriter may not be able to get the image size.
So if I don't do this, the result like below.
Alt Text

Discussion (0)