【发布时间】:2020-10-23 08:57:05
【问题描述】:
网上有很多投诉(如this 一个和this 一个)关于打印WebVeiw 的网页,打印的页面只显示屏幕上的当前视图,而不是整个页面。通过浏览在线搜索中的一些代码,我能够使用以下代码打印整个页面。但是打印的页面已尝试在启用滚动条的情况下将其全部打印在一个页面中。而且打印出来的内容很模糊(如下图)。
问题:在启用滚动条的情况下,如何在打印整个页面的同时使打印的内容不模糊?
WebView 中使用的网站:Wikipedia
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:here
更新:
@Faywang - MSFT 的回复似乎很有希望。我尝试如下:
- 使用来自here 的
OnPrintButtonClick()事件的代码创建了一个方法调用PrintWebView() - 添加了我上面帖子中显示的所有其他方法/事件。
- 在我的
btnTest_Click(...)中,我修改了用户@Faywang的代码如下
.
List<Rectangle> allpages = await GetWebPages(wvTest, new Windows.Foundation.Size(750d, 950d));
//print these pages
foreach (Rectangle rectangle in allpages)
PrintWebView();
- 当应用程序在默认模式下运行时,它显示
allpages的计数为 7 并且上述foreach调用PrintWebView()7 次。如果我将应用程序屏幕置于最大模式,allpages的计数为 3,foreach调用PrintWebView()3 次(如预期的那样)。在这两种情况下,我都期望循环的最后一次迭代将带来打印对话框并打印所有页面 7(或 3,取决于应用程序屏幕的默认或最大模式)。相反,调试器转到PrintWebView()方法的catch块,如前所述,其代码取自here - 问题:我是否正确执行了上述步骤?如果没有,有什么更好的方法?
【问题讨论】:
标签: c# webview uwp windows-community-toolkit