文章出處

如果一臺電腦同時連接多個打印機,而且每個打印機使用的紙張大小各不相同(比如:票據打印錢用的小票專用張,辦公打印機用的是A4標準紙),在處理打印類的需求時,如果不用代碼干預,用戶必須每次打印時,都必須在彈出窗口里,手動選擇打印機(還有可能需要設置紙張類型),這樣用起來會比較煩。

幸好,.Net提供了“二”個很有用的類:PrintDialog(打印機設置對話框)、PageSetupDialog(頁面設置對話框) (注:之所以給“二”加引號,是因為"打印機設置"其實已經完全包含了“頁面設置”的所有功能,而且“ PageSetupDialog”類在實際使用中發現還有一個容易誤導的地方)

一、打印機設置(PrintDialog)

示例代碼:

using System;
using System.Drawing.Printing;
using System.Windows.Forms;

namespace PrintDemo
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();            
        }       

        private void btnPrintSet_Click(object sender, EventArgs e)
        {
            PrintDialog dlg = new PrintDialog();
            if (dlg.ShowDialog() == DialogResult.OK) {               
                ShowInfo(dlg.PrinterSettings);
            }
        }

        private void ShowInfo(PrinterSettings printSettings) { 

            var pageSettings = printSettings.DefaultPageSettings;
            var pageSize = pageSettings.PaperSize;

            label1.Text = string.Format("打印機:{1}{0}紙張類型:{2}{0}紙張大小:{3}cm * {4}cm{0}紙張布局:{5}",
                Environment.NewLine + Environment.NewLine,
                printSettings.PrinterName,
                pageSize.PaperName,
                InchToCm(pageSize.Width / 100.0M).ToString("F2"),
           InchToCm(pageSize.Height / 100.0M).ToString("F2"),
           pageSettings.Landscape ? "橫向" : "縱向");
        
        }

        const decimal K = 2.54M;

        private decimal InchToCm(decimal inch)
        {
            return inch * K;
        }

        private decimal CmToInch(decimal cm) 
        {
            return cm / K;
        }
    }
}

 "打印機設置"對話框的截圖如下:

"打印機設置"對話框調用完成后,可以取回一些有用的信息,下面是一些關鍵信息的展示截圖:

可以看到,打印機設置界面里,已經包含了關于紙張尺寸、紙張布局(縱向、橫向)的設置,所以在我看來,系統沒有必要再單獨提供"頁面設置(PageSetupDialog)"

二、頁面設置(PageSetupDialog)
示例代碼:(在剛才的代碼基礎上加點東西)

using System;
using System.Drawing.Printing;
using System.Windows.Forms;

namespace PrintDemo
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();            
        }       

        /// <summary>
        /// 打印機設置
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnPrintSet_Click(object sender, EventArgs e)
        {
            PrintDialog dlg = new PrintDialog();
            if (dlg.ShowDialog() == DialogResult.OK) {               
                ShowInfo(dlg.PrinterSettings);
            }
        }

        /// <summary>
        /// 頁面設置
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnPageSet_Click(object sender, EventArgs e)
        {
            PageSetupDialog dlg = new PageSetupDialog();
            dlg.PageSettings = new PageSettings();
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                ShowInfo(dlg.PageSettings);
            }
        }

        private void ShowInfo(PrinterSettings printSettings) { 

            var pageSettings = printSettings.DefaultPageSettings;
            var pageSize = pageSettings.PaperSize;

            label1.Text = string.Format("打印機:{1}{0}紙張類型:{2}{0}紙張大小:{3}cm * {4}cm{0}紙張布局:{5}",
                Environment.NewLine + Environment.NewLine,
                printSettings.PrinterName,
                pageSize.PaperName,
                HundredthsInchToCM(pageSize.Width).ToString("F1"),
           HundredthsInchToCM(pageSize.Height).ToString("F1"),
           pageSettings.Landscape ? "橫向" : "縱向");
        
        }

        private void ShowInfo(PageSettings pageSettings)
        {
            var pageSize = pageSettings.PaperSize;
            label1.Text = string.Format("紙張類型:{1}{0}紙張大小:{2}cm * {3}cm{0}紙張布局:{4}{0}頁邊距:{5}",
                Environment.NewLine + Environment.NewLine,
                pageSize.PaperName,
                HundredthsInchToCM(pageSize.Width).ToString("F1"),
           HundredthsInchToCM(pageSize.Height).ToString("F1"),
           pageSettings.Landscape ? "橫向" : "縱向",
           MarginToString(pageSettings.Margins));
        }

        private string MarginToString(Margins margins) {
            return string.Format("左:{0}mm,上:{1}mm,右:{2}mm,下:{3}mm", HundredthsInchToMM(margins.Left), HundredthsInchToMM(margins.Top), HundredthsInchToMM(margins.Right), HundredthsInchToMM(margins.Bottom));                
        }

        const decimal K = 2.54M;       

        /// <summary>
        /// (百分之一)英寸制,轉毫米
        /// </summary>
        /// <returns></returns>
        private int HundredthsInchToMM(decimal d) {
            return  (int)Math.Round((d / 100.00M) * K * 10);
        }

        /// <summary>
        /// (百分之一)英寸制,轉厘米
        /// </summary>
        private decimal HundredthsInchToCM(decimal d)
        {
            return (d / 100.00M) * K;
        }


    }
}

 

這里有一個坑爹的地方,不管你如何選擇Pager Size,最后返回的PageSettings里,PageSize 始終是A4紙的大小(如下圖),這也是我強烈推薦大家盡量避免使用PageSettings的理由

 還有一個問題,如何在彈出這二個對話框時,默認就選中一些特定的值呢?這個容易,參見下面的代碼:

        /// <summary>
        /// 打印機設置
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnPrintSet_Click(object sender, EventArgs e)
        {
            PrintDialog dlg = new PrintDialog();
            dlg.PrinterSettings = new PrinterSettings()
            {
                PrinterName = "pdfFactory Pro"                
            };
            if (dlg.ShowDialog() == DialogResult.OK) {               
                ShowInfo(dlg.PrinterSettings);
            }
        }

 這樣,在彈出打印機設置界面時,就默認選中了"pdfFactory Pro"打印機(當然,這個名字必須確實是你本機安裝的打印機之一,如果這個打印機名字不存在,系統仍將選中默認打印機)

        /// <summary>
        /// 頁面設置
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnPageSet_Click(object sender, EventArgs e)
        {
            PageSetupDialog dlg = new PageSetupDialog();
            dlg.PageSettings = new PageSettings()
            {
                PaperSize = new PaperSize()
                {
                    PaperName = "A5",//其實這里不管設置什么名稱,都沒啥用
                    //一旦設置初始尺寸大小后,在頁面設置對話框里,不管選什么紙張Size,
                    //對話框關閉時,返回值的PageSize里,始終就是這個大小,不會隨用戶選擇而改變
                    Height = 827,
                    Width = 583
                },
                Landscape = false,
                Margins = new Margins() { Left = 10, Top = 20, Bottom = 30, Right = 40 }
            };
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                ShowInfo(dlg.PageSettings);
            }
        }

 這樣,頁面設置對話框彈出時,就默認選中了布局方向為“縱向”,同時設置了邊距,而且紙張大小為A5的大小(注意:PageSize的設置,在界面上看不出效果,但是關閉對話框后,返回值的PageSize里會起作用)

三、RDLC報表用代碼指定打印機、紙張大小、打印份數

rdlc報表的預覽控制ReportViewer里,已經對外暴露了PrinterSettings屬性

        //
        // Summary:
        //     Gets or sets a System.Drawing.Printing.PrinterSettings object that contains
        //     the settings for the default printer and print options that are used to initialize
        //     the Print dialog and the printer's Preferences dialog.
        //
        // Returns:
        //     A System.Drawing.Printing.PrinterSettings object.
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [Browsable(false)]
        public PrinterSettings PrinterSettings { get; set; }

 以及PageSettings的set/get方法

        //
        // Summary:
        //     Returns the page settings that are used to print the current report in the
        //     ReportViewer control or display it in print layout mode.
        //
        // Returns:
        //     A System.Drawing.Printing.PageSettings object that contains the page settings
        //     that are used to print the current report in the ReportViewer control or
        //     display it in print layout mode, or null if the ReportViewer control has
        //     not yet processed a report.
        public PageSettings GetPageSettings();

 

        //
        // Summary:
        //     Sets the page settings that are used to print the current report in the ReportViewer
        //     control or display it in print layout mode.
        //
        // Parameters:
        //   pageSettings:
        //     A System.Drawing.Printing.PageSettings object that contains the new page
        //     settings.This parameter must not be null.
        public void SetPageSettings(PageSettings pageSettings);

 利用這些信息,就足夠控制RDLC的打印機和紙張大小了,比如要指定某臺打印機打印,可以這么做:

            this.reportViewer1.PrinterSettings = new PrinterSettings()
            {
                PrinterName = "pdfFactory Pro"
            };

 要指定RDLC打印時,采用特定的紙張大小,可以參考下面的代碼:

            var pageSettings = this.reportViewer1.GetPageSettings();
            pageSettings.PaperSize = new PaperSize()
                {
                    Height = 100,
                    Width = 50
                };
            pageSettings.Landscape = true;
            this.reportViewer1.SetPageSettings(pageSettings);

打印份數的控制很簡單:PrinterSettings類有一個Copies屬性,直接給它賦值一個short型數字就行了

最后再回到本文最開頭提出的問題,知道如何用代碼影響打印機、紙張大小后,最后可以將PageSettings以及PrinterSettings中的關鍵信息,持久化存儲起來(比如:用xml或DB),下次再進入該業務界面時,根據存儲的配置信息還原相關的設置,這樣用戶只要設置一次,以后就不用每次手動切換打印機或紙張類型了。

 

 


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()