TCanvas オブジェクト

Abstract: TCanvas オブジェクトの概要と使い方について、簡単な例を交えてご紹介いたします。

TCanvas オブジェクトは Windows のデバイスコンテキストをカプセル化した描画の実体です。

TCanvas は、Windows の描画プログラムで必要となる、デバイスコンテキストの取得や開放といったわずらわしい手続きを隠蔽し、安全で確実な描画手段を提供します。TCanvas は、TForm や TBitmap、TPrinter などの描画対象の Canvas プロパティとして用意されています。

Canvas は、Pen、Brush、Font プロパティを持ちます。

Pen は、線の描画スタイルを決定します。このプロパティの影響を受けるのは、Arc、LineTo などです。線の色は Pen.Color プロパティで指定します。線の幅は、Pen.Width プロパティで指定します。Pen.Style プロパティによって、線のスタイルを指定できます。ただし、Windows の制限により、Pen.Width に 2 以上を指定したときは、psSolid と psClear 以外の Pen.Style は無効です。Pen.Mode プロパティは、線の描画方法を規定します。例えば、Pen.Mode を pmXOR にすると、お絵描きプログラムの未確定の線描画が実現できます。

   var
     FDown: Boolean;
     FSX,
     FSY,
     FEX,
     FEY  : Integer;
   
   procedure TForm1.FormMouseDown(Sender: TObject;
   Button: TMouseButton;
     Shift: TShiftState; X, Y: Integer);
   begin
     Canvas.Pen.Color:= clYellow;
     Canvas.Pen.Mode := pmXor;
     FDown := True;
     FSX := X;
     FSY := Y;
     FEX := X;
     FEY := Y;
   end;
   
   procedure TForm1.FormMouseUp(Sender: TObject;
     Button: TMouseButton;
     Shift: TShiftState; X, Y: Integer);
   begin
     FDown := False;
     Canvas.Pen.Color:= clBlack;
     Canvas.Pen.Mode := pmCopy;
     Canvas.MoveTo(FSX, FSY);
     Canvas.LineTo(FEX, FEY);
   end;
   
   
   procedure TForm1.FormMouseMove(Sender: TObject;
     Shift: TShiftState; X, Y: Integer);
   begin
     if FDown then begin
       Canvas.MoveTo(FSX, FSY);
       Canvas.LineTo(FEX, FEY);
       Canvas.MoveTo(FSX, FSY);
       Canvas.LineTo(X,Y);
       FEX := X;
       FEY := Y;
     end;
   end;

Brush は、塗りつぶしのスタイルを決定します。

このプロパティの影響を受けるのは、FillRect や FloodFill などの描画メソッドです。また、Rectangle や Pie のように、現在の Pen で輪郭を描画し、図形内部を Brush で塗りつぶすメソッドもあります。塗りつぶす色は、Brush.Color プロパティで指定します。塗りつぶすパターンは、Brush.Style で指定します。Brush.Bitmap は、ユーザー定義のパターンを 8×8 のビットマップで指定できます。Brush.Bitmap プロパティは、Bitmap への参照を指定するので、ビットマップの確保、開放は呼び出し側で行ない、使用が完了した Brush.Bitmap プロパティには、nil をセットしなければなりません。

   var
     Bitmap: TBitmap;
   begin
     Bitmap:= TBitmap.Creat;
     Bitmap.LoadFromFile('Brush.bmp');
     Canvas.Brush.Bitmap := Bitmap;
     Canvas.FillRect(Rect(0, 0, 100, 100));
     Canvas.Brush.Bitmap := nil;
     Bitmap.Free;
   end;

Font プロパティは、TextOut や TextRect で描画する文字列のスタイルを決定します。

Font.Name はフォントの名称を指定します。フォントの色は Font.Color プロパティで、太字や斜体といった属性は Font.Style プロパティで指定します。フォントのサイズは Font.Size プロパティで指定します。この値はポイント数です。ピクセル単位で指定したい場合は、Font.Height プロパティを用います。Font.Size プロパティと Font.Height プロパティの関係は、次の式で表わすことができます。

   Font.Height = 
     Trunc (-Font.Size * Font.PixelsPerInch / 72)

Hide image
fig_01

Font.Height が負数のときは、文字の高さに内部レディングが含まれます。そして、Font.Size は正数になります。一方、Font.Height に正数を指定すると、内部レディングを除いた高さを指定したことになり、Font.Size は負数になります。

文字列の出力では、通常文字列領域を現在のバックグラウンドカラーで塗りつぶします。バックグラウンドカラーは、TCanvas のプロパティを用いて設定することができません。以下のように Windows API を用います。

   SetBkColor(Canvas.Handle, ColorToRGB(clHighlight));

また、背景を透過にしたい場合も、Windows API で以下のように記述します。

   SetBkMode(Canvas.Handle, TRANSPARENT);

TCanvas への描画メソッドには、基本的な図形の描画のほかに、ビットマップやメタファイルの描画メソッドがあります。Draw メソッドは、指定した位置にビットマップやアイコン、メタファイルを表示するものです。これらのグラフィックオブジェクトを特定の領域に伸縮して表示するには、StretchDraw メソッドを用います。

別のキャンバスからイメージをコピーするには、CopyRect メソッドを用います。CopyRect は、指定したキャンバスの特定の領域の内容を、キャンバスの指定した領域に描画します。キャンバスに描画された内容をビットマップオブジェクトに保管するには、TBitmap の Canvas.CopyRect メソッドを用います。以下はフォームに描画された内容をビットマップに保管する例です。

   procedure TForm1.Button1Click(Sender: TObject);
   
   var
     Bitmap: TBitmap;
   begin
     Bitmap := TBitmap.Create;
     Bitmap.Width := ClientWidth;
     Bitmap.Height := ClientHeight;
   Bitmap.Canvas.CopyRect(
     Rect(0,0,ClientWidth,ClientHeight),
       Canvas, Rect(0,0,ClientWidth, ClientHeight));
     Bitmap.SaveToFile('c:\tmp\form.bmp');
     Bitmap.Free;
   end;

TCanvas は、デバイスコンテキストを隠蔽したオブジェクトです。従って、デバイスコンテキストのハンドルである Handle プロパティを用いれば、直接 GDI 関数をコールすることもできます。以下は、Windows API の CreateFontIndirect 関数を用いて、TFont では指定できないスタイルでフォントを生成し、フォームに描画する例です。LogFont 構造体の lfEscapement に 300 を指定して、 30 度の傾きで文字を描画します。

   procedure TForm1.Button1Click(Sender: TObject);
   var
     OrgFont, MyFont : THandle;
     LogFont: TLogFont;
   begin
     with LogFont do begin
       lfHeight := 20;
       lfWidth  := 0;
       lfEscapement  := 300;
       lfOrientation := 0;
       lfWeight := FW_NORMAL;
       lfItalic := 0;
       lfUnderline := 0;
       lfStrikeOut := 0;
       lfCharSet := SHIFTJIS_CHARSET;
       lfOutPrecision  := OUT_DEFAULT_PRECIS;
       lfClipPrecision := CLIP_DEFAULT_PRECIS;
       lfQuality := DEFAULT_QUALITY;
       lfPitchAndFamily := 
           DEFAULT_PITCH or FF_DONTCARE;
       StrCopy(lfFaceName, 'TimesNewRoman');
     end;
     MyFont := CreateFontIndirect(LogFont);
     OrgFont := SelectObject(Canvas.Handle, MyFont);
     Canvas.TextOut(100, 100, Edit1.Text);
     SelectObject(Canvas.Handle, OrgFont);
     DeleteObject(MyFont);
   end;

TCanvas のこのような特性を利用すれば、Delphi でサポートされていないグラフィック API をカプセル化することもできます。