プログラムな日常>C#>
ページ印刷テンプレート
(a sample program to print pages --- C#)

プログラムからの印刷には以下のような注意事項がある。

  1. 単数ページの出力は簡単だが、複数ページの出力構築は、プリンタ接続がマルチタスクになるせいか、意外に面倒。
  2. インチ、ミリメートル間で変換を繰り返し、見通しの悪いプログラムになり易い。
  3. インストールされたプリンタや許容される紙サイズ、フォントファミリーなど、環境へのアクセス。

さらには、

  1. データをファイルから読み、また、書き込む。
  2. 所定の枠に収まるように文をレイアウトする。
  3. 文の一部を選択し、消去、挿入する。
  4. 図形データを表示、編集する。
といった課題があるが、そちらは次回以降ということにして、とりあえずは先の1~3をクリアし、ページを特徴づける最低限の情報である各ページの番号のみを印字するプログラムを作ってみた(末尾にコード)。

このソフトを動かしたところ。


印刷範囲は次のようなダイアログで指定できます。


印刷(この場合PDFへ)したページの一つです。

白い紙なので、色地の上に置きました。


【多数ページ印刷の留意点】

印刷呼び出し機能の核の部分は下図(プログラムの一部)参照。 メニューの印刷を指定した時の処理で最後に実行される thePrinter.Print(); は、プリンタの確認などをした後、このプログラム上ではすぐ次に書いている thePrinter.PrintPage イベントを励起する。 このイベントは印刷されるページ毎に呼び出されるもので、EventArgs から Graphics を抽出し、ここでは paintpage と名付けているルーチンに渡す。 これは、画面のペイントそのものでも良いが、ここでは mydocument.paintpage という関数を別個に置き、共通の呼び出し先としている。 さらに、同 EventArgs オブジェクト下の、 .HasMorePages のセッティングに留意する必要があり、ハンドラ終了時にこれが true だと、同じイベントハンドラが再び呼び出しされる。

特徴的なのは、ここでは「連続してページを出力する」という作業が行われているだけで、ページ番号はそこで必要なことが多い情報だと思うが、EventArgs オブジェクトにはこれが含まれておらず、別途用意しなければならない点だ。 だからこれは、同じ内容のページを複数枚出すとか、一連のページを複数セット出すとかにも応用される一般的な機能として作られているのだろうが、これを Adobe Acrobat などに繋げて使うときには、やはり違和感がある。


【画面スケールの単位の問題】

ディスプレイへの出力を担うのは、OnPaint 関数や、Paint イベントであって、これらは Invalidate 関数や、 Refresh 関数から励起される。 これらが運ぶ EventArgs オブジェクトから、 Graphics オブジェクトを引出すことができるが、この世界の単位は、1が1ピクセルである。 これはまた、Graphics オブジェクトの利用に先立って置かれる TranslateTransform 関数によって平行移動したり、ScaleTransform 関数によってスケール変更したりすることができ、途中からの変更も可能である。

さて、1ピクセルが画面上でどういう大きさかはディスプレイの機能に依存し、常識的な範囲や規格はあるらしいが、割とまちまちである (画面サイズを縦や横のピクセル数で割ったものがピクセル当たりのサイズになる。昔のブラウン管式では、表示の粗さを選べた)。 これに対し、紙への出力は、1ピクセルが 1/100 インチ(0.254mm)となるように統一されていることが多いが、そこは大判専用プリンタなどでは少し違うのだろうとは思う。 このソフトでは、紙上での大きさを、画面背景の市松模様で確認することができる。 正方形の大きさ(一辺)は、40/100 インチ(赤色)または、10mm(青色)で、どちらかを上にして重ね描きされる。

先に述べたスケール変更は、単精度不動小数点数で倍数指定できるので、ピクセルをミリ単位に整合させることは可能であるが、 そういう面倒な変換をするよりも、4ピクセルを1疑似ミリ(1.6 %だけ大きい)と見積もって運用した方が、何かと困難は少ないかと思う。 紙には余白はあるのだから。


【インストールされているプリンタの取得】

プリンタの名前リストは、System.Drawing.Printing.PrinterSettings.InstalledPrinters に収められている。 ここで得た名前(printernamehere)から、プリンタの情報(printerhere)を引出すのは、次のような意外な、と言うか、見慣れない操作による。

この情報の主体は、守備する紙サイズ(PaperSize)のコレクションであり、それは printerhere.PaperSizes として得られる。 この個々のオブジェクトからは、.PaperName, .Width, .Height などが得られる。寸法は何れもピクセル(1/100 インチ)単位である。


【インストールされているフォントの取得】

フォントのコレクションを得るのも、またまた見慣れない別の操作による。

この FontFamily[] の成員(object)から、.Name を引出して活用する(名前とサイズを引数として、new Font(*,*) する)。


PrintPages.cs