UWP WebView打印显示打印页面模糊 [英] UWP WebView Printing shows the printed page blurred

查看:86
本文介绍了UWP WebView打印显示打印页面模糊的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在线上有很多投诉(例如一个)有关在WebVeiw中打印网页的情况,其中打印页面仅显示当前视图在屏幕上,而不是整个页面上.通过在线搜索中的一些代码,我可以使用以下代码打印整个页面.但是,已打印的页面已尝试在启用滚动条的情况下将其全部打印在一页中.此外,打印的内容非常模糊(如下所示).

There are many complaints online (such as this one and this one) about the printing of a webpage in WebVeiw where the printed page only shows the current view on the screen and not the entire page. By going through some code from online searches, I was able to print the entire page using the following code. But the printed page has tried to print it all in one page with a scrollbar enabled. Moreover, the printed content is very blurred (as shown below).

问题:如何在启用滚动条的情况下仍打印整个页面时使打印的内容不模糊?

Question: How can we make the printed content not blurred while still printing the entire page with scrollbar enable?

WebView中使用的网站:维基百科

参考:从WebView到WebViewBrush

MainPage.xaml :

<Page
    x:Class="UWP_WebViewPrinting.MainPage"
    ....>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <WebView x:Name="wvTest" Source="https://en.wikipedia.org/wiki/Universal_Windows_Platform" Grid.Row="1" Margin="0,61,0,0"/>
        <Button x:Name="btnTest" Content="Test" Grid.Row="0"  VerticalAlignment="Top" Click="btnTest_Click"/>
        <Rectangle x:Name="RectangleToPrint" Grid.Row="1"/>
    </Grid>
</Page>

MainPage.xaml.cs :

private async void btnTest_Click(object sender, RoutedEventArgs e)
{
    //Step 1: use WebViewBrush to render the content of webview into the Rectangle
    int width;
    int height;
    // get the total width and height
    var widthString = await wvTest.InvokeScriptAsync("eval", new[] { "document.body.scrollWidth.toString()" });
    var heightString = await wvTest.InvokeScriptAsync("eval", new[] { "document.body.scrollHeight.toString()" });

    if (!int.TryParse(widthString, out width))
    {
        throw new Exception("Unable to get page width");
    }
    if (!int.TryParse(heightString, out height))
    {
        throw new Exception("Unable to get page height");
    }

    // resize the webview to the content
    wvTest.Width = width;
    wvTest.Height = height;

    WebViewBrush b = new WebViewBrush();
    b.SourceName = "wvTest";
    b.Redraw();
    RectangleToPrint.Fill = b;

    //Step 2: Then print the rectangle
    if (PrintManager.IsSupported())
    {
        try
        {
            // Show print UI
            await PrintManager.ShowPrintUIAsync();
        }
        catch
        {
            // Printing cannot proceed at this time
            ContentDialog noPrintingDialog = new ContentDialog()
            {
                Title = "Printing error",
                Content = "\nSorry, printing can' t proceed at this time.",
                PrimaryButtonText = "OK"
            };
            await noPrintingDialog.ShowAsync();
        }
    }
    else
    {
        // Printing is not supported on this device
        ContentDialog noPrintingDialog = new ContentDialog()
        {
            Title = "Printing not supported",
            Content = "\nSorry, printing is not supported on this device.",
            PrimaryButtonText = "OK"
        };
        await noPrintingDialog.ShowAsync();
    }
}

#region Register for printing

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    // Register for PrintTaskRequested event
    printMan = PrintManager.GetForCurrentView();
    printMan.PrintTaskRequested += PrintTaskRequested;

    // Build a PrintDocument and register for callbacks
    printDoc = new PrintDocument();
    printDocSource = printDoc.DocumentSource;
    printDoc.Paginate += Paginate;
    printDoc.GetPreviewPage += GetPreviewPage;
    printDoc.AddPages += AddPages;
}

#endregion

#region Showing the print dialog

private void PrintTaskRequested(PrintManager sender, PrintTaskRequestedEventArgs args)
{
    // Create the PrintTask.
    // Defines the title and delegate for PrintTaskSourceRequested
    var printTask = args.Request.CreatePrintTask("Print", PrintTaskSourceRequrested);

    // Handle PrintTask.Completed to catch failed print jobs
    printTask.Completed += PrintTaskCompleted;
}

private void PrintTaskSourceRequrested(PrintTaskSourceRequestedArgs args)
{
    // Set the document source.
    args.SetSource(printDocSource);
}

#endregion

#region Print preview

private void Paginate(object sender, PaginateEventArgs e)
{
    // As I only want to print one Rectangle, so I set the count to 1
    printDoc.SetPreviewPageCount(1, PreviewPageCountType.Final);
}

private void GetPreviewPage(object sender, GetPreviewPageEventArgs e)
{
    // Provide a UIElement as the print preview.
    printDoc.SetPreviewPage(e.PageNumber, this.RectangleToPrint);
}

#endregion

#region Add pages to send to the printer

private void AddPages(object sender, AddPagesEventArgs e)
{
    printDoc.AddPage(this.RectangleToPrint);

    // Indicate that all of the print pages have been provided
    printDoc.AddPagesComplete();
}

#endregion

#region Print task completed

private async void PrintTaskCompleted(PrintTask sender, PrintTaskCompletedEventArgs args)
{
    // Notify the user when the print operation fails.
    if (args.Completion == PrintTaskCompletion.Failed)
    {
        await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
        {
            ContentDialog noPrintingDialog = new ContentDialog()
            {
                Title = "Printing error",
                Content = "\nSorry, failed to print.",
                PrimaryButtonText = "OK"
            };
            await noPrintingDialog.ShowAsync();
        });
    }
}

#endregion

印刷的PDF :在此处

更新:

@Faywang - MSFT的回应似乎很有希望.我尝试如下:

A response from @Faywang - MSFT seems quite promising. I tried it as follows:

  1. 使用
  1. Created a method call PrintWebView() with the code from the OnPrintButtonClick() event from here
  2. Added all the other methods/events shown in my post above.
  3. In my btnTest_Click(...), I modified the code from user @Faywang as follows

.

List<Rectangle> allpages = await GetWebPages(wvTest, new Windows.Foundation.Size(750d, 950d));
//print these pages
foreach (Rectangle rectangle in allpages)
   PrintWebView();

  1. 当应用在默认模式下运行时,它显示allpages的计数为7,并且上述foreach调用PrintWebView() 7次.如果我将应用程序屏幕置于最大模式,则allpages的计数为3,而foreach调用PrintWebView()的次数为3次(如预期的那样).在这两种情况下,我都希望循环的最后一次迭代将带来打印对话框并打印所有页面7(或3,具体取决于应用程序屏幕的默认或最大模式).相反,调试器转到PrintWebView()方法的catch块,如前所述,其代码来自
  1. When the app runs in default mode it shows count for allpages to be 7 and the above foreach calls PrintWebView() 7 times. If I put the app screen in max mode, the count for allpages is 3 and the foreach calls PrintWebView() 3 times (as expected). In both cases I was expecting the last iteration of the loop will bring the print dialog and print all pages 7 (or 3 depending on default or max mode of the app's screen). Instead, the debugger went to the catch block of the PrintWebView() method whose code, as stated earlier, is taken from here
  2. Question: Did I follow the above steps correctly? If not, what would be a better way of doing it?

推荐答案

将Webview压缩并重新绘制到矩形时,它将变得模糊,最好在多个页面中显示Webview.首先,我将打印页面的宽度和高度指定为750、950,然后根据比例确定需要打印多少页.之后,您可以打印这些矩形.例如:

When you compress and redraw the webview to the rectangle, it will become blurred, it's better to display the webview in mutiple pages. First I give the width and height of printed page as 750, 950, and then according to the scale to cacluate how many pages it needs to be. After that, you can print these Rectangles. For example:

private async void btnTest_Click(object sender, RoutedEventArgs e)
{
    allPages = await GetWebPages(wvTest, new Windows.Foundation.Size(750d, 950d));
    //print these pages
}

async Task<List<Windows.UI.Xaml.Shapes.Rectangle>> GetWebPages(Windows.UI.Xaml.Controls.WebView webView, Windows.Foundation.Size page)
{
    // ask the content its width
    var _WidthString = await webView.InvokeScriptAsync("eval",
                new[] { "document.body.scrollWidth.toString()" });
    int _ContentWidth;
    if (!int.TryParse(_WidthString, out _ContentWidth))
        throw new Exception(string.Format("failure/width:{0}", _WidthString));
    webView.Width = _ContentWidth;

    // ask the content its height
    var _HeightString = await webView.InvokeScriptAsync("eval",
                new[] { "document.body.scrollHeight.toString()" });
    int _ContentHeight;
    if (!int.TryParse(_HeightString, out _ContentHeight))
        throw new Exception(string.Format("failure/height:{0}", _HeightString));
    webView.Height = _ContentHeight;

    // how many pages will there be?
    var _Scale = page.Width / _ContentWidth;
    var _ScaledHeight = (_ContentHeight * _Scale);
    var _PageCount = (double)_ScaledHeight / page.Height;
    _PageCount = _PageCount + ((_PageCount > (int)_PageCount) ? 1 : 0);

    // create the pages
    var _Pages = new List<Windows.UI.Xaml.Shapes.Rectangle>();
    for (int i = 0; i < (int)_PageCount; i++)
    {
        var _TranslateY = -page.Height * i;
        var _Page = new Windows.UI.Xaml.Shapes.Rectangle
        {
            Height = page.Height,
            Width = page.Width,
            Margin = new Windows.UI.Xaml.Thickness(5),
            Tag = new Windows.UI.Xaml.Media.TranslateTransform { Y = _TranslateY },
        };
        _Page.Loaded += async (s, e) =>
        {
            var _Rectangle = s as Windows.UI.Xaml.Shapes.Rectangle;
            var _Brush = await GetWebViewBrush(webView);
            _Brush.Stretch = Windows.UI.Xaml.Media.Stretch.UniformToFill;
            _Brush.AlignmentY = Windows.UI.Xaml.Media.AlignmentY.Top;
            _Brush.Transform = _Rectangle.Tag as Windows.UI.Xaml.Media.TranslateTransform;
            _Rectangle.Fill = _Brush;
        };
        _Pages.Add(_Page);
    }
    return _Pages;
}

async Task<WebViewBrush> GetWebViewBrush(Windows.UI.Xaml.Controls.WebView webView)
{
    // resize width to content
    var _OriginalWidth = webView.Width;
    var _WidthString = await webView.InvokeScriptAsync("eval",
            new[] { "document.body.scrollWidth.toString()" });
    int _ContentWidth;
    if (!int.TryParse(_WidthString, out _ContentWidth))
            throw new Exception(string.Format("failure/width:{0}", _WidthString));
    webView.Width = _ContentWidth;

    // resize height to content
    var _OriginalHeight = webView.Height;
    var _HeightString = await webView.InvokeScriptAsync("eval",
            new[] { "document.body.scrollHeight.toString()" });
    int _ContentHeight;
    if (!int.TryParse(_HeightString, out _ContentHeight))
            throw new Exception(string.Format("failure/height:{0}", _HeightString));
    webView.Height = _ContentHeight;

    // create brush
    var _OriginalVisibilty = webView.Visibility;
    webView.Visibility = Windows.UI.Xaml.Visibility.Visible;
    var _Brush = new WebViewBrush
    {
        SourceName = webView.Name,
        Stretch = Windows.UI.Xaml.Media.Stretch.Uniform
    };
    _Brush.Redraw();

    // reset, return
    webView.Width = _OriginalWidth;
    webView.Height = _OriginalHeight;
    webView.Visibility = _OriginalVisibilty;
    return _Brush;
}

这篇关于UWP WebView打印显示打印页面模糊的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆