WPF實戰案例-列印

来源:https://www.cnblogs.com/BeiJing-Net-DaiDai/archive/2019/01/09/10243072.html
-Advertisement-
Play Games

在前段時間做了一下列印,因為需要支持的格式比較多,所以wpf能列印的有限分享一下幾種格式的列印(.xls .xlsx .doc .docx .png .jpg .bmp .pdf) 首先為了保證excel和word的格式問題,excel和word是調用的office進行列印的。 獲取所有印表機的方法 ...


在前段時間做了一下列印,因為需要支持的格式比較多,所以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群。

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 清晨起床,震驚了,窗外一片雪白,大雪紛飛,我承認我詞窮了,說再多話也描述不了此刻的大好心情。所以,話不多說,先上一張朋友圈的圖吧! 趁著這麼“好的”天氣以及這麼好的心情突然想寫點東西記錄一下自己的2018這一年以及2019年的這一天以及對.NET Core的看法。 俗話說“瑞雪兆豐年”,其實我想說這 ...
  • 第一種,自己手寫dockerfile發佈,上傳至hubDocker 1. 正常發佈到文件夾中,發佈文件上傳至linux機器上。如 /www/app 2. 將Dockerfile文件也複製到同目錄 。/www/app 3. 輸入 ,構建一個demo名字的鏡像。這個時候就會構建鏡像,輸入 可以查看當剛剛 ...
  • 之前都是看別人寫博客,自己沒有寫博客的習慣.在工作的過程中,總是會碰到許多的技術問題.有很多時候想記錄下來,後面一直有許多的問題等著解決.總想著等系統完成了,再回頭總結下.往往結果就把這事拋到腦後了. 總覺得不能一直這樣哈.今天簡單記一下吧.有表達不清楚的地方,多多包涵. 最近在研究.net orm ...
  • https://stackoverflow.com/questions/45875981/error while reading json file in dotnet core the configured user limit 128 on You are creating file watch ...
  • 在 .Net Core 2.2中 Microsoft.AspNetCore.App 預設內置了EntityFramework Core 包,所以在使用過程中,我們無需再從 NuGet 倉庫單獨應用 EFCore 包;本文並不打算深入的介紹 EFCore 的各種使用方式、原理解析,本文重點在於解決讓初... ...
  • 解決方法 定位到csproject 文件夾 問題解決 接下來正常進行CodeFirst操作:生成Migration [name] Upate Database 來源: pass:我會經常修改 不希望被轉載! ...
  • 先看下ASP.NET Core的啟動代碼,如下圖:通過以上代碼,我們可以初步得出以下結論:所有的ASP.NET Core程式本質上也是一個控制台程式,使用Program的Main方法作為程式的入口。控制台Main入口-->IWebHostBuilder-->IWebHost-->Run,發現本質上就... ...
  • asp.net core2.2 "用戶驗證" 和 "授權" 有很詳細和特貼心的介紹,我感興趣的主要是這兩篇: 1. "cookie身份驗證" 2. "基於角色的授權" 我的項目有兩類用戶: 1. 微信公眾號用戶,用戶名為公眾號的openid 2. 企業微信的用戶,用戶名為企業微信的userid 每類 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...