如何在 Windows 应用商店应用程序中打印 WebView 内容? [英] How do I print WebView content in a Windows Store App?

查看:28
本文介绍了如何在 Windows 应用商店应用程序中打印 WebView 内容?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 Metro 应用,我正在尝试打印 WebView 控件的内容.使用 MSDN Print Sample 作为我的源参考.我只需将 printableArea 中的 XAML 更改如下:

I have a Metro App and I am attempting to Print the Content of a WebView control. Using the MSDN Print Sample as my source reference. I simply change the XAML in the printableArea as follows:

    <RichTextBlock>
        <Paragraph>
            <InlineUIContainer>
                <WebView Width="800" Height="2000" Source="http://www.stackoverflow.com"/>
            </InlineUIContainer>
        </Paragraph>
    </RichTextBlock>

这部分有效.问题是指定尺寸的Visible区域被打印,即可以滚动的区域不打印并且在PrintPreview中不显示为Multiple Pages.

This works partially. The problem is that the Visible area in the specified dimensions is Printed, i.e. The area that can be scrolled does not Print and also does not show up as Multiple Pages in the PrintPreview.

我快到了,希望得到一点帮助,让它按预期工作.

I'm almost there, would appreciate a little bit of help to get this to work as expected.

我在任何地方都没有找到任何可以解决这个特定问题的样本.

I haven't found any samples anywhere, which tackle this specific problem.

我什至在这里尝试了解决方案:http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/5edcb239-7a5b-49f7-87e3-e5a253b809c4

I have even tried the solutions here: http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/5edcb239-7a5b-49f7-87e3-e5a253b809c4

我不是第一个遇到相同/类似问题的人:http://social.msdn.microsoft.com/Search/en-US/?Refinement=112&query=print%20webview#refinementChanges=180&pageNumber=1&showMore=false

I am not the first to have experienced same/similar problem: http://social.msdn.microsoft.com/Search/en-US/?Refinement=112&query=print%20webview#refinementChanges=180&pageNumber=1&showMore=false

愿意给任何能解决这个问题的人悬赏100分.希望将演练、示例代码或模拟项目作为解决方案.

推荐答案

好的,给你.

首先,您可以将 WebView 调整为实际内容.然后,将 WebView 缩放回原始大小.它需要一个脚本调用和一个 ScaleTransform.很简单,真的.

First, you can resize the WebView to the actual content. Then, you scale the WebView back to the original size. It would require a script invoke and a ScaleTransform. Pretty simple, really.

像这样:

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
    <WebView x:Name="MyWebView" Source="http://www.stackoverflow.com" />
</Grid>

void MyWebView_LoadCompleted(object sender, NavigationEventArgs e)
{
    var _Original = MyWebView.RenderSize;

    // ask the content its width
    var _WidthString = MyWebView.InvokeScript("eval",
        new[] { "document.body.scrollWidth.toString()" });
    int _Width;
    if (!int.TryParse(_WidthString, out _Width))
        throw new Exception(string.Format("failure/width:{0}", _WidthString));

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

    // resize the webview to the content
    MyWebView.Width = _Width;
    MyWebView.Height = _Height;

    // scale the webview back to original height (can't do both height & width)
    var _Transform = (MyWebView.RenderTransform as ScaleTransform)
        ?? (MyWebView.RenderTransform = new ScaleTransform()) as ScaleTransform;
    var _Scale = _Original.Height / _Height;
    _Transform.ScaleX = _Transform.ScaleY = _Scale;
}

这将导致一个非常高而窄的 WebView 像这样:

This will result in a very tall, narrow WebView like this:

但这不是你想要的.

即使您可以调整生成的矩形的大小以使其形状不那么疯狂,但 Windows 8 中的打印合同要求您为其提供单页.它不会为你做分页.因此,您真正需要的是检索单个网站,一次一页.

Even though you can resize the resulting rectangle so that it is not so crazy shaped, the Print Contract in Windows 8 requires that you provide it with a single page. It does not do the pagination for you. As a result, what you really need is to retrieve the individual web site, one page at a time.

第一种方法是如何做到这一点的基础.但是您需要将矩形的大小固定为 Windows 8 的打印任务传递给您的页面大小.这将基于用户的打印机选择.例如,Letter 与 A4(在英国).然后,使用画笔的 Stretch 属性可以确保它自行裁剪.然后,使用画笔的 Transform 属性,您可以在矩形内上下滑动它,直到它显示出您要打印的页面.

The first approach is the basis on how to do that. But you need to fix the size of the rectangle to the page size passed to you by Windows 8's Print task. This will be based on the user's printer selection. For example, Letter versus A4 (in UK). Then, using the Stretch property of the brush you can ensure it crops itself. Then, using the Transform property of the brush, you can slide it up and down inside the rectangle until it is revealing the page you want to print.

方法如下:

<Grid Background="Blue">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="995" />
        <ColumnDefinition Width="300" />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <WebView Grid.Column="0" x:Name="MyWebView" Source="http://www.stackoverflow.com" HorizontalAlignment="Right" />
    <Rectangle Grid.Column="1" x:Name="MyWebViewRectangle" Fill="Red" />
    <ScrollViewer Grid.Column="2" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
        <ItemsControl x:Name="MyPrintPages" VerticalAlignment="Top" HorizontalAlignment="Left">
            <Rectangle Height="150" Width="100" Fill="White" Margin="5" />
            <Rectangle Height="150" Width="100" Fill="White" Margin="5" />
            <Rectangle Height="150" Width="100" Fill="White" Margin="5" />
            <Rectangle Height="150" Width="100" Fill="White" Margin="5" />
            <Rectangle Height="150" Width="100" Fill="White" Margin="5" />
        </ItemsControl>
    </ScrollViewer>
</Grid>

public MainPage()
{
    this.InitializeComponent();
    MyWebView.LoadCompleted += MyWebView_LoadCompleted;
}

void MyWebView_LoadCompleted(object sender, NavigationEventArgs e)
{
    MyWebViewRectangle.Fill = GetWebViewBrush(MyWebView);
    MyPrintPages.ItemsSource = GetWebPages(MyWebView, new Windows.Foundation.Size(100d, 150d));
    MyWebView.Visibility = Windows.UI.Xaml.Visibility.Visible;
}

WebViewBrush GetWebViewBrush(WebView webView)
{
    // resize width to content
    var _OriginalWidth = webView.Width;
    var _WidthString = webView.InvokeScript("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 = webView.InvokeScript("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 = Stretch.Uniform
    };
    _Brush.Redraw();

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

IEnumerable<FrameworkElement> GetWebPages(WebView webView, Windows.Foundation.Size page)
{
    // ask the content its width
    var _WidthString = webView.InvokeScript("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 = webView.InvokeScript("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 Thickness(5),
            Tag = new TranslateTransform { Y = _TranslateY },
        };
        _Page.Loaded += (s, e) =>
        {
            var _Rectangle = s as Windows.UI.Xaml.Shapes.Rectangle;
            var _Brush = GetWebViewBrush(webView);
            _Brush.Stretch = Stretch.UniformToFill;
            _Brush.AlignmentY = AlignmentY.Top;
            _Brush.Transform = _Rectangle.Tag as TranslateTransform;
            _Rectangle.Fill = _Brush;
        };
        _Pages.Add(_Page);
    }
    return _Pages;
}

因此 UI 将是这样的,其中左列是 WebView,第二列(中间)是像我们的第一个解决方案一样的一体机,第三列是一个显示各个页面准备就绪的中继器打印.

So the UI will be something like this, where the left column is the WebView, the second column (middle) is the all-in-one like our first solution, and the third, is a repeater showing the individual pages ready to print.

当然,魔术真的在 GetWebPages() 方法中!我不介意说,这是一个简单的奇迹,通过 C# 和 Transforms 的工作方式变得非常容易.

Of course the magic is really in the GetWebPages() method! I don't mind saying, it's a simple marvel made pretty easy by the way C# and Transforms work.

请注意,这不完整.是的,它会为您拆分页面,但我不确定您希望页面上有多少边距.所以所需的调整很小,但我想提一下.这是分解 WebView 和准备 Windows 8 打印任务以响应分页事件所需的 98% 的代码.然后一次一个地将矩形传递给它.

Please note, this is not complete. Yeah, it breaks up the page for you, but I can't be sure how much margin you want on your page. So the required tweaking is tiny, but I wanted to mention it. This is 98% of the code you will need to break up a WebView and prep if for the Windows 8 Print Task in response for the paginate event. Then pass the rectangles to it one at a time.

话虽如此,这可能是互联网上针对此问题的最全面的解决方案.:)

Having said that, this is probably the most comprehensive solution to this problem on the internet. :)

祝你好运!!

这篇关于如何在 Windows 应用商店应用程序中打印 WebView 内容?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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