Using the printer/ja
│
Deutsch (de) │
English (en) │
español (es) │
日本語 (ja) │
polski (pl) │
中文(中国大陆) (zh_CN) │
はじめに
Lazarus/FreePascal での印刷は簡単です。しかしながら、いくつかのステップを踏む必要があります。第一ステップは共通です。その次からは、さまざまな進んだ印刷技法を学べるようになります。この文書は、必要不可欠なステップをさまざまなネットのフォーラムや例から集めてきたものです。最初のステップの後で、実際に文書を印刷してみます。最後に、更に高度な印刷技法のヒントを提供します。
基本的なステップ
プリンタを使えるようにするには、次の段階を踏まなければなりません: You must do the following to be able to use printers:
- Printer4Lazarus パッケージを、プロジェクトが要求するパッケージに含める。
- Printers ユニットを、プログラムの uses 節に加える。
- 既に存在する Printer オブジェクトを使用する。
Printer4Lazarus パッケージを、プロジェクトが要求するパッケージに含める
Printer4Lazarus パッケージは基本的なプリンタを定義し、プラットフォームに依存しない印刷環境を提供します。さまざまなプラットフォームで、次の事が行えます。 The Printer4Lazarus package defines a basic printer and provides platform independent printing. The following can thus be used on various platforms.
Lazarus IDE で、次のようにしてください:
- プロジェクトメニューで、プロジェクトインスペクタをクリックします。ツリー表示のウインドゥが現れ、その中に、要求されたパッケージという枝があります。初期状態では、その枝にはLCLパッケージがあります。
- 追加ボタンを押します(ウインドゥ上部の+印ボタン)。
- 新規の要求 ページを開きます。
- パッケージ名リストボックスから Printer4Lazarus を選びます。
- OKをクリック。
- これで Printer4Lazarus が要求されたパッケージに現れます。
Printers ユニットをプログラムのユニットの uses 節に加える
このステップは簡単で、こんなふうになるでしょう:
unit MainUnit;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Printers;
既存の Printer オブジェクトを用いる
ボタンを押したら文章を印刷するようにしたいとします。フォームに PrintBtn という名前でボタンを置き、OnClick イヴェントのところにこう書いてください:
procedure TForm1.PrintBtnClick(Sender: TObject);
const
LEFTMARGIN = 100;
HEADLINE = 'I Printed My Very First Text On ';
var
YPos, LineHeight, VerticalMargin: Integer;
SuccessString: String;
begin
with Printer do
try
BeginDoc;
Canvas.Font.Name := 'Courier New';
Canvas.Font.Size := 10;
Canvas.Font.Color := clBlack;
LineHeight := Round(1.2 * Abs(Canvas.TextHeight('I')));
VerticalMargin := 4 * LineHeight;
// There we go
YPos := VerticalMargin;
SuccessString := HEADLINE + DateTimeToStr(Now);
Canvas.TextOut(LEFTMARGIN, YPos, SuccessString);
finally
EndDoc;
end;
end;
先ほど基本的かつ単純と書きました。上記の例はちょっと複雑です。ボールドで基礎的なテキスト出力を行う方法に引き続き、書式を設定する例も示しています。
begin から end までの間に、こんなことが起きています:
- Printer.BeginDoc によって、印刷が始まります。ですが、 Printer.EndDoc を実行するまでプリンタには何も送られません。
- プチンタは描画に Canvas を用います。そこに描かれたものが、最終的に印刷されるページに表示されます。Canvas.Font は Canvas への出力に用いられるフォントオブジェクトです。すなわち、ここで指定されたフォント設定が後の TextOut 呼出しによってテクストを描画する際に用いられるわけです。
- Canvas に描画するものはすべて、座標によって位置決めされる必要があります。そこで、テクストの垂直方向の位置を定めるために LineHeight を計算しています。水平方向の位置も同様に計算します。ここでは LEFTMARGIN に置くことにします。
- テクストは TextOut 呼出しで描画されます。
- Printer.EndDoc によって、この偉業がプリンタに送られます。
フォーラムによっては、PrintDialog(プリンタ選択ダイアログ)を呼び出さないとうまくいかないように書いてありますが、(もはや)そんなことはありません。
次のステップ
上述の基本的なステップを踏んだら、次の段階に進めます。読者には以下の宿題を出しておきましょう:
- 紙に図形を描画する。
- テクストをかっこ良くフォーマットする。
- 他のプリンタを選択して結果を比べる。
Lazarus には、プリンタへの Raw 印刷を用いる例があります。次の場所をみてください。 $(lazarusdir)\components\printers\samples\rawmode\rawmodetest.lpi 他のプリンタを選択する例はこれです: $(lazarusdir)\components\printers\samples\dialogs\selectprinter.lpi
進んだステップ: コントロールの印刷
根本的には、プリンタオブジェクトは Canvas への描画を許し、その Canvas のイメジをプリンタに送るものです。上述の路線で進むなら、プリンタの canvas が持つメソッドを用いてテクストや楕円や菱形やなんかを描画していくことになります。
しかしながらこれは、立派なプログラマには到底興味を持たれるようなものではありません。あなたは今、完璧な CAD ソフトや画像ファイルのソータを書いているところで、あなたのプログラムが生んだ素晴らしい結果をプリンタに送りたいと思っています。完全なピクチャを Canvas メソッド呼出しの集団に翻訳するですって? とんでもない: すでにピクチャは手許にあるのです。
あなたがフォームに置くコントロールは一つ残らず、プリンタと同じように TCanvas オブジェクトにピクチャを描画しているのです。スクリーンからプリンタにピクチャを持ち込むために、これが使えます。
プレビュープログラムを書いているとします。まずフォームを作り、その上に TPanel を置きます。このパネルは、プレビューのすてきな灰色の背景となります。そのパネルの上に、page と呼ばれるもう一つの TPanel を置きます。この page は白色で、紙を表します。ページの大きさもすてきに変更可能です。
このページの上に TShape オブジェクトを一つおきます。例えばすてきな赤の、角が丸い長方形。さてここで、次のコードを PrintBtnClick イヴェントメソッドに置いてみてください:
MyPrinter.BeginDoc;
page.PaintTo(myPrinter.Canvas, 0, 0);
MyPrinter.EndDoc;
何が起きるか:
- BeginDoc が印刷を開始します(が、まだ何も送られません)。
- page.PaintTo は先に作った紙を表す TPanel オブジェクトの出力をプリンタの Canvas に送ります。次のことに注意してください:
- PaintTo メソッドは、コントロールのヒエラルキーの中のどのコントロールのものも使いたければ使えます。
- PaintTo メソッドを持っていれば、どのコントロールからもプリンタに出力を送れるので、いろいろなことができます。画像ソータなら、TImage の出力をプリンタに送れるわけです。
- TCanvas には、矩形領域を他の Canvas にコピーするメソッドがあります。しかし、この機能はそのオブジェクトが実際に Canvas に描画する場合にのみ使えます。思うに、ほとんどのコントロールは実際の Canvas としてコンテナを利用しています。ですから、コントロールから矩形領域のコピーを行うことはできません。少なくとも、私の所ではだめでした。
- 印刷しようとするコントロールが可視であることを確認してください。不可視だと、何もペイントされず、プリンタにも送られません。
- EndDoc によって、描画情報がプリンタに送られます。
更に進もう: リサイジング
プリンタが紙の上の一インチあたり使うピクセルの数は、モニタがスクリーン上の一インチあたり使うピクセルの数よりもはるかに大きくなっています(訳注: プリンタの DPI の方が、モニタの DPI よりずっと大きいということ)。その結果、スクリーンからプリンタにリダイレクトされた出力は、紙の上ではちっぽけになってしまいます。見栄えのする印刷には、スケーリングとレイアウトの制御が大事です。スクリーンで見る大きさと紙の上での大きさが揃っていればすてきでしょう(訳注: 昔のマックのように)。
今の時点では、我々は理想(ideal)を追っているのではなく、理念(idea)を探っているのです。前にも述べた通り、コントロールは描画に自前の Canvas を持っておらず、コンテナあるいはオーナーの Canvas に依存しています。しかし、自前の Canvas を持つコンポーネントもあります。ここでは TBitMap を選びます。次のように働きます。
procedure TForm1.PrintBtnClick(Sender: TObject);
var
MyPrinter : TPrinter;
myBitMap : TBitMap;
begin
myBitMap := TBitMap.Create;
myBitMap.Width := page.Width;
myBitMap.Height := page.Height;
page.BorderStyle:=bsNone;
page.PaintTo(myBitMap.Canvas, 0, 0);
page.BorderStyle:=bsSingle;
//
MyPrinter := Printer;
MyPrinter.BeginDoc;
//page.PaintTo(myPrinter.Canvas, 0, 0);
//myPrinter.Canvas.Draw(0,0, myBitMap);
myPrinter.Canvas.CopyRect(Classes.Rect(0, 0, myPrinter.PaperSize.Width, myPrinter.PaperSize.Height),
myBitMap.Canvas, Classes.Rect(0, 0, myBitMap.Width, myBitMap.Height));
MyPrinter.EndDoc;
myBitMap.Free;
end;
これを動作させるには、Windows ユニットを使わないでください。Windows ユニットは異なった Rect を定義しています。この例ではこんなことが起こります:
- ビットマップが一枚生成され、page コントロールと同じ大きさに設定されます。
- 輪郭が描画されないように、ビットマップへの描画に先立って、page の BorderStyle をオフにしています。描画後、元の値に戻されます。
- 印刷が開始され、BitMap の Canvas の内容がプリンタの Canvas にコピーされます。
page が拡大される時に一つ注意すべきことがあります。Printer.papersize はビットマップの大きさより相当大きいが、コピーされる過程でうまく当てはまるようになるということです。ただし、これがちゃんと働くようにするには、page の縦横比を用紙の縦横比と一致させなければなりません。やり方はわかるでしょう。
このやりかたの問題点は、スクリーンのピクセルが印刷した紙にも出ることです。言ったように、理想ではなく理念を提示したのです。コントロールは自前の Canvas を持っていない、コントロールを印刷するには、自前の Canvas を持つオブジェクト(TBitMap)にまず描画する。さてこれで、読者はそれがどう働くかを知り、精細な図版や文書を作り出す方法を理解することができるようになったわけです。そのためには、自分自身を描画する際に、TPanel には低解像度で、TBitMap には高解像度で行うようなオブジェクトが必要になるでしょう。しかし、それは別の解説書の題材です。
関連項目
- LazReport Documentation LazReport はデータドリブンな報告書を作るのに使えます。それは印刷したり PDF としてエクスポートしたりすることができます。
- LazReport Tutorial