C#visual(控件)的打印

方法有下面几种

1, 使用PrintDialog::PrintVisual

        public bool PrintVisual(FrameworkElement source)
        {
            PrintDialog printDlg = new System.Windows.Controls.PrintDialog();

           if (printDlg.ShowDialog() == true)
           {
               printDlg.PrintVisual(source, "PrintVisual");
               return true;
           }

            return false;
        }

2,  转成Bitmap图,再打印

            double width = source.ActualWidth;
            double height = source.ActualHeight;

            RenderTargetBitmap renderTarget = new RenderTargetBitmap(
                (int)width, (int)height, 96, 96, PixelFormats.Default);
            renderTarget.Render(source);

            // BitmapSourceをBitmapに転換
            System.Drawing.Bitmap bitmap;
            MemoryStream outStream = new MemoryStream();
            BitmapEncoder pngEncoder = new PngBitmapEncoder();
            pngEncoder.Frames.Add(BitmapFrame.Create(renderTarget));
            pngEncoder.Save(outStream);
            bitmap = new System.Drawing.Bitmap(outStream);
            printBridge.print(bitmap);

补充说明,转成位图的格式,这里用了png格式,原因是当控件的背景色是透明(transparent)时,jpg和map格式图像背景色都变成了黑色。。

printBridge的print的实现如下:

int HpPrintBridge::print(Image^ data)
{
	_data = data;

	PrintDocument^ pd = gcnew PrintDocument;
	pd->PrintPage += gcnew PrintPageEventHandler( this, &HpPrintBridge::pd_PrintPage );
	pd->Print();

	return 0;
}
void HpPrintBridge::pd_PrintPage( Object^ /*sender*/, PrintPageEventArgs^ ev )
{
    ev->Graphics->DrawImage(_data, 0, 0);
}

void HpPrintBridge::pd_PrintPage( Object^ /*sender*/, PrintPageEventArgs^ ev )
{
    ev->Graphics->DrawImage(_data, 0, 0);
}



3,将vistual控件先转换为xps document ,再转换FlowDocument,再打印。

  参照:   点击打开链接

(sample示例代码有异常,无法执行。)


打印中有时会超出页面,一张纸打不下来。可用下面的办法,先得到缩放比例,再打印。


       private PrintCapabilities GetPrintCapabilities(bool isDefaultPrint)
        {
            System.Printing.PrintCapabilities capabilities = null;

            if (isDefaultPrint)
            {
                var localPrintServer = new LocalPrintServer();

                // Retrieving collection of local printer on user machine
                var localPrinterCollection =
                    localPrintServer.GetPrintQueues();

                var localPrinterEnumerator =
                    localPrinterCollection.GetEnumerator();

                if (localPrinterEnumerator.MoveNext())
                {
                    // Get PrintQueue from first available printer
                    PrintQueue printQueue = (PrintQueue)localPrinterEnumerator.Current;
                    capabilities = printQueue.GetPrintCapabilities();
                }
            }
            else
            {
                PrintDialog printDlg = new System.Windows.Controls.PrintDialog();
                if (printDlg.ShowDialog() == true)
                {
                    capabilities = printDlg.PrintQueue.GetPrintCapabilities(printDlg.PrintTicket);
                }
            }

            return capabilities;

        }

        public bool PrintVisualAutoFitPage(FrameworkElement source, bool isDefaultPrint)
        {
            PrintDialog printDlg = new System.Windows.Controls.PrintDialog();

            System.Printing.PrintCapabilities capabilities = GetPrintCapabilities(isDefaultPrint);
            
            if(capabilities != null){
                // 印刷 get scale of the print wrt to screen of WPF visual
                double scale = Math.Min(capabilities.PageImageableArea.ExtentWidth / source.ActualWidth, 
                    capabilities.PageImageableArea.ExtentHeight / source.ActualHeight);

                //元のTransformを一時に保留
                Transform oldTransform = source.LayoutTransform;
                var oldSize = new System.Windows.Size(source.ActualWidth, source.ActualHeight);

                //Transform the Visual to scale
                this.LayoutTransform = new ScaleTransform(scale, scale);

                //get the size of the printer page
                System.Windows.Size sz = new System.Windows.Size(capabilities.PageImageableArea.ExtentWidth, capabilities.PageImageableArea.ExtentHeight);

                //update the layout of the visual to the printer page size.
                this.Measure(sz);
                this.Arrange(new Rect(new System.Windows.Point(capabilities.PageImageableArea.OriginWidth, capabilities.PageImageableArea.OriginHeight), sz));

                //now print the visual to printer to fit on the one page.
                printDlg.PrintVisual(source, "PrintVisualAutoFitPage");

                source.LayoutTransform = oldTransform;
                source.Measure(oldSize);
                return true;
            }
            return false;
        }


根据scale,对方法二做如下修改

    private void PrintByImage(FrameworkElement source, bool isDefaultPrint)
        {
            double scale = GetPrintScale(source, isDefaultPrint);

            //double actualHeight = source.ActualWidth;
            //double actualWidth = source.ActualHeight;
            
            double actualHeight = source.RenderSize.Height;
            double actualWidth = source.RenderSize.Width;

            double renderHeight = actualHeight * scale;
            double renderWidth = actualWidth * scale;

            RenderTargetBitmap renderTarget = new RenderTargetBitmap((int)renderWidth, (int)renderHeight, 96, 96, PixelFormats.Default);
            VisualBrush sourceBrush = new VisualBrush(source);

            DrawingVisual drawingVisual = new DrawingVisual();
            DrawingContext drawingContext = drawingVisual.RenderOpen();

            using (drawingContext)
            {
                drawingContext.PushTransform(new ScaleTransform(scale, scale));
                drawingContext.DrawRectangle(sourceBrush, null, new Rect(new System.Windows.Point(0, 0), new System.Windows.Point(actualWidth, actualHeight)));
            }
            renderTarget.Render(drawingVisual);


            // BitmapSourceをBitmapに転換
            System.Drawing.Bitmap bitmap;
            MemoryStream outStream = new MemoryStream();
            BitmapEncoder pngEncoder = new PngBitmapEncoder();
            pngEncoder.Frames.Add(BitmapFrame.Create(renderTarget));
            pngEncoder.Save(outStream);
            bitmap = new System.Drawing.Bitmap(outStream);

            obj.print(bitmap);
        }



猜你喜欢

转载自blog.csdn.net/jfyy/article/details/8488675