WPF實戰案例-打印

在前段時間作了一下打印,由於須要支持的格式比較多,因此wpf能打印的有限分享一下幾種格式的打印(.xls .xlsx .doc .docx .png .jpg .bmp .pdf)windows

首先爲了保證excel和word的格式問題,excel和word是調用的office進行打印的。api

獲取全部打印機的方法:app

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

 

 

Excel打印。三個參數 :1.打印機名稱  2要打印的文件路徑+名稱   3要打印的sheet頁名稱(能夠不寫就打印所有sheet)less

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操做完成後調用:ide

[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打印(打印機名稱,要打印的文件路徑+名稱)ui

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)spa

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羣。
相關文章
相關標籤/搜索