在前段時間作了一下打印,由於須要支持的格式比較多,因此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羣。