• WPF实战案例-打印


    在前段时间做了一下打印,因为需要支持的格式比较多,所以wpf能打印的有限分享一下几种格式的打印(.xls .xlsx .doc .docx .png .jpg .bmp .pdf)

    首先为了保证excel和word的格式问题,excel和word是调用的office进行打印的。

    获取所有打印机的方法:

    LocalPrintServer print = new LocalPrintServer();
                       
                        var printers = print.GetPrintQueues();
                        foreach (var item in printers)
                        {
                               //打印机名称  item.Name;
                        }

    Excel打印。三个参数 :1.打印机名称  2要打印的文件路径+名称   3要打印的sheet页名称(可以不写就打印全部sheet)

    static Excel.Application Application { get; set; }
            public static void PrintExcel(string printName, string fileName, List<string> sheetNames = null)
            {
                if (Application == null)
                    Application = new Excel.Application();
                Application.Visible = false;
                //Application.Calculation = Excel.XlCalculation.xlCalculationManual;
                var book = Application.Workbooks.Open(fileName);
    
                
                if (sheetNames == null)
                {
                    sheetNames = new List<string>();
                    Excel.Sheets sheets = book.Sheets;
                    for (int i = 1; i <= sheets.Count; i++)
                    {
                        Excel.Worksheet workSheet = sheets.Item[i];
                        if (workSheet.Visible != Excel.XlSheetVisibility.xlSheetHidden)
                            sheetNames.Add(workSheet.Name);
                    }
                }
    
                
                foreach (var item in sheetNames)
                {
                    Excel.Worksheet workSheet = (Excel.Worksheet)book.Worksheets[item];
                    //------------------------打印页面相关设置--------------------------------
                    workSheet.PageSetup.PaperSize = Excel.XlPaperSize.xlPaperA4;//纸张大小
                    //workSheet.PageSetup.Orientation = Excel.XlPageOrientation.xlLandscape;//页面横向
                    workSheet.PageSetup.Zoom = 75; //打印时页面设置,缩放比例百分之几
                    workSheet.PageSetup.Zoom = false; //打印时页面设置,必须设置为false,页高,页宽才有效
                    workSheet.PageSetup.FitToPagesWide = 1; //设置页面缩放的页宽为1页宽
                    workSheet.PageSetup.FitToPagesTall = false; //设置页面缩放的页高自动
                                                                //workSheet.PageSetup.LeftHeader = "Nigel";//页面左上边的标志
                    //workSheet.PageSetup.CenterFooter = "第 &P 页,共 &N 页";//页面下标
                    workSheet.PageSetup.FirstPageNumber = (int)Excel.Constants.xlAutomatic;
                    workSheet.PageSetup.Order = Excel.XlOrder.xlDownThenOver;
                    workSheet.PageSetup.PrintGridlines = true; //打印单元格网线
                    workSheet.PageSetup.TopMargin = 1.5 / 0.035; //上边距为2cm(转换为in)
                    workSheet.PageSetup.BottomMargin = 1.5 / 0.035; //下边距为1.5cm
                    workSheet.PageSetup.LeftMargin = 2 / 0.035; //左边距为2cm
                    workSheet.PageSetup.RightMargin = 2 / 0.035; //右边距为2cm
                    workSheet.PageSetup.CenterHorizontally = true; //文字水平居中
                                                                   //------------------------打印页面设置结束--------------------------------
                    workSheet.PrintOutEx(Missing.Value, Missing.Value, Missing.Value, Missing.Value, printName);
                }
    
                //book.PrintOutEx(Missing.Value, Missing.Value, Missing.Value, Missing.Value, printName); //直接打印
                book.Close(false); //关闭工作空间
                
            }

    excel有时候关不干净,贡献一个强制关闭的方法,可以在excel操作完成后调用:

    [DllImport("User32.dll")]
            public static extern int GetWindowThreadProcessId(IntPtr hWnd, out int Processid);
    
            public static void ExcelClose()
            {
                if (Application != null)
                {
                    Application.Quit();
                    int iId = 0;
                    IntPtr intptr = new IntPtr(Application.Hwnd);
                    System.Diagnostics.Process p = null;
    
                    try
                    {
                        GetWindowThreadProcessId(intptr, out iId);
                        p = System.Diagnostics.Process.GetProcessById(iId);
    
                        if (p != null)
                        {
                            p.Kill();
                            p.Dispose();
                        }
                        Application = null;
                    }
                    catch (Exception e)
                    {
                        throw e;
                    }
                }
                
                System.GC.Collect();
            }

    Word打印(打印机名称,要打印的文件路径+名称)

    public static void PrintWord(string printName, string fileName)
            {
                Word.Application appword = new Word.Application();
                appword.Visible = false;
                appword.DisplayAlerts = Word.WdAlertLevel.wdAlertsNone;
                Word.Document doc = appword.Documents.Open(fileName);
                appword.ActivePrinter = printName;
                doc.PrintOut(true);
                doc.Close(false);
                appword.Quit();
            }

    图片打印WPF(支持格式 png jpg bmp)

    public static string PrintImage(string printName, string fileName)
            {
                System.Windows.Controls.PrintDialog dialog = new System.Windows.Controls.PrintDialog();//开始打印
                var printers = new LocalPrintServer().GetPrintQueues();
    
                var selectedPrinter = printers.FirstOrDefault(d => d.Name == printName);
                if (selectedPrinter == null)
                {
                    return "没有找到打印机";
                }
                dialog.PrintQueue = selectedPrinter;
                dialog.PrintDocument(new TestDocumentPaginator(new BitmapImage(new Uri(fileName))), "Image");
                return "";
                
            }
    public class TestDocumentPaginator : DocumentPaginator
        {
    
            #region 字段
            private Size _pageSize;
            private ImageSource image;
            #endregion
    
            #region 构造
            public TestDocumentPaginator(BitmapImage img)
            {
                image = img;
                //我们使用A3纸张大小
                var pageMediaSize = LocalPrintServer.GetDefaultPrintQueue()
                               .GetPrintCapabilities()
                               .PageMediaSizeCapability
                               .FirstOrDefault(x => x.PageMediaSizeName == PageMediaSizeName.ISOA4);
    
                if (pageMediaSize != null)
                {
                    _pageSize = new Size((double)pageMediaSize.Width, (double)pageMediaSize.Height);
                }
            }
            #endregion
    
            #region 重写
            /// <summary>
            /// 
            /// </summary>
            /// <param name="pageNumber">打印页是从0开始的</param>
            /// <returns></returns>
            public override DocumentPage GetPage(int pageNumber)
            {
                var visual = new DrawingVisual();
    
                using (DrawingContext dc = visual.RenderOpen())
                {
                    double imgWidth = 0;
                    double imgHeight = 0;
                    if (image.Height > _pageSize.Height)
                    {
                        double h = _pageSize.Height / image.Height;
                        imgWidth = image.Width * h;
                        imgHeight = image.Height * h;
                    }
                    if (image.Width > _pageSize.Width)
                    {
                        double w = _pageSize.Width / image.Width;
                        imgWidth = image.Width * w;
                        imgHeight = image.Height * w;
                    }
    
                    if (image.Width < _pageSize.Width && image.Height < _pageSize.Height)
                    {
                        double h = _pageSize.Height / image.Height;
                        double w = _pageSize.Width / image.Width;
                        if (h > w)
                        {
                            imgWidth = image.Width * w;
                            imgHeight = image.Height * w;
                        }
                        else
                        {
                            imgWidth = image.Width * h;
                            imgHeight = image.Height * h;
                        }
    
                    }
    
                    double left = Math.Abs((_pageSize.Width - imgWidth) <= 0 ? 2 : (_pageSize.Width - imgWidth)) / 2;
                    double top = Math.Abs((_pageSize.Height - imgHeight) <= 0 ? 2 : (_pageSize.Height - imgHeight)) / 2;
    
                    dc.DrawImage(image, new Rect(left, top, imgWidth, imgHeight));
                }
    
                return new DocumentPage(visual, _pageSize, new Rect(_pageSize), new Rect(_pageSize));
            }
    
            public override bool IsPageCountValid
            {
                get
                {
                    return true;
                }
            }
            
            public override Size PageSize
            {
                get
                {
                    return _pageSize;
                }
                set
                {
                    _pageSize = value;
                }
            }
    
            public override IDocumentPaginatorSource Source
            {
                get
                {
                    return null;
                }
            }
    
            public override int PageCount
            {
                get
                {
                    return 1;
                }
            }
            #endregion
        }
    TestDocumentPaginator内部的重写方法是计算将图片全部居中显示。
    关于图片打印多说一句:在之前我是使用image加载图片,然后通过PrintVisual打印控件的方式打印的,但是这种方式我发现在win7机器上打印出来的是空白纸张,还没明白是为什么,所以就用这种方式了。

    PDF打印(这是调用windows api去打印,不需要乱起八糟的第三方):
    // Structure and API declarions:
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
            public class DOCINFOA
            {
                [MarshalAs(UnmanagedType.LPStr)]
                public string pDocName;
                [MarshalAs(UnmanagedType.LPStr)]
                public string pOutputFile;
                [MarshalAs(UnmanagedType.LPStr)]
                public string pDataType;
            }
    
            [DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
            public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd);
    
            [DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
            public static extern bool ClosePrinter(IntPtr hPrinter);
    
            [DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
            public static extern bool StartDocPrinter(IntPtr hPrinter, Int32 level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);
    
            [DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
            public static extern bool EndDocPrinter(IntPtr hPrinter);
    
            [DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
            public static extern bool StartPagePrinter(IntPtr hPrinter);
    
            [DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
            public static extern bool EndPagePrinter(IntPtr hPrinter);
    
            [DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
            public static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, Int32 dwCount, out Int32 dwWritten);
    
            // SendBytesToPrinter()
            // When the function is given a printer name and an unmanaged array
            // of bytes, the function sends those bytes to the print queue.
            // Returns true on success, false on failure.
            public static bool SendBytesToPrinter(string szPrinterName, IntPtr pBytes, Int32 dwCount)
            {
                Int32 dwError = 0, dwWritten = 0;
                IntPtr hPrinter = new IntPtr(0);
                DOCINFOA di = new DOCINFOA();
                bool bSuccess = false; // Assume failure unless you specifically succeed.
    
                di.pDocName = "My C#.NET RAW Document";
                di.pDataType = "RAW";
    
                // Open the printer.
                if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
                {
                    // Start a document.
                    if (StartDocPrinter(hPrinter, 1, di))
                    {
                        // Start a page.
                        if (StartPagePrinter(hPrinter))
                        {
                            // Write your bytes.
                            bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
                            EndPagePrinter(hPrinter);
                        }
                        EndDocPrinter(hPrinter);
                    }
                    ClosePrinter(hPrinter);
                }
                // If you did not succeed, GetLastError may give more information
                // about why not.
                if (bSuccess == false)
                {
                    dwError = Marshal.GetLastWin32Error();
                }
                return bSuccess;
            }
    
            public static bool SendFileToPrinter(string szPrinterName, string szFileName)
            {
                // Open the file.
                FileStream fs = new FileStream(szFileName, FileMode.Open);
                // Create a BinaryReader on the file.
                BinaryReader br = new BinaryReader(fs);
                // Dim an array of bytes big enough to hold the file's contents.
                Byte[] bytes = new Byte[fs.Length];
                bool bSuccess = false;
                // Your unmanaged pointer.
                IntPtr pUnmanagedBytes = new IntPtr(0);
                int nLength;
    
                nLength = Convert.ToInt32(fs.Length);
                // Read the contents of the file into the array.
                bytes = br.ReadBytes(nLength);
                // Allocate some unmanaged memory for those bytes.
                pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength);
                // Copy the managed byte array into the unmanaged array.
                Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength);
                // Send the unmanaged bytes to the printer.
                bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength);
                // Free the unmanaged memory that you allocated earlier.
                Marshal.FreeCoTaskMem(pUnmanagedBytes);
                return bSuccess;
            }
    
            public static bool SendStringToPrinter(string szPrinterName, string szString)
            {
                IntPtr pBytes;
                Int32 dwCount;
                // How many characters are in the string?
                dwCount = szString.Length;
                // Assume that the printer is expecting ANSI text, and then convert
                // the string to ANSI text.
                pBytes = Marshal.StringToCoTaskMemAnsi(szString);
                // Send the converted ANSI string to the printer.
                SendBytesToPrinter(szPrinterName, pBytes, dwCount);
                Marshal.FreeCoTaskMem(pBytes);
                return true;
            }
    public static void PrintPDF(string printName, string fileName)
            {
                SendFileToPrinter(printName, fileName);
            }

    以上就是wpf常用的打印,目前看起来格式还是可以达到要求的,更多技术讨论请关注页面下方的qq群。
  • 相关阅读:
    C#生成图形验证码
    飞刀软件官网正式开通
    IIS7或者IIS7.5部署MVC项目时出现404错误
    office编程必不可少 [转]
    C# 利用 HttpWebRequest 和 HttpWebResponse 模拟登录有验证码的网站
    console方便用法
    24个解决实际问题的ES6代码段
    遍历对象的属性和对象的值
    前端图片处理
    Vue团队代码规范
  • 原文地址:https://www.cnblogs.com/BeiJing-Net-DaiDai/p/10243072.html
Copyright © 2020-2023  润新知