WPF可视化控件打印
标签:
IntroductionWhile coding an application that displays a detailed report in a ScrollViewer, it was decided that it would be nice to print the report to a printer.
I found that WPF provides a PrintDialog.PrintVisual method for printing any WPF control derived from the Visual class. PrintVisual will only print a single page so you have to scale your control to fit on the page. Unfortunately this would not work for me since the report was sometimes long enough that it could not be read easily when scaled to fit on the page.
Another option for printing provided by WPF is to create a separate view in a FlowDocument. This is probably the best way to print documents, but it was more work than I wished to put into it, not to mention the extra view that would have to be maintained for each control I wished to print.
What I ended up doing may be a bit unorthodox but works well for my purpose of printing a report that is already displayed in the application. I take the control and convert it into a bitmap that will look good on a 300 dpi printer and then chop the bitmap up into pieces that will fit on a page, add the pages to a FixedDocumentand send that to the printer using PrintDialog.PrintDocument.
Using the codeBelow is a class that you can bind to that will print any control derived from the FrameworkElement class.
Hide Shrink Copy Code
public class PrintCommand : ICommand { public bool CanExecute(object parameter) { return true; } public void Execute(object parameter) { if (parameter is FrameworkElement) { FrameworkElement objectToPrint = parameter as FrameworkElement; PrintDialog printDialog = new PrintDialog(); if ((bool)printDialog.ShowDialog().GetValueOrDefault()) { Mouse.OverrideCursor = Cursors.Wait; System.Printing.PrintCapabilities capabilities = printDialog.PrintQueue.GetPrintCapabilities(printDialog.PrintTicket); double dpiScale = 300.0 / 96.0; FixedDocument document = new FixedDocument(); try { // Change the layout of the UI Control to match the width of the printer page objectToPrint.Width = capabilities.PageImageableArea.ExtentWidth; objectToPrint.UpdateLayout(); objectToPrint.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); Size size = new Size(capabilities.PageImageableArea.ExtentWidth, objectToPrint.DesiredSize.Height); objectToPrint.Measure(size); size = new Size(capabilities.PageImageableArea.ExtentWidth, objectToPrint.DesiredSize.Height); objectToPrint.Measure(size); objectToPrint.Arrange(new Rect(size)); // Convert the UI control into a bitmap at 300 dpi double dpiX = 300; double dpiY = 300; RenderTargetBitmap bmp = new RenderTargetBitmap(Convert.ToInt32( capabilities.PageImageableArea.ExtentWidth * dpiScale), Convert.ToInt32(objectToPrint.ActualHeight * dpiScale), dpiX, dpiY, PixelFormats.Pbgra32); bmp.Render(objectToPrint); // Convert the RenderTargetBitmap into a bitmap we can more readily use PngBitmapEncoder png = new PngBitmapEncoder(); png.Frames.Add(BitmapFrame.Create(bmp)); System.Drawing.Bitmap bmp2; using (MemoryStream memoryStream = new MemoryStream()) { png.Save(memoryStream); bmp2 = new System.Drawing.Bitmap(memoryStream); } document.DocumentPaginator.PageSize = new Size(printDialog.PrintableAreaWidth, printDialog.PrintableAreaHeight); // break the bitmap down into pages int pageBreak = 0; int previousPageBreak = 0; int pageHeight = Convert.ToInt32(capabilities.PageImageableArea.ExtentHeight * dpiScale); while (pageBreak < bmp2.Height - pageHeight) { pageBreak += pageHeight; // Where we thing the end of the page should be // Keep moving up a row until we find a good place to break the page while (!IsRowGoodBreakingPoint(bmp2, pageBreak)) pageBreak--; PageContent pageContent = generatePageContent(bmp2, previousPageBreak, pageBreak, document.DocumentPaginator.PageSize.Width, document.DocumentPaginator.PageSize.Height, capabilities); document.Pages.Add(pageContent); previousPageBreak = pageBreak; } // Last Page PageContent lastPageContent = generatePageContent(bmp2, previousPageBreak, bmp2.Height, document.DocumentPaginator.PageSize.Width, document.DocumentPaginator.PageSize.Height, capabilities); document.Pages.Add(lastPageContent); } finally { // Scale UI control back to the original so we don‘t effect what is on the screen objectToPrint.Width = double.NaN; objectToPrint.UpdateLayout(); objectToPrint.LayoutTransform = new ScaleTransform(1, 1); Size size = new Size(capabilities.PageImageableArea.ExtentWidth, capabilities.PageImageableArea.ExtentHeight); objectToPrint.Measure(size); objectToPrint.Arrange(new Rect(new Point(capabilities.PageImageableArea.OriginWidth, capabilities.PageImageableArea.OriginHeight), size)); Mouse.OverrideCursor = null; } printDialog.PrintDocument(document.DocumentPaginator, "Print Document Name"); } } }温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/69074.html
- 上一篇:nginx轻松实现api认证
- 下一篇:Windows 10介绍及下载