none
使用PrintDialog 打印Grid RRS feed

  • 问题

  • 
            private void btnPrint_Click(object sender, RoutedEventArgs e)
            {
                PrintDialog dialog = new PrintDialog();  
                if (dialog.ShowDialog() == true)
                {
                    dialog.UserPageRangeEnabled = true; 
                    dialog.PrintVisual(Grid_Main,  DateTime.Now.ToString("yyyy-MM-dd") );
                }
            }


    使用 printDialog 的 printVisual方法发硬 Grid (Grid_main是Grid的名称) 当数据量很大时一页纸不够打印,但打印机只打印一张纸,完了以后就不打印了。怎么实现可以打印多页?


    2016年1月2日 8:41

答案

  • 您好 卡托,

    >>怎么实现可以打印多页?

    PrintVisual方法并不会自动帮助我们把打印结果分为多页。我们需要手动去实现。 我们可以通过在一个FixedDocument中添加多个FixedPage来实现,最后调用PrintDialog的PrintDocument方法来打印这个多页的文档。 这其中一个难点是如果分析一个WPF的控件并把它动态的拆分成为多个页面并放入不同的FixedPage中。 下面一个Command实现了这个功能,供您参考。

    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
                    {
                        // 修改此UI Control的外观来适应打印页的宽度
                        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));
    
                        //将这个UI控件转换为一个bitmap
                        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);
    
                        //将RenderTargetBitmap转换为bitmap
                        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);
    
                        //将bitmap拆分为多个Page
                        int pageBreak = 0;
                        int previousPageBreak = 0;
                        int pageHeight =
                            Convert.ToInt32(capabilities.PageImageableArea.ExtentHeight * dpiScale);
                        while (pageBreak < bmp2.Height - pageHeight)
                        {
                            pageBreak += pageHeight; 
    
                            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;
                        }
    
                        //最后一页
                        PageContent lastPageContent = generatePageContent(bmp2, previousPageBreak,
                          bmp2.Height, document.DocumentPaginator.PageSize.Width,
                          document.DocumentPaginator.PageSize.Height, capabilities);
                        document.Pages.Add(lastPageContent);
                    }
                    finally
                    {
                        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");
                }
            }
        }
    
        private PageContent generatePageContent(System.Drawing.Bitmap bmp, int top,
         int bottom, double pageWidth, double PageHeight,
         System.Printing.PrintCapabilities capabilities)
        {
            FixedPage printDocumentPage = new FixedPage();
            printDocumentPage.Width = pageWidth;
            printDocumentPage.Height = PageHeight;
    
            int newImageHeight = bottom - top;
            System.Drawing.Bitmap bmpPage = bmp.Clone(new System.Drawing.Rectangle(0, top,
                   bmp.Width, newImageHeight), System.Drawing.Imaging.PixelFormat.Format32bppArgb);
    
            Image pageImage = new Image();
            BitmapSource bmpSource =
                System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                    bmpPage.GetHbitmap(),
                    IntPtr.Zero,
                    System.Windows.Int32Rect.Empty,
                    BitmapSizeOptions.FromWidthAndHeight(bmp.Width, newImageHeight));
    
            pageImage.Source = bmpSource;
            pageImage.VerticalAlignment = VerticalAlignment.Top;
    
            printDocumentPage.Children.Add(pageImage);
    
            PageContent pageContent = new PageContent();
            ((System.Windows.Markup.IAddChild)pageContent).AddChild(printDocumentPage);
    
            FixedPage.SetLeft(pageImage, capabilities.PageImageableArea.OriginWidth);
            FixedPage.SetTop(pageImage, capabilities.PageImageableArea.OriginHeight);
    
            pageImage.Width = capabilities.PageImageableArea.ExtentWidth;
            pageImage.Height = capabilities.PageImageableArea.ExtentHeight;
            return pageContent;
        }
    
        private bool IsRowGoodBreakingPoint(System.Drawing.Bitmap bmp, int row)
        {
            double maxDeviationForEmptyLine = 1627500;
            bool goodBreakingPoint = false;
    
            if (rowPixelDeviation(bmp, row) < maxDeviationForEmptyLine)
                goodBreakingPoint = true;
    
            return goodBreakingPoint;
        }
    
    
        private double rowPixelDeviation(System.Drawing.Bitmap bmp, int row)
        {
            int count = 0;
            double total = 0;
            double totalVariance = 0;
            double standardDeviation = 0;
            System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(new System.Drawing.Rectangle(0, 0, 
                   bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);
            int stride = bmpData.Stride;
            IntPtr firstPixelInImage = bmpData.Scan0;
    
            unsafe
            {
                byte* p = (byte*)(void*)firstPixelInImage;
                p += stride * row;  // find starting pixel of the specified row
                for (int column = 0; column < bmp.Width; column++)
                {
                    count++;  //count the pixels
    
                    byte blue = p[0];
                    byte green = p[1];
                    byte red = p[3];
    
                    int pixelValue = System.Drawing.Color.FromArgb(0, red, green, blue).ToArgb();
                    total += pixelValue;
                    double average = total / count;
                    totalVariance += Math.Pow(pixelValue - average, 2);
                    standardDeviation = Math.Sqrt(totalVariance / count);
    
                    // go to next pixel
                    p += 3;
                }
            }
            bmp.UnlockBits(bmpData);
    
            return standardDeviation;
        }
    
        public event EventHandler CanExecuteChanged;
    }
    
    我们只需要在项目中创建一个PrintCommand类,然后把上面的代码都拷贝进去,最后执行以下代码即可分多页打印我们的Grid。
    PrintCommand pc = new PrintCommand();
    pc.Execute(Grid_Main);



    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    2016年1月5日 2:28
    版主