徹底解決 C# 中頁面設置對話框數值變化的 Bug

文章目錄

在使用 C# 做頁面設置時經常會在進行打印時發現下面的問題:當你打開一個 PageSetupDialog 並保存了一個頁邊距後,再次打開該窗口並顯示當前 PageSettings 時,頁邊距會自動變小。

實際上,這是 .NET Framework 的一個 Bug。實際上這是單位轉換的問題。

這個問題可以如下描述:

在出現的頁面設置對話框中,頁邊距的單位是「頁邊距(毫米)」,可是「左、右、上、下」後面的文本框中的數字似乎是當前頁邊距以「百分之一英寸」為單位的數值,而不是以「毫米」為單位數值。

但是當你按下「確定」鍵時,屏幕上的當前的以「百分之一英寸」為單位的頁邊距數值似乎被理解成了以「毫米」為單位的數值,對頁邊距進行設定。  

當你再次按下「頁面設置」按鈕(調用PageSetupDialog類進行頁面設置)時,它又把新的頁邊距以「百分之一英寸」為單位顯示在屏幕上。  

如此反覆,你每次進入「頁面設置」對話框,按「確定」,再進入,再「確定」,頁邊距不斷減少,這可不是我們希望的。

那麼如何解決這個問題呢?網絡上有很多解決方案。最主要是按如下代碼在每次打開設置窗口之後進行單位轉換

PrinterUnitConvert.Convert(mg,   PrinterUnit.Display,   PrinterUnit.TenthsOfAMillimeter); 

有人說,每次保存後,手工進行單位的轉換。可是問題是,美國和中國,一個是公制單位,一個是美國單位,如果在中國大部分情況下沒問題,如果 「Windows 區域設置」不在中國或修改為使用美製單位,那就會產生嚴重的問題。因為此時該 Bug 並不存在。你卻把實際正確的以0.1毫米為單位的內容以百分之一英寸的名義轉成了 0.1 毫米。

所以徹底解決該方法的最好途徑是:重寫代碼,實現自己的頁面設置。

在重寫自己的頁面設置時,有幾個問題值得注意:

如何獲取所有支持的紙張大小列表

使用一個打印機對象的 PaperSizes 屬性獲取該打印機支持的紙張列表。

PrinterSettings s = new PrinterSettings();
pc = s.PaperSizes;

for (int i = 0; i < pc.Count; ++i)  
{  
    // pc\[i\].PaperName :名稱
    // pc\[i\].Width, Height:高度和寬度。  
}

如何橫向打印

PageSettings 類實例的 Landscape 屬性用於設置橫向打印。

如何保存設置

設置可保存在一個 PageSettings 類中。通過 .NET 的 Xml 序列化或自己保存該類的所有字段即可保存頁面設置並隨時用這些保存的數據創建一個一樣的新類用於給 PrintDocument 提供打印設置。

下面是我實現的類供參考。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Printing;

namespace MySpace
{
    public partial class PrintPageSettingsForm : Form
    {
        private System.Drawing.Printing.PrinterSettings.PaperSizeCollection pc = null;
        PageSettings ps = null;
        public PrintPageSettingsForm()
        {
            InitializeComponent();
            this.ps = new PageSettings();
        }
        public PrintPageSettingsForm(ref PageSettings _ps)
        {
            InitializeComponent();
            this.ps = _ps;
        }
        public static PageSettings OpenDialog(IWin32Window parent, ref PageSettings ps)
        {
            (new PrintPageSettingsForm(ref ps)).ShowDialog(parent);
            return ps;
        }
        private void PrintPageSettingsForm_Load(object sender, EventArgs e)
        {
            if (PrinterSettings.InstalledPrinters.Count == 0)
            {
                Error.ShowError("您還沒有安裝打印機。在您打印或頁面設置之前必須安裝一個打印機。");
                return;
            }
            PrinterSettings s = new PrinterSettings();
            this.label2.Text += s.PrinterName;
            pc = s.PaperSizes;
            this.comboBox1.Items.Add("<自定義紙張...>");
            for (int i = 0; i < pc.Count; ++i)
            {
                this.comboBox1.Items.Add(pc[i].PaperName);
            }
            try
            {
                if (ps.PaperSize.PaperName.StartsWith("User"))
                {
                    this.comboBox1.SelectedIndex = 0;
                    swidth.Text = InchToMM(ps.PaperSize.Width).ToString();
                    sheight.Text = InchToMM(ps.PaperSize.Height).ToString();
                }
                else
                    this.comboBox1.SelectedItem = ps.PaperSize.PaperName;
            }
            catch
            {
                try
                {
                    this.comboBox1.SelectedItem = "A4";
                }
                catch
                {
                    this.comboBox1.SelectedIndex = 0;
                }
            }
            this.mleft.Text = ((int)InchToMM(ps.Margins.Left)).ToString();
            this.mright.Text = ((int)InchToMM(ps.Margins.Right)).ToString();
            this.mtop.Text = ((int)InchToMM(ps.Margins.Top)).ToString();
            this.mbottom.Text = ((int)InchToMM(ps.Margins.Bottom)).ToString();
            if (ps.Landscape)
            {
                this.radioButton2.Checked = true;
                this.radioButton1.Checked = false;
            }
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (this.comboBox1.SelectedIndex == 0)
            {
                this.panel1.Visible = true;
                return;
            }
            this.panel1.Visible = false;
            ps.PaperSize = pc[this.comboBox1.SelectedIndex - 1];
            this.label3.Text = "紙張大小:  " + InchToMM(pc[this.comboBox1.SelectedIndex - 1].Width).ToString() + " 毫米 × " + InchToMM(pc[this.comboBox1.SelectedIndex - 1].Height).ToString() + " 毫米";

        }
        private double InchToMM(double inch)
        {
            return Math.Round(PrinterUnitConvert.Convert(inch, PrinterUnit.Display, PrinterUnit.TenthsOfAMillimeter) / 10, 0);
        }
        private int MMToInch(double inch)
        {
            return (int)PrinterUnitConvert.Convert(inch * 10, PrinterUnit.TenthsOfAMillimeter, PrinterUnit.Display);
        }
        private void button2_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            ps.Landscape = this.radioButton2.Checked;
            if (this.comboBox1.SelectedIndex == 0)
            {
                if(double.Parse(this.swidth.Text)<=10 || (double.Parse(this.sheight.Text) <=10))
                {
                    Error.ShowError ("您輸入的紙張寬度或高度無效。");
                    return;
                }
                ps.PaperSize = new PaperSize("User Paper", MMToInch(double.Parse(this.swidth.Text)), MMToInch(double.Parse(this.sheight.Text)));
            }
            ps.Margins.Top = MMToInch(double.Parse(mtop.Text));
            ps.Margins.Left = MMToInch(double.Parse(mleft.Text));
            ps.Margins.Right = MMToInch(double.Parse(this.mright.Text));
            ps.Margins.Bottom = MMToInch(double.Parse(this.mbottom.Text));
            this.Close();
        }
    }
}

設計文件:(PrintPageSettingsForm.Designer.cs)

namespace MySpace
{
    partial class PrintPageSettingsForm
    {
        /// /// Required designer variable.
        /// 
        private System.ComponentModel.IContainer components = null;

        /// /// Clean up any resources being used.
        /// 
        /// true if managed resources should be disposed; otherwise, false.
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// 
        private void InitializeComponent()
        {
            this.label1 = new System.Windows.Forms.Label();
            this.comboBox1 = new System.Windows.Forms.ComboBox();
            this.label2 = new System.Windows.Forms.Label();
            this.label3 = new System.Windows.Forms.Label();
            this.groupBox1 = new System.Windows.Forms.GroupBox();
            this.radioButton2 = new System.Windows.Forms.RadioButton();
            this.radioButton1 = new System.Windows.Forms.RadioButton();
            this.button1 = new System.Windows.Forms.Button();
            this.button2 = new System.Windows.Forms.Button();
            this.groupBox2 = new System.Windows.Forms.GroupBox();
            this.label6 = new System.Windows.Forms.Label();
            this.label7 = new System.Windows.Forms.Label();
            this.label5 = new System.Windows.Forms.Label();
            this.label4 = new System.Windows.Forms.Label();
            this.panel1 = new System.Windows.Forms.Panel();
            this.label9 = new System.Windows.Forms.Label();
            this.label8 = new System.Windows.Forms.Label();
            this.sheight = new CeejiJXC.NumberTextBox();
            this.swidth = new CeejiJXC.NumberTextBox();
            this.mbottom = new CeejiJXC.NumberTextBox();
            this.mtop = new CeejiJXC.NumberTextBox();
            this.mright = new CeejiJXC.NumberTextBox();
            this.mleft = new CeejiJXC.NumberTextBox();
            this.groupBox1.SuspendLayout();
            this.groupBox2.SuspendLayout();
            this.panel1.SuspendLayout();
            this.SuspendLayout();
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(16, 41);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(65, 12);
            this.label1.TabIndex = 0;
            this.label1.Text = "紙張類型: ";
            // 
            // comboBox1
            // 
            this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
            this.comboBox1.FormattingEnabled = true;
            this.comboBox1.Location = new System.Drawing.Point(83, 38);
            this.comboBox1.Name = "comboBox1";
            this.comboBox1.Size = new System.Drawing.Size(343, 20);
            this.comboBox1.TabIndex = 1;
            this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged);
            // 
            // label2
            // 
            this.label2.AutoSize = true;
            this.label2.Location = new System.Drawing.Point(16, 12);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(71, 12);
            this.label2.TabIndex = 2;
            this.label2.Text = "打 印 機:  ";
            // 
            // label3
            // 
            this.label3.AutoSize = true;
            this.label3.Location = new System.Drawing.Point(16, 70);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(65, 12);
            this.label3.TabIndex = 3;
            this.label3.Text = "紙張大小: ";
            // 
            // groupBox1
            // 
            this.groupBox1.Controls.Add(this.radioButton2);
            this.groupBox1.Controls.Add(this.radioButton1);
            this.groupBox1.Location = new System.Drawing.Point(18, 102);
            this.groupBox1.Name = "groupBox1";
            this.groupBox1.Size = new System.Drawing.Size(174, 89);
            this.groupBox1.TabIndex = 4;
            this.groupBox1.TabStop = false;
            this.groupBox1.Text = "打印方向";
            // 
            // radioButton2
            // 
            this.radioButton2.AutoSize = true;
            this.radioButton2.Location = new System.Drawing.Point(20, 52);
            this.radioButton2.Name = "radioButton2";
            this.radioButton2.Size = new System.Drawing.Size(47, 16);
            this.radioButton2.TabIndex = 7;
            this.radioButton2.Text = "橫向";
            this.radioButton2.UseVisualStyleBackColor = true;
            // 
            // radioButton1
            // 
            this.radioButton1.AutoSize = true;
            this.radioButton1.Checked = true;
            this.radioButton1.Location = new System.Drawing.Point(20, 25);
            this.radioButton1.Name = "radioButton1";
            this.radioButton1.Size = new System.Drawing.Size(89, 16);
            this.radioButton1.TabIndex = 6;
            this.radioButton1.TabStop = true;
            this.radioButton1.Text = "縱向 (默認)";
            this.radioButton1.UseVisualStyleBackColor = true;
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(139, 209);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(75, 23);
            this.button1.TabIndex = 5;
            this.button1.Text = "確定";
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.button1_Click);
            // 
            // button2
            // 
            this.button2.Location = new System.Drawing.Point(229, 209);
            this.button2.Name = "button2";
            this.button2.Size = new System.Drawing.Size(75, 23);
            this.button2.TabIndex = 6;
            this.button2.Text = "取消";
            this.button2.UseVisualStyleBackColor = true;
            this.button2.Click += new System.EventHandler(this.button2_Click);
            // 
            // groupBox2
            // 
            this.groupBox2.Controls.Add(this.mbottom);
            this.groupBox2.Controls.Add(this.label6);
            this.groupBox2.Controls.Add(this.mtop);
            this.groupBox2.Controls.Add(this.label7);
            this.groupBox2.Controls.Add(this.mright);
            this.groupBox2.Controls.Add(this.label5);
            this.groupBox2.Controls.Add(this.mleft);
            this.groupBox2.Controls.Add(this.label4);
            this.groupBox2.Location = new System.Drawing.Point(203, 102);
            this.groupBox2.Name = "groupBox2";
            this.groupBox2.Size = new System.Drawing.Size(223, 89);
            this.groupBox2.TabIndex = 7;
            this.groupBox2.TabStop = false;
            this.groupBox2.Text = "邊距設置 (毫米)";
            // 
            // label6
            // 
            this.label6.AutoSize = true;
            this.label6.Location = new System.Drawing.Point(114, 54);
            this.label6.Name = "label6";
            this.label6.Size = new System.Drawing.Size(41, 12);
            this.label6.TabIndex = 8;
            this.label6.Text = "下(&B):";
            // 
            // label7
            // 
            this.label7.AutoSize = true;
            this.label7.Location = new System.Drawing.Point(18, 54);
            this.label7.Name = "label7";
            this.label7.Size = new System.Drawing.Size(41, 12);
            this.label7.TabIndex = 6;
            this.label7.Text = "上(&T):";
            // 
            // label5
            // 
            this.label5.AutoSize = true;
            this.label5.Location = new System.Drawing.Point(114, 27);
            this.label5.Name = "label5";
            this.label5.Size = new System.Drawing.Size(41, 12);
            this.label5.TabIndex = 4;
            this.label5.Text = "右(&R):";
            // 
            // label4
            // 
            this.label4.AutoSize = true;
            this.label4.Location = new System.Drawing.Point(18, 27);
            this.label4.Name = "label4";
            this.label4.Size = new System.Drawing.Size(41, 12);
            this.label4.TabIndex = 0;
            this.label4.Text = "左(&L):";
            // 
            // panel1
            // 
            this.panel1.Controls.Add(this.label9);
            this.panel1.Controls.Add(this.sheight);
            this.panel1.Controls.Add(this.label8);
            this.panel1.Controls.Add(this.swidth);
            this.panel1.Location = new System.Drawing.Point(80, 64);
            this.panel1.Name = "panel1";
            this.panel1.Size = new System.Drawing.Size(346, 27);
            this.panel1.TabIndex = 9;
            this.panel1.Visible = false;
            // 
            // label9
            // 
            this.label9.AutoSize = true;
            this.label9.Location = new System.Drawing.Point(210, 6);
            this.label9.Name = "label9";
            this.label9.Size = new System.Drawing.Size(65, 12);
            this.label9.TabIndex = 12;
            this.label9.Text = "毫米(高度)";
            // 
            // label8
            // 
            this.label8.AutoSize = true;
            this.label8.Location = new System.Drawing.Point(71, 6);
            this.label8.Name = "label8";
            this.label8.Size = new System.Drawing.Size(65, 12);
            this.label8.TabIndex = 10;
            this.label8.Text = "毫米(寬度)";
            // 
            // sheight
            // 
            this.sheight.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
            this.sheight.CanInputDecimal = false;
            this.sheight.Location = new System.Drawing.Point(142, 3);
            this.sheight.Name = "sheight";
            this.sheight.Size = new System.Drawing.Size(62, 21);
            this.sheight.TabIndex = 11;
            this.sheight.Text = "0";
            this.sheight.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
            // 
            // swidth
            // 
            this.swidth.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
            this.swidth.CanInputDecimal = false;
            this.swidth.Location = new System.Drawing.Point(3, 3);
            this.swidth.Name = "swidth";
            this.swidth.Size = new System.Drawing.Size(62, 21);
            this.swidth.TabIndex = 9;
            this.swidth.Text = "0";
            this.swidth.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
            // 
            // mbottom
            // 
            this.mbottom.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
            this.mbottom.CanInputDecimal = false;
            this.mbottom.Location = new System.Drawing.Point(160, 51);
            this.mbottom.Name = "mbottom";
            this.mbottom.Size = new System.Drawing.Size(42, 21);
            this.mbottom.TabIndex = 9;
            this.mbottom.Text = "0";
            this.mbottom.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
            // 
            // mtop
            // 
            this.mtop.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
            this.mtop.CanInputDecimal = false;
            this.mtop.Location = new System.Drawing.Point(65, 51);
            this.mtop.Name = "mtop";
            this.mtop.Size = new System.Drawing.Size(42, 21);
            this.mtop.TabIndex = 7;
            this.mtop.Text = "0";
            this.mtop.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
            // 
            // mright
            // 
            this.mright.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
            this.mright.CanInputDecimal = false;
            this.mright.Location = new System.Drawing.Point(160, 24);
            this.mright.Name = "mright";
            this.mright.Size = new System.Drawing.Size(42, 21);
            this.mright.TabIndex = 5;
            this.mright.Text = "0";
            this.mright.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
            // 
            // mleft
            // 
            this.mleft.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
            this.mleft.CanInputDecimal = false;
            this.mleft.Location = new System.Drawing.Point(65, 24);
            this.mleft.Name = "mleft";
            this.mleft.Size = new System.Drawing.Size(42, 21);
            this.mleft.TabIndex = 3;
            this.mleft.Text = "0";
            this.mleft.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
            // 
            // PrintPageSettingsForm
            // 
            this.AcceptButton = this.button1;
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(442, 248);
            this.Controls.Add(this.panel1);
            this.Controls.Add(this.groupBox2);
            this.Controls.Add(this.button2);
            this.Controls.Add(this.button1);
            this.Controls.Add(this.groupBox1);
            this.Controls.Add(this.label3);
            this.Controls.Add(this.label2);
            this.Controls.Add(this.comboBox1);
            this.Controls.Add(this.label1);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
            this.MaximizeBox = false;
            this.MinimizeBox = false;
            this.Name = "PrintPageSettingsForm";
            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
            this.Text = "頁面設置";
            this.Load += new System.EventHandler(this.PrintPageSettingsForm_Load);
            this.groupBox1.ResumeLayout(false);
            this.groupBox1.PerformLayout();
            this.groupBox2.ResumeLayout(false);
            this.groupBox2.PerformLayout();
            this.panel1.ResumeLayout(false);
            this.panel1.PerformLayout();
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.ComboBox comboBox1;
        private System.Windows.Forms.Label label2;
        private System.Windows.Forms.Label label3;
        private System.Windows.Forms.GroupBox groupBox1;
        private System.Windows.Forms.RadioButton radioButton1;
        private System.Windows.Forms.RadioButton radioButton2;
        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.Button button2;
        private System.Windows.Forms.GroupBox groupBox2;
        private System.Windows.Forms.Label label4;
        private NumberTextBox mleft;
        private System.Windows.Forms.Label label5;
        private NumberTextBox mright;
        private NumberTextBox mbottom;
        private System.Windows.Forms.Label label6;
        private NumberTextBox mtop;
        private System.Windows.Forms.Label label7;
        private System.Windows.Forms.Panel panel1;
        private NumberTextBox swidth;
        private System.Windows.Forms.Label label8;
        private System.Windows.Forms.Label label9;
        private NumberTextBox sheight;
    }
}
当前页阅读量为: