我有一个基本的UWP应用程序,嵌入式WebView显示一个相当大的HTML文档(多达500个字母大小的打印页)。
我想添加对打印HTML文档的支持。以下是我的做法:
<div style="height:100vh">来生成第二个被分解成“页面”的HTML文档,其中最多500个。WebView中,然后根据用户选择的页面大小重新调整大小以适合一个页面。scrollY设置为只显示使用JavaScript:window.scrollTo(0, -pageOffset)的当前页面WebViewBrush捕获WebView中当前页面的快照。
问题:
我可以生成所有500页的打印预览,但有时预览会丢失页面,而其他页面则会多次出现。
我怀疑这是因为我使用WebViewBrush.Redraw()来捕获滚动WebView的快照,但是文档中说Redraw() 是异步发生的。在WebViewBrush有机会重新绘制之前,我可能会翻阅当前页面,从而意外地捕获下一页。
如何确保WebViewBrush捕获了WebView,以便滚动到下一页?
生成一个页面的代码:
private async Task<Rectangle> MakePage(WebView webView,
Size pageSize, double pageOffset)
{
// Scroll to next page:
await webView.EvaluateJavaScriptSnippetAsync(
$"window.scrollTo(0, {pageOffset})");
var brush = new WebViewBrush();
brush.Stretch = Stretch.Uniform;
brush.SetSource(webView);
brush.Redraw(); // XXX Need to wait for this, but there's no API
// Add a delay hoping Redraw() finishes... I think here is the problem.
await Task.Delay(150);
var rectangle = new Rectangle()
{
Width = pageSize.Width,
Height = pageSize.Height
};
rectangle.Fill = brush;
brush.Stretch = Stretch.UniformToFill;
brush.AlignmentY = AlignmentY.Top;
return rectangle;
}注意:如果有一个替代使用WebViewBrush打印500页,我是开放的建议。我试着为每个页面使用一个单独的WebView,但是这个应用程序在200页之后耗尽了内存。
奖品:,我开始了一项赏金计划,每一个能打印500页的人都能得到100分。
发布于 2018-03-22 03:17:32
根据 remarks的重要部分
WebView控件具有固有的异步行为,当控件的内容被完全加载时,它会重新绘制控件。但是,相关的WebViewBrush在XAML被解析后立即呈现(这可能在WebView加载URI内容之前)。或者,您可以等待在SetSource上调用WebViewBrush,直到完全加载源内容(例如,在处理程序中调用WebView.LoadCompleted事件的SetSource )。
以便您可以在SetSource之后调用WebViewBrush的WebView.LoadCompleted方法。
发布于 2018-03-26 06:37:30
我从你的问题中了解到,你只有一个HTML文档。这是非常大的内容,你可以把它划分成500页。你需要打印整个HTML页面。在这里,我认为HTML页面中没有不想打印的内容、空间或部分。
我搜索了你的问题发现了一些东西。我修改了这段代码,并在我的UWP应用程序上运行,为您提供了强大的基础。
我确信这不是您想要的确切解决方案,因为我不知道您想要打印的页面大小和其他参数,但是下面的代码对您是超过90%有用的。
此代码根据提供给方法的大小生成页。它将把整个网页划分为no。一页一页。它没有任何打印逻辑。我确信您有足够的能力(基于您的声誉点:)来处理C#和这段代码。您可以根据需要修改它。
XAML
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<WebView x:Name="wv" Source="http://www.stackoverflow.com"></WebView>
</Grid>C#
public MainPage()
{
this.InitializeComponent();
wv.LoadCompleted += Wv_LoadCompleted;
}
async private void Wv_LoadCompleted(object sender, NavigationEventArgs e)
{
var allPages = await GetWebPages(wv, new Windows.Foundation.Size(100d, 150d));
}
async Task<IEnumerable<FrameworkElement>> GetWebPages(WebView webView, Windows.Foundation.Size pageSize)
{
// GETTING WIDTH FROM WEVIEW CONTENT
var widthFromView = await webView.InvokeScriptAsync("eval", new[] { "document.body.scrollWidth.toString()" });
int contentWidth;
if (!int.TryParse(widthFromView, out contentWidth))
throw new Exception(string.Format("failure/width:{0}", widthFromView));
webView.Width = contentWidth;
// GETTING HEIGHT FROM WEBVIEW CONTENT
var heightFromView = await webView.InvokeScriptAsync("eval", new[] { "document.body.scrollHeight.toString()" });
int contentHeight;
if (!int.TryParse(heightFromView, out contentHeight))
throw new Exception(string.Format("failure/height:{0}", heightFromView));
webView.Height = contentHeight;
// CALCULATING NO OF PAGES
var scale = pageSize.Width / contentWidth;
var scaledHeight = (contentHeight * scale);
var pageCount = (double)scaledHeight / pageSize.Height;
pageCount = pageCount + ((pageCount > (int)pageCount) ? 1 : 0);
// CREATE PAGES
var pages = new List<Windows.UI.Xaml.Shapes.Rectangle>();
for (int i = 0; i < (int)pageCount; i++)
{
var translateY = -pageSize.Height * i;
var page = new Windows.UI.Xaml.Shapes.Rectangle
{
Height = pageSize.Height,
Width = pageSize.Width,
Margin = new Thickness(5),
Tag = new TranslateTransform { Y = translateY },
};
page.Loaded += async (s, e) =>
{
var rectangle = s as Windows.UI.Xaml.Shapes.Rectangle;
var wvBrush = await GetWebViewBrush(webView);
wvBrush.Stretch = Stretch.UniformToFill;
wvBrush.AlignmentY = AlignmentY.Top;
wvBrush.Transform = rectangle.Tag as TranslateTransform;
rectangle.Fill = wvBrush;
};
pages.Add(page);
}
return pages;
}
async Task<WebViewBrush> GetWebViewBrush(WebView webView)
{
// ASSING ORIGINAL CONTENT WIDTH
var originalWidth = webView.Width;
var widthFromView = await webView.InvokeScriptAsync("eval", new[] { "document.body.scrollWidth.toString()" });
int contentWidth;
if (!int.TryParse(widthFromView, out contentWidth))
throw new Exception(string.Format("failure/width:{0}", widthFromView));
webView.Width = contentWidth;
// ASSINGING ORIGINAL CONTENT HEIGHT
var originalHeight = webView.Height;
var heightFromView = await webView.InvokeScriptAsync("eval", new[] { "document.body.scrollHeight.toString()" });
int contentHeight;
if (!int.TryParse(heightFromView, out contentHeight))
throw new Exception(string.Format("failure/height:{0}", heightFromView));
webView.Height = contentHeight;
// CREATING BRUSH
var originalVisibilty = webView.Visibility;
webView.Visibility = Windows.UI.Xaml.Visibility.Visible;
var wvBrush = new WebViewBrush
{
SourceName = webView.Name,
Stretch = Stretch.Uniform
};
wvBrush.Redraw();
webView.Width = originalWidth;
webView.Height = originalHeight;
webView.Visibility = originalVisibilty;
return wvBrush;
}发布于 2018-08-30 06:17:43
重获承诺。原始答案保留在末尾.
比我想象的要难得多。
这里有一个完全不同的解决方案,可以完全避免这个问题:https://github.com/ArthurHub/HTML-Renderer/
这一项目已被放弃,但状况良好,仍然具有现实意义。有一个核心呈现器和一系列针对各种.NET平台的包装器项目。
UWP没有列出,但是核心呈现器是一个纯的C#解决方案,它故意将与平台相关的内容分解出来,并复制几个完全工作的伙伴(平台适配器层)。
我使用它从一个MVC5网络API打印,提供浏览器内的网络打印服务给SPA客户端。这个库速度快得惊人,比MSHTML或EdgeHTML小得多。它不打印,它呈现。这些示例呈现一个位图,打印示例在WinForms PrintDocument.PrintPage事件提供的Graphics对象上绘制位图。这会产生可怕的上采样像素化,而(完全没有文档记录的)解决方案是呈现一个Windows元文件。仍然存在分页的问题,但是有一个用于PDF的PAL,您可以从它中建立这个方法。
著名的遗言:将WPF解决方案转换为UWP应该不难。
如果你感兴趣,我们可以分叉回购和添加失踪的UWP伙伴。这样做的风险在于需要支持--它可能对小部件猴子非常有用。
对于预览方面,您可能会在UI上分页和绘制元文件。
我的第一个想法是一次丑陋的黑客攻击,这应该是可行的:好好睡一觉。重绘已经在另一个线程上进行,这就是为什么您处于竞争状态。如果你保证其他线程有更多的时间,你的机会会大大提高。
新问题: Thread.Sleep在UWP中是不可用的,因为所有的东西都支持延续,除非它不支持。
幸运的是,还有其他方法剥去这只猫的皮。
wvBrush.Redraw();
// System.Threading.Tasks.Task.Delay(30).Wait() is more elegant but less portable than...
using (var waitHandle = new System.Threading.ManualResetEventSlim(initialState: false))
waitHandle.Wait(TimeSpan.FromMilliseconds(30)); // exploit timeout下一个问题是渲染时间不可预测,长时间睡眠会影响性能,因此您需要一种测试成功的方法。
你说失败会产生一个全白的页面。我会为所有的白色写一个测试,回来,并重写这个答案的结尾,当我使它工作得很快。
https://stackoverflow.com/questions/49411176
复制相似问题