宇宙仮面の
C# Programming

 
Image

Windows.Forms からの印刷

開発環境: Visual Studio 2003

1.目次

2.目的

Windows Forms から印刷する方法です。

3.参考書

(1) 

4.Windows.Forms で印刷するアプリケーションを作る

次のような印刷テストツールを作ります。

Windows.Forms の新規プロジェクトを作成し、ボタンを3つはりつけます。
Image

5.まず、印刷プレビューから作る。

印刷から作ると、印刷がうまくいくのかテストするのに紙が無駄になってしまうので、
印刷プレビューから作りましょう。

(1) ツールボックスより、PrintPreviewDialog をドラッグアンドドロップします。

(2) プレビューボタンをダブルクリックし、ボタンが押されたときのイベントハンドラーを追加します。

印刷プレビューボタンイベント
        private void btnPreview_Click(object sender, System.EventArgs e)
        {
            DialogResult result = this.printPreviewDialog1.ShowDialog();
        }

(3) この段階でコンパイル、実行してみましょう。
   すると、次のような印刷プレビューダイアログが表示されますが、
   ドキュメントにページが含まれていませんと言うメッセージが出て、何もプレビューされません。

Image

これは、プリントダイアログにプレビューするドキュメントがないためです。

(4) このドキュメントのオブジェクトをつかさどるものが PrintDocument です。
では、ツールボックスから PrintDocument をドラッグアンドドロップします。

(5) printDialogBox1 のプロパティを開き、printDocument1 をセットします。
この段階でコンパイル、実行してみましょう。
次のような印刷プレビューダイアログが表示されるはずです。
でも、まだ何もプレビューされません。
ここでプレビューするためには、描画処理を実装しなければなりません。

Image

(6) この描画処理は、PrintDocument の PrintPage イベントでに記述します。
printDocument1 の PrintPage イベントをダブルクリックして、イベントハンドラを追加します。
複数ページの場合には、HasMorePages を true にしてリータンすれば、再度このイベントが呼び出され、次のページを描画できます。

Image

PrintDocument の PrintPage イベント
        private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
        {
            Graphics g = e.Graphics;
            // グラフィクス単位をミリメートル単位にします。
            g.PageUnit = GraphicsUnit.Millimeter;
            // 描画部分 10cmx10cmの四角を描きます。
            g.DrawRectangle(new Pen(Color.Blue, 1F), 50, 50, 100, 100);
            // 次のページは無い。
            e.HasMorePages = false;
        }

ここで、コンパイル実行すると、次のように印刷プレビューを行うことができるようになります。
Image

6.ページセットアップ

次に、ページセットアップをするためのダイアログを出すようにします。

(1) ツールボックスより、PageSetupDialog をドラッグアンドドロップします。
    この PageSetupDialog は、ダイアログを表示するだけなので、そのページセットアップの結果を保持する先のデータが必要です。

(2) そこで、pageSetupDialog1 のプロパティの Document プロパティに次のように、先ほどの printDocument1 を指定します。
    この printDocument1 にページセットアップの結果が保持されることになります。
Image

(3) 次にページセットアップダイアログボタンをダブルクリックし、ボタンが押されたときのイベントハンドラーを追加します。
PageSetup イベント
        private void btnPageSetup_Click(object sender, System.EventArgs e)
        {
            DialogResult result = this.pageSetupDialog1.ShowDialog();        
        }

本当は、これでいいはずなんですが、PageSetupDialog には次のようなバグがあり、それを回避する必要があります。

注意 PageSetupDialog にバグあり! ,NET Framework V1.1
BBS #331 の方より、情報をいただきました。

ページ設定ダイアログにバグがあるようで、ページ設定ダイアログを出して設定するたびに余白が変わってしまいます。
そこで、次のようなコードにする必要があります。

        private void btnPageSetup_Click(object sender, System.EventArgs e)
        {
            if (pageSetupDialog1.ShowDialog() == DialogResult.OK)
            {
                // ページ設定ダイアログにバグがあるようで、
                // ページ設定ダイアログを出して設定するたびに余白が変わってしまいます。
                // ダイアログのマージン数値(ミリ)を変換する。
                int marg;
                marg=(int)(printDocument1.DefaultPageSettings.Margins.Left*2.54);
                printDocument1.DefaultPageSettings.Margins.Left=marg;
                marg=(int)(printDocument1.DefaultPageSettings.Margins.Right*2.54);
                printDocument1.DefaultPageSettings.Margins.Right=marg;
                marg=(int)(printDocument1.DefaultPageSettings.Margins.Top*2.54);
                printDocument1.DefaultPageSettings.Margins.Top=marg;
                marg=(int)(printDocument1.DefaultPageSettings.Margins.Bottom*2.54);
                printDocument1.DefaultPageSettings.Margins.Bottom=marg;
            }
        }


(3) ここでコンパイル、実行してみましょう。
   すると、次のようなっページセットアップダイアログが表示されます。

   Image


7.印刷

次に、印刷するためのダイアログを出すようにします。

(1) ツールボックスより、PrintDialog をドラッグアンドドロップします。
    この PrintDialog は、ダイアログを表示するだけなので、印刷データをセットアップする必要があります。

(2) そこで、printDialog1 のプロパティの Document プロパティに次のように、先ほどの printDocument1 を指定します。
Image

(3) 次に印刷ボタンをダブルクリックし、ボタンが押されたときのイベントハンドラーを追加します。
印刷ボタンイベント
        private void btnPrint_Click(object sender, System.EventArgs e)
        {
            DialogResult result = this.printDialog1.ShowDialog();
        }

(4) ここでコンパイル、実行すると、次のような印刷ダイアログが表示されます。
Image

あとは、印刷範囲、印刷部数、ファイルへの出力など、いろいろなプロパティが用意されていますから、
必要に応じてセットします。それから、各ダイアログの結果に応じて、処理を付け加えます。
また、PrintDocument で BeginPrint, EndPrint イベントでフォントの生成、消滅などの印刷処理全体にかかわる共通処理を記述します。
   

8.ページサイズの変更


ページサイズを変更するには?というBBSへの質問がありましたので、調べました。

プリンタでサポートされている用紙サイズを読み込み、コンボボックスに登録します。
(1) Form_Load イベントを追加して、InitializePaperSizeComboBox() を呼び出すようにします。
(2) コンボボックスを追加します。
(3) InitializePaperSizeComboBox() を次のように実装します。

プリンタでサポートされている用紙サイズを読み込み、コンボボックスに登録
        private void Form1_Load(object sender, System.EventArgs e)
        {
            InitializePaperSizeComboBox();
        }

        // ページサイズのコンボボックスを初期化する。
        private void InitializePaperSizeComboBox()
        {
            PrinterSettings.PaperSizeCollection psizeCollection = this.printDocument1.PrinterSettings.PaperSizes;
            for(int i = 0; i < psizeCollection.Count; i++)
                this.comboBox1.Items.Add(psizeCollection[i].PaperName);
            this.comboBox1.SelectedIndex = 0;
        }

これで、次のようにコンボボックスにデフォルトのページサイズが表示されるようになります。

Image

次に、コンボボックスを変更したときの SelectedValueChanged イベントに次のコードを追加します。
この処理では、コンボボックスの選択したインデックスから、PaperSizeCollection から対応するPaperSize を取得し、
デフォルトページセッティングのペーパーサイズにセットするという処理です。

デフォルトページセッティングのペーパーサイズを変更する。
        // ページサイズのコンボボックスを変更した。
        private void comboBox1_SelectedValueChanged(object sender, System.EventArgs e)
        {
            // PrintDocument のページサイズを変更する。
            PrinterSettings.PaperSizeCollection psizeCollection = this.printDocument1.PrinterSettings.PaperSizes;
            this.printDocument1.DefaultPageSettings.PaperSize = psizeCollection[this.comboBox1.SelectedIndex];
        }

これにより、たとえばA6を指定した場合には、次のようにページセットアップでA6がデフォルトになります。
Image

9.テストコードのソースコード

変更履歴
2003/7/18初版作成
2004/4/3 ページサイズの変更を追加
Form1.cs
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Drawing.Printing;

namespace Print
{
    /// <summary>
    /// Form1 の概要の説明です。
    /// </summary>
    public class Form1 : System.Windows.Forms.Form
    {
        private System.Windows.Forms.Button btnPreview;
        private System.Windows.Forms.Button btnPageSetup;
        private System.Windows.Forms.Button btnPrint;
        private System.Windows.Forms.PrintPreviewDialog printPreviewDialog1;
        private System.Drawing.Printing.PrintDocument printDocument1;
        private System.Windows.Forms.PrintDialog printDialog1;
        private System.Windows.Forms.PageSetupDialog pageSetupDialog1;
        private System.Windows.Forms.ComboBox comboBox1;
        /// <summary>
        /// 必要なデザイナ変数です。
        /// </summary>
        private System.ComponentModel.Container components = null;

        public Form1()
        {
            //
            // Windows フォーム デザイナ サポートに必要です。
            //
            InitializeComponent();

            //
            // TODO: InitializeComponent 呼び出しの後に、コンストラクタ コードを追加してください。
            //
        }

        /// <summary>
        /// 使用されているリソースに後処理を実行します。
        /// </summary>
        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if (components != null) 
                {
                    components.Dispose();
                }
            }
            base.Dispose( disposing );
        }

        #region Windows フォーム デザイナで生成されたコード 
        /// <summary>
        /// デザイナ サポートに必要なメソッドです。このメソッドの内容を
        /// コード エディタで変更しないでください。
        /// </summary>
        private void InitializeComponent()
        {
            System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(Form1));
            this.btnPreview = new System.Windows.Forms.Button();
            this.btnPageSetup = new System.Windows.Forms.Button();
            this.btnPrint = new System.Windows.Forms.Button();
            this.printPreviewDialog1 = new System.Windows.Forms.PrintPreviewDialog();
            this.printDocument1 = new System.Drawing.Printing.PrintDocument();
            this.printDialog1 = new System.Windows.Forms.PrintDialog();
            this.pageSetupDialog1 = new System.Windows.Forms.PageSetupDialog();
            this.comboBox1 = new System.Windows.Forms.ComboBox();
            this.SuspendLayout();
            // 
            // btnPreview
            // 
            this.btnPreview.Location = new System.Drawing.Point(16, 16);
            this.btnPreview.Name = "btnPreview";
            this.btnPreview.Size = new System.Drawing.Size(104, 23);
            this.btnPreview.TabIndex = 0;
            this.btnPreview.Text = "プレビュー";
            this.btnPreview.Click += new System.EventHandler(this.btnPreview_Click);
            // 
            // btnPageSetup
            // 
            this.btnPageSetup.Location = new System.Drawing.Point(16, 56);
            this.btnPageSetup.Name = "btnPageSetup";
            this.btnPageSetup.Size = new System.Drawing.Size(104, 23);
            this.btnPageSetup.TabIndex = 1;
            this.btnPageSetup.Text = "ページセットアップ";
            this.btnPageSetup.Click += new System.EventHandler(this.btnPageSetup_Click);
            // 
            // btnPrint
            // 
            this.btnPrint.Location = new System.Drawing.Point(16, 96);
            this.btnPrint.Name = "btnPrint";
            this.btnPrint.Size = new System.Drawing.Size(104, 23);
            this.btnPrint.TabIndex = 2;
            this.btnPrint.Text = "印刷";
            this.btnPrint.Click += new System.EventHandler(this.btnPrint_Click);
            // 
            // printPreviewDialog1
            // 
            this.printPreviewDialog1.AutoScrollMargin = new System.Drawing.Size(0, 0);
            this.printPreviewDialog1.AutoScrollMinSize = new System.Drawing.Size(0, 0);
            this.printPreviewDialog1.ClientSize = new System.Drawing.Size(400, 300);
            this.printPreviewDialog1.Document = this.printDocument1;
            this.printPreviewDialog1.Enabled = true;
            this.printPreviewDialog1.Icon = ((System.Drawing.Icon)(resources.GetObject("printPreviewDialog1.Icon")));
            this.printPreviewDialog1.Location = new System.Drawing.Point(406, 17);
            this.printPreviewDialog1.MinimumSize = new System.Drawing.Size(375, 250);
            this.printPreviewDialog1.Name = "printPreviewDialog1";
            this.printPreviewDialog1.TransparencyKey = System.Drawing.Color.Empty;
            this.printPreviewDialog1.Visible = false;
            // 
            // printDocument1
            // 
            this.printDocument1.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(this.printDocument1_PrintPage);
            // 
            // printDialog1
            // 
            this.printDialog1.Document = this.printDocument1;
            // 
            // pageSetupDialog1
            // 
            this.pageSetupDialog1.Document = this.printDocument1;
            // 
            // comboBox1
            // 
            this.comboBox1.Location = new System.Drawing.Point(32, 152);
            this.comboBox1.Name = "comboBox1";
            this.comboBox1.Size = new System.Drawing.Size(176, 20);
            this.comboBox1.TabIndex = 3;
            this.comboBox1.SelectedValueChanged += new System.EventHandler(this.comboBox1_SelectedValueChanged);
            // 
            // Form1
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 12);
            this.ClientSize = new System.Drawing.Size(292, 266);
            this.Controls.Add(this.comboBox1);
            this.Controls.Add(this.btnPrint);
            this.Controls.Add(this.btnPageSetup);
            this.Controls.Add(this.btnPreview);
            this.Name = "Form1";
            this.Text = "Form1";
            this.Load += new System.EventHandler(this.Form1_Load);
            this.ResumeLayout(false);

        }
        #endregion

        /// <summary>   
        /// アプリケーションのメイン エントリ ポイントです。
        /// </summary>
        [STAThread]
        static void Main() 
        {
            Application.Run(new Form1());
        }

        private void btnPreview_Click(object sender, System.EventArgs e)
        {
            DialogResult result = this.printPreviewDialog1.ShowDialog();
        }

        private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
        {

            Graphics g = e.Graphics;
            // グラフィクス単位をミリメートル単位にします。
            g.PageUnit = GraphicsUnit.Millimeter;
            // 描画部分 10cmx10cmの四角を描きます。
            g.DrawRectangle(new Pen(Color.Blue, 1F), 50, 50, 100, 100);
            // 次のページは無い。
            e.HasMorePages = false;
        }

        private void btnPageSetup_Click(object sender, System.EventArgs e)
        {
            if (pageSetupDialog1.ShowDialog() == DialogResult.OK)
            {
                // ページ設定ダイアログにバグがあるようで、
                // ページ設定ダイアログを出して設定するたびに余白が変わってしまいます。
                // ダイアログのマージン数値(ミリ)を変換する。
                int marg;
                marg=(int)(printDocument1.DefaultPageSettings.Margins.Left*2.54);
                printDocument1.DefaultPageSettings.Margins.Left=marg;
                marg=(int)(printDocument1.DefaultPageSettings.Margins.Right*2.54);
                printDocument1.DefaultPageSettings.Margins.Right=marg;
                marg=(int)(printDocument1.DefaultPageSettings.Margins.Top*2.54);
                printDocument1.DefaultPageSettings.Margins.Top=marg;
                marg=(int)(printDocument1.DefaultPageSettings.Margins.Bottom*2.54);
                printDocument1.DefaultPageSettings.Margins.Bottom=marg;
            }
        }
        
        private void btnPrint_Click(object sender, System.EventArgs e)
        {
            DialogResult result = this.printDialog1.ShowDialog();
        }

        private void Form1_Load(object sender, System.EventArgs e)
        {
            InitializePaperSizeComboBox();
        }

        // ページサイズのコンボボックスを初期化する。
        private void InitializePaperSizeComboBox()
        {
            PrinterSettings.PaperSizeCollection psizeCollection = this.printDocument1.PrinterSettings.PaperSizes;

            for(int i = 0; i < psizeCollection.Count; i++)
                this.comboBox1.Items.Add(psizeCollection[i].PaperName);
            this.comboBox1.SelectedIndex = 0;
        }

        // ページサイズのコンボボックスを変更した。
        private void comboBox1_SelectedValueChanged(object sender, System.EventArgs e)
        {
            // PrintDocument のページサイズを変更する。
            PrinterSettings.PaperSizeCollection psizeCollection = this.printDocument1.PrinterSettings.PaperSizes;
            this.printDocument1.DefaultPageSettings.PaperSize = psizeCollection[this.comboBox1.SelectedIndex];     
        }
    }
}