這次遇到一個需求,就是將整個界面列印在A4紙上。 需求清楚後,Bing一下關於列印,就找打一個類PrintDialog ,其中兩個方法可能會用到: 特別是public void PrintVisual(Visual visual, string description)可以直接傳一個控制項就能列印出來 ...
這次遇到一個需求,就是將整個界面列印在A4紙上。
需求清楚後,Bing一下關於列印,就找打一個類PrintDialog ,其中兩個方法可能會用到:
特別是public void PrintVisual(Visual visual, string description)可以直接傳一個控制項就能列印出來了。試了一下後發現,只列印了部分,還有部分沒列印出來。
繼續Bing,就是看了一篇關於列印UserControl的文章 ,直接c+v到工程中,很強大,能列印且還分頁列印了。但是界面佈局變醜了,仔細研究了一下源碼,是由於修改了界面的比率和寬度導致的。但是無論我怎麼修改,一直沒有達到理想的效果。我就想有沒有其他的方法,不修改比率和寬度。答案是肯定有的,將整個界面按照一定的比率保存為圖片(關於DPI,解析度的知識,自行百度,因為我說不清楚),然後再列印出來,就可以了。
代碼邏輯如下
1.初始化一個列印對象
public class ControlPrint { //A4紙的尺寸300dpi 的圖像的像素是2480×3508 private const int A4_WIDTH_PIXEL = 2480; private const int A4_HEIGTH_PIXEL = 3580; // 圖片 和 界面 dpi比率 // 通常圖片都是300 dpi 而是界面96 dpi(dpi dot per inch) private readonly double IMAGE_DPI_SCALE = 300.0 / 96.0; //標準列印使用 300dpi private readonly double PRINT_DPI_X = 300; private readonly double PRINT_DPI_Y = 300; private PrintDialog _printer = null; public ControlPrint() { InitPrinter(); } private void InitPrinter() { _printer = new PrintDialog(); //灰度列印 _printer.PrintTicket.OutputColor = OutputColor.Grayscale; } ..... }
2.列印:截圖,將圖片放到文檔中,列印文檔
........ /// <summary> /// print /// </summary> /// <param name="control"></param> /// <returns></returns> public bool Print(FrameworkElement control) { if (null == control || null == _printer) { return false; } try {
//截圖 var bitmapSrc = CaptureControlScreen(control); //圖片放在文檔里 var fixedDoc = GenerateDocument(bitmapSrc); //列印 _printer.PrintDocument(fixedDoc.DocumentPaginator, "print reprot"); return true; } catch (Exception) { return false; } } .......
3.截圖和創建文檔。
...... /// <summary> /// control to BitmapSource /// https://blogs.msdn.microsoft.com/jaimer/2009/07/03/rendertargetbitmap-tips/ /// </summary> /// <param name="control"></param> /// <returns></returns> private BitmapSource CaptureControlScreen(Visual control) { var bounds = VisualTreeHelper.GetDescendantBounds(control); var rtb = new RenderTargetBitmap((int)(bounds.Width * IMAGE_DPI_SCALE), (int)(bounds.Height * IMAGE_DPI_SCALE), PRINT_DPI_X, PRINT_DPI_Y, PixelFormats.Pbgra32); var dv = new DrawingVisual(); using (DrawingContext ctx = dv.RenderOpen()) { VisualBrush vb = new VisualBrush(control); ctx.DrawRectangle(vb, null, new Rect(new Point(), bounds.Size)); } rtb.Render(dv); return rtb; } /// <summary> /// document /// </summary> /// <param name="bmpSource"></param> /// <returns></returns> private FixedDocument GenerateDocument(BitmapSource bmpSource) { if (null == bmpSource) { return null; }
var capabilities = _printer.PrintQueue.GetPrintCapabilities(_printer.PrintTicket); //append bitmap to control of image var image = new Image(); image.Source = bmpSource; image.VerticalAlignment = VerticalAlignment.Top; image.HorizontalAlignment = HorizontalAlignment.Center; image.Width = capabilities.PageImageableArea.ExtentWidth; image.Height = capabilities.PageImageableArea.ExtentHeight; //append image to fixedpage var printDocumentPage = new FixedPage(); printDocumentPage.Width = capabilities.PageImageableArea.ExtentWidth; printDocumentPage.Height = capabilities.PageImageableArea.ExtentHeight; printDocumentPage.HorizontalAlignment = HorizontalAlignment.Center; printDocumentPage.Children.Add(image); //append fixedpage to pagecontent var pageContent = new PageContent(); pageContent.HorizontalAlignment = HorizontalAlignment.Center; ((System.Windows.Markup.IAddChild)pageContent).AddChild(printDocumentPage); //append pagecontent to document var fixedDoc = new FixedDocument(); fixedDoc.Pages.Add(pageContent); return fixedDoc; }
至此就完成了列印界面。需要註意的是,如果界面有滾動條的話,那列印的是滾動條裡面的一層grid或者panel,這樣才能完整的列印出。