|
Delphi Programming / Object Pascal

[掲載 2012年12月06日] [更新 2012年12月06日] GDI+ 関係サンプル |
GDI+ 関係サンプル
G060_フォントと文字列 |
| 動作確認等 |
Windows 7 U64(SP1) + Delphi XE(UP1) Pro |
 |
G060_GDIPlus_FontAndString.zip [6,788 KB] 2012年12月06日版 (EXE 同梱) |
GDI+ の機能を使用して文字列を描画する際の参考サンプルです。
同じコントロール内で、GDI+ の関数類を使用した描画と、VCL の TCanvas への文字列画像のコードを混在させると、描画が揺れることがあります。その場合は、GDI+ の文字列描画用の関数類を使用することになるでしょう。 |
| 01_文字列の描画 - DrawString, UnitPixel, UnitPoint |
文字列は、TGPGraphics.DrawString 関数を使用します。
フォントは、TGPFont オブジェクトのインスタンスを生成して設定します。
文字の色は、VCL では TFont.Color ですが、GDI+ では TGPBrush を使用します。したがって、いろいろな効果を持たせることができます。
これまでのサンプルでは、描画の位置とサイズの単位として、主に、UnitPixel という、画面のピクセル単位を使用していました。文字列を、画像や図形内に文字列を描画する際、ピクセル単位で指定すれは、描画位置の設定に便利です。
本ページでは、UnitPoint という単位も使用しています。この UnitPixcel は TFont.Size と同じポイント数で設定するものです。UnitPoint の単位は 1/72インチです。
UnitPixel での描画は、文字列の場合、TFont.Height に相当しますが、同じではありません。GDI+ ではフォントサイズに、負の値は指定できません。
次のサンプルでは、この描画単位の効果を確認するために、両方の単位で文字列を描画しています。描画単位の変更に、SetPageUnit 関数を使用しています。
比較として、VCL の TCanvas.Font を使用した文字列も描画しています。
|
 |
図1
設計時画面 |
 |
図2
実行結果
- どの文字列もフォントサイズは 20
- 一番上は、ピクセル単位
- 下の 2 つはポイント数の指定となる
|
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, StdCtrls, GDIPAPI, GDIPOBJ;
type
TMyPanel = class(TPanel)
protected
procedure Paint; override;
end;
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private 宣言 }
MyPanel : TMyPanel;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
//=============================================================================
// フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
Caption := 'GDI+ 文字列の描画';
//描画するコントロールを生成
MyPanel := TMyPanel.Create(Self);
with MyPanel do begin
Parent := Self;
SetBounds(5, 5, Self.ClientWidth - 10, Self.ClientHeight - 10);
DoubleBuffered := True;
ControlStyle := MyPanel.ControlStyle + [csOpaque];
BevelOuter := bvNone;
Visible := True;
Color := clSkyBlue;
ParentBackground := False;
Anchors := [akLeft, akTop, akRight, akBottom];
end;
end;
{ TMyPanel }
//-----------------------------------------------------------------------------
// TMyPanelクラスのPaintメソッド
// 実際の文字列の描画コード
//
// 文字列の描画は、フォント(TGPFont)とブラシ(TGPBrush)のオブジェクトを生成する
// TGPFontは、フォント名、フォントサイズ、フォントスタイル等を設定する
// TGPBrushは、文字の色をブラシとして設定する
//
// フォントは
// LGPFont := TGPFont.Create(Canvas.Handle, HFONT);
// として、第2引数に描画先のCAnvasのLogFont構造体の値を指定することも可能
//
// UnitPixel は、ピクセル単位での文字サイズの設定
// UnitPointは、TFont.sizeと同じく、ポイント数で文字のサイズを設定
//-----------------------------------------------------------------------------
procedure TMyPanel.Paint;
var
LGPGraphic : TGPGraphics;
LGPFont : TGPFont;
LGPBrush : TGPSolidBrush;
LFontSize : Single;
begin
inherited;
LFontSize := 20.0;
//TGFontとTGPSolidBrushのオブジェクトを生成し設定
//文字のサイズをピクセル(ドット)単位で指定
LGPFont := TGPFont.Create('Arial', LFontSize, FontStyleRegular, UnitPixel);
LGPBrush := TGPSolidBrush.Create(MakeColor(255, 0, 0, 0));
//描画先をこのTMyPanelのCanvasに指定して、TGPGraphicsのオブジェクトを生成
LGPGraphic := TGPGraphics.Create(Canvas.Handle);
//そのCanvasに文字列を描画
LGPGraphic.DrawString('UnitPixel', -1, LGPFont, MakePoint(0.0, 0.0), LGPBrush);
//文字のサイズをポイント数で指定して文字列を描画
LGPGraphic.SetPageUnit(UnitPoint);
LGPGraphic.DrawString('UnitPoint', -1, LGPFont, MakePoint(0.0, 30.0), LGPBrush);
//Createしたオブジェクトは解放処理する
LGPFont.Free;
LGPBrush.Free;
LGPGraphic.Free;
//比較のため、VCLのTCanvasを使用して文字列を描画
Canvas.Font.Size := Trunc(LFontSize);
Canvas.Font.Name := 'Arial';
Canvas.TextOut(0, 80, 'UnitPoint VCL TextOut');
end;
end.
文字の色には、TGPPathGradientBrush
以外のブラシが使用できます。
次のサンプルは、リニアグラデーションを使用した例です。 |
 |
図3
設計時画面 |
 |
図4
実行結果 |
| ブラシの適用範囲が、実際の文字列の描画範囲より少ないと、下図のようになってしまいます。 |
 |
図5
ブラシの適用範囲に注意 |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, StdCtrls, GDIPAPI, GDIPOBJ;
type
TMyPanel = class(TPanel)
protected
procedure Paint; override;
end;
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private 宣言 }
MyPanel : TMyPanel;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
//=============================================================================
// フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
Caption := 'GDI+ 文字列の描画';
//描画するコントロールを生成
MyPanel := TMyPanel.Create(Self);
with MyPanel do begin
Parent := Self;
SetBounds(5, 5, Self.ClientWidth - 10, Self.ClientHeight - 10);
DoubleBuffered := True;
ControlStyle := MyPanel.ControlStyle + [csOpaque];
BevelOuter := bvNone;
Visible := True;
Color := clWhite;
ParentBackground := False;
Anchors := [akLeft, akTop, akRight, akBottom];
end;
end;
{ TMyPanel }
//-----------------------------------------------------------------------------
// TMyPanelクラスのPaintメソッド
// 実際の描画コード
//-----------------------------------------------------------------------------
procedure TMyPanel.Paint;
var
LGPGraphic : TGPGraphics;
LGPFont : TGPFont;
LGPBrush : TGPLinearGradientBrush;
LFontSize : Single;
begin
inherited;
LFontSize := 80.0;
//TGPFontとTGPSolidBrushのオブジェクトを生成し設定
//太字のイタリック体とし、文字のサイズをポイント数で指定
LGPFont := TGPFont.Create('Arial', LFontSize, FontStyleBoldItalic, UnitPoint);
//リニアグラデーションを設定
LGPBrush := TGPLinearGradientBrush.Create(MakeRect(0, 10, 400, 50),
MakeColor(255, 0, 255, 0),
MakeColor(255, 0, 0, 255),
LinearGradientModeHorizontal);
//描画先をこのTMyPanelのCanvasに指定して、TGPGraphicsのオブジェクトを生成
LGPGraphic := TGPGraphics.Create(Canvas.Handle);
//そのCanvasに文字列を描画
LGPGraphic.DrawString('Delphi', -1, LGPFont, MakePoint(0.0, 10.0), LGPBrush);
//Createしたオブジェクトは解放処理する
LGPFont.Free;
LGPBrush.Free;
LGPGraphic.Free;
end;
end.
| 03_GDI+ の描画内容をプリンタへ出力 - UnitMillimeter |
描画の単位を UnitMillimeter にすると、ミリメートル単位での描画となります。
プリンタへ出力する際、この単位で描画すれば、単位の換算が必要ありません。画面上でも、この単位でのサイズに換算して表示します。この描画単位の設定は、文字列だけでなく、GDI+ の描画全てに共通です。
次のサンプルは、この単位で描画し、プリンタへ出力します。画面への描画とプリンタへの出力の両方で描画コードを共有するために、描画先の TCanvas を引数にした DrawRoutine というメソッドを実装しています。
|
 |
図6
設計時画面 |
 |
図7
実行画面 |
 |
図8
[印刷] ボタンをクリック |
リスト3
GDI+ の描画内容をプリンタへ出力
描画コードは、画面と印刷用と同じ。違うのは出力先の Canvas |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, StdCtrls, GDIPAPI, GDIPOBJ;
type
TMyPanel = class(TPanel)
protected
procedure Paint; override;
public
procedure DrawRoutine(ACanvas: TCanvas);
end;
TForm1 = class(TForm)
Button1: TButton;
PrintDialog1: TPrintDialog;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
MyPanel : TMyPanel;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses
Printers;
{$R *.DFM}
//=============================================================================
// フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
Caption := 'GDI+ の描画をプリンタへ出力';
//描画するコントロールを生成
MyPanel := TMyPanel.Create(Self);
with MyPanel do begin
Parent := Self;
SetBounds(5, 35, Self.ClientWidth - 10, Self.ClientHeight - 40);
DoubleBuffered := True;
ControlStyle := MyPanel.ControlStyle + [csOpaque];
BevelOuter := bvNone;
Visible := True;
Color := clWhite;
ParentBackground := False;
Anchors := [akLeft, akTop, akRight, akBottom];
end;
end;
//=============================================================================
// [印刷]ボタン
// TMyPanelのDrawRoutineメソッドを実行して、描画コードをTPrinter.Canvasに出力
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
if not Assigned(MyPanel) then exit;
if PrintDialog1.Execute then begin
Printer.BeginDoc;
try
MyPanel.DrawRoutine(Printer.Canvas);
finally
Printer.EndDoc;
end;
end;
end;
{ TMyPanel }
//-----------------------------------------------------------------------------
// TMyPanelクラスのPaintメソッド
// 実際の描画コードはDrawRoutineメソッドで行う
//-----------------------------------------------------------------------------
procedure TMyPanel.Paint;
begin
inherited;
DrawRoutine(Canvas);
end;
//-----------------------------------------------------------------------------
// TMyPanelクラスのPaintメソッド
// 実際の描画コード
// 引数のACanvasは描画先のTCanvas
// TPrinter.Canvasにすればプリンタへの出力となる
//-----------------------------------------------------------------------------
procedure TMyPanel.DrawRoutine(ACanvas: TCanvas);
var
LGPGraphic : TGPGraphics;
LGPFont : TGPFont;
LGPBrush : TGPLinearGradientBrush;
LFontSize : Single;
begin
inherited;
LFontSize := 27.0;
//TGPFontとTGPSolidBrushのオブジェクトを生成し設定
//太字のイタリック体とし、文字のサイズをミリメートル単位で指定
LGPFont := TGPFont.Create('Arial', LFontSize, FontStyleBoldItalic, UnitMillimeter);
//リニアグラデーションを設定
LGPBrush := TGPLinearGradientBrush.Create(MakeRect(0, 10, 400, 50),
aclRed,
aclRoyalBlue,
LinearGradientModeHorizontal);
//描画先を引数のCanvasに指定して、TGPGraphicsのオブジェクトを生成
LGPGraphic := TGPGraphics.Create(ACanvas.Handle);
//そのCanvasに文字列を描画
LGPGraphic.DrawString('Delphi', -1, LGPFont, MakePoint(10.0, 10.0), LGPBrush);
//Createしたオブジェクトは解放処理する
LGPFont.Free;
LGPBrush.Free;
LGPGraphic.Free;
end;
end.
書式を指定して文字列を描画するには、TGPStringFormat オブジェクトのインスタンスを生成して、その関数、SetFormatFlags で設定します。
次のサンプルは、縦書きを指定して、改行後の文字列を左側に描画する例です。
題材は JUNKI さんのサイトのものをお借りしました。 |
表1
書式設定用関数、SetFormatFlags で指定可能な値。複数のフラグの指定が可能 |
| StringFormatFlagsDirectionRightToLeft |
改行後の文字の描画位置を現在の左側とする |
| StringFormatFlagsDirectionVertical |
縦方向に描画する |
| StringFormatFlagsNoFitBlackBox |
英小文字の f 等のオーバーハングがある文字の扱い方のようであるが、効果は確認できず |
| StringFormatFlagsDisplayFormatControl |
制御文字の出力 |
| StringFormatFlagsNoFontFallback |
指定フォントにない文字を代替フォントで表示
デフォルトでは、指定フォントにない文字は、白い四角の文字を使用する |
| StringFormatFlagsMeasureTrailingSpaces |
文字列末尾の空白 (半角・全角共)も文字列に含める
これを指定しないと、末尾の空白はアライメントの際に無視される |
| StringFormatFlagsNoWrap |
領域指定の文字列描画の際、自動改行を無効にする |
| StringFormatFlagsLineLimit |
複数行表示の際の設定
これを設定すると、文字本体が完全に矩形領域内に描画できない場合は、その行の文字列を描画しない |
| StringFormatFlagsNoClip |
MSDN の記事からは、描画領域をクリップしないで描画すると解釈できるが、今回は縦方向のみ確認できた
グリフ部の描画関係の設定ではないかと思われる |
 |
図9
設計時画面 |
 |
図10
実行画面
|
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, StdCtrls, GDIPAPI, GDIPOBJ;
type
TMyPanel = class(TPanel)
private
FStartPoint : TGPPointF;
FFontName : string;
FFontSize : Single;
FFontColor : Cardinal;
FText : string;
protected
procedure Paint; override;
public
constructor Create(AOwner: TComponent); override;
end;
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private 宣言 }
MyPanel : TMyPanel;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
//=============================================================================
// フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
Caption := 'GDI+ 縦書き文章';
MyPanel := TMyPanel.Create(Self);
with MyPanel do begin
Parent := Self;
SetBounds(5, 5, Self.ClientWidth - 10, Self.ClientHeight - 10);
DoubleBuffered := True;
ControlStyle := MyPanel.ControlStyle + [csOpaque];
BevelOuter := bvNone;
Visible := True;
Color := clWhite;
ParentBackground := False;
Anchors := [akLeft, akTop, akRight, akBottom];
end;
end;
{ TMyPanel }
//-----------------------------------------------------------------------------
// コンストラクタ
// 背景に描画する画像用のビットマップ生成
// 文字列関係のプロパティを設定
// HG行書体はMicrosoft Officeに含まれている
//-----------------------------------------------------------------------------
constructor TMyPanel.Create(AOwner: TComponent);
begin
inherited;
FStartPoint := MakePoint(220.0, 15.0);
FFontName := 'HG行書体';
FFontSize := 30;
FFontColor := MakeColor(255, 0, 0, 0);
FText := '潮かをる北の浜辺の' + sLineBreak +
'砂山のかの浜薔薇よ' + sLineBreak +
'今年も咲けるや' + sLineBreak +
' 石川啄木';
end;
//-----------------------------------------------------------------------------
// TMyPanelクラスのPaintメソッド
// 実際の描画コード
//
// StringFormatFlagsDirectionVerticalで縦書き指定
// StringFormatFlagsDirectionRightToLeftで改行後の次の行が左側となる
// 描画開始位置は、右上となるので注意
//-----------------------------------------------------------------------------
procedure TMyPanel.Paint;
var
LBitmap : TBitmap;
LGPGraphic : TGPGraphics;
LGPFontFamily : TGPFontFamily;
LGPStrFormat : TGPStringFormat;
LGPFont : TGPFont;
LGPBrush : TGPSolidBrush;
begin
inherited;
//サンプルの趣旨と関係ないが、背景に画像を表示してみる
LBitmap := TBitmap.Create;
try
LBitmap.SetSize(Width, Height);
LBitmap.LoadFromFile('Hachi.bmp');
LBitmap.Canvas.StretchDraw(ClientRect, LBitmap);
Canvas.Draw(0, 0, LBitmap, 80);
finally
FreeAndNil(LBitmap);
end;
//フォント名とフォントサイズ等を設定
LGPFontFamily := TGPFontfamily.Create(FFontName);
LGPFont := TGPFont.Create(LGPFontFamily,
FFontSize,
FontStyleRegular,
UnitPixel);
//TGPStringFormatを生成して、縦書きの設定
LGPStrFormat := TGPStringFormat.Create();
LGPStrFormat.SetFormatFlags(StringFormatFlagsDirectionVertical or
StringFormatFlagsDirectionRightToLeft);
//文字のブラシ(色)を設定
LGPBrush := TGPSolidBrush.Create(FFontColor);
//描画先をこのコントロールのCanvasにしてTGPGraphicsを生成して描画
LGPGraphic := TGPGraphics.Create(Canvas.Handle);
LGPGraphic.DrawString(FText, -1, LGPFont, FStartPoint, LGPStrFormat, LGPBrush);
//Createしたオブジェクトは解放処理する
LGPFontFamily.Free;
LGPStrFormat.Free;
LGPFont.Free;
LGPBrush.Free;
LGPGraphic.Free;
end;
end.
| 右寄せ等、描画のアライメントの設定は、同じく TGPStringFormat の SetAlignment 関数で指定します。下表は指定可能な値です。 |
| StringAlignmentNear |
左端または上端寄せ |
| StringAlignmentCenter |
中央 |
| StringAlignmentFar |
右端または下端寄せ |
 |
図11
設計時画面 |
 |
図12
実行時画面
|
 |
図13
上下左右共に中央の場合 |
 |
図14
右寄せで上下の中央の場合 |
文字列の末尾に半角または全角の空白文字が含まれている場合、空白文字を描画領域内に描画するかを指定することができます。
SetFormatFlags 関数の引数に、StringFormatFlagsMeasureTrailingSpaces を含めると、この空白分も描画します。このフラグの指定がない場合、空白分は描画しません。デフォルトでは、このフラグは含まれていません。 |
 |
図15
空白文字も描画 |
| 次の図は、日本語を描画したものです。上の結果の図でもそうですが、英文字では、上に少し余白があります。 |
 |
図16
日本語と英文字の比較 |
かって印刷は、活字と言われる金属片の 1つ 1 の文字を組み合わせて行われていました。これを活版印刷と呼んでいます。
この文字、タイポグラフィの単位として、下図のような、em-square というのが使われています。これらの用語は、1440 年代のヨハン・グーテンベルクの時代から、いまでもフォントの用語に使用されています。1 em-square はポイントサイズと同じ幅の空白を意味します。
英文字は、外部レディングを除いた内部に描画されますが、日本語は em-squre 内に描画されます。つまり、日本語は、同じポイント数でも、英文字よりも大きいサイズとなります。この方が全体的にバランスが良くなることから、一般的に使用されています。
|
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, StdCtrls, GDIPAPI, GDIPOBJ;
type
TMyPanel = class(TPanel)
protected
procedure Paint; override;
end;
TForm1 = class(TForm)
RadioGroup1: TRadioGroup;
RadioGroup2: TRadioGroup;
CheckBox1: TCheckBox;
procedure FormCreate(Sender: TObject);
procedure RadioGroup1Click(Sender: TObject);
procedure RadioGroup2Click(Sender: TObject);
procedure CheckBox1Click(Sender: TObject);
private
{ Private 宣言 }
MyPanel : TMyPanel;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses
TypInfo;
{$R *.DFM}
//=============================================================================
// フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
var
i : Integer;
begin
Caption := 'GDI+ 文字列のアライメント';
//描画するコントロールを生成
MyPanel := TMyPanel.Create(Self);
with MyPanel do begin
Parent := Self;
SetBounds(5, 110, Self.ClientWidth - 10, Self.ClientHeight - 115);
DoubleBuffered := True;
ControlStyle := MyPanel.ControlStyle + [csOpaque];
BevelOuter := bvNone;
Visible := True;
Color := clWhite;
ParentBackground := False;
Anchors := [akLeft, akTop, akRight, akBottom];
end;
//アライメントの選択項目を作成
for i := 0 to 2 do begin
RadioGroup1.Items.Add(GetEnumName(TypeInfo(TStringAlignment), i));
end;
RadioGroup2.Items.Text := RadioGroup1.Items.Text;
RadioGroup1.ItemIndex := 0;
RadioGroup2.ItemIndex := 0;
//文字列末尾の空白もアライメントの対象にする設定
CheckBox1.Caption := 'StringFormatFlagsMeasureTrailingSpaces';
end;
//=============================================================================
// RadioGroup1のOnClickイベント
// 選択したら、MyPanel1を再描画
//=============================================================================
procedure TForm1.RadioGroup1Click(Sender: TObject);
begin
if not Assigned(MyPanel) then exit;
MyPanel.Invalidate;
end;
//=============================================================================
// RadioGroup2のOnClickイベント
// 選択したら、MyPanel1を再描画
//=============================================================================
procedure TForm1.RadioGroup2Click(Sender: TObject);
begin
if not Assigned(MyPanel) then exit;
MyPanel.Invalidate;
end;
//=============================================================================
// ChekcBoox1のOnClickイベント
// 操作したら、MyPanel1を再描画
//=============================================================================
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
if not Assigned(MyPanel) then exit;
MyPanel.Invalidate;
end;
{ TMyPanel }
//-----------------------------------------------------------------------------
// TMyPanelクラスのPaintメソッド
// 実際の描画コード
//
// Form1の値を参照しているが、本来はTMyPanelのプロパティにすべき
//-----------------------------------------------------------------------------
procedure TMyPanel.Paint;
var
LGPGraphic : TGPGraphics;
LGPFont : TGPFont;
LGPStrFormat : TGPStringFormat;
LGPBrush : TGPSolidBrush;
LGPPen : TGPPen;
LGPRect : TGPRectF;
begin
inherited;
//描画範囲の矩形領域を設定
LGPRect := MakeRect(30.0, 20.0, 250.0, 100.0);
//TGPFontのオブジェクトを生成し設定
//太字とし、文字のサイズをポイント数で指定
LGPFont := TGPFont.Create('Arial', 30, FontStyleBold, UnitPoint);
//TGPStringFormatを生成してアライメントを設定
LGPStrFormat := TGPStringFormat.Create;
//横方向のアライメント
LGPStrFormat.SetAlignment(TStringAlignment(Form1.RadioGroup1.ItemIndex));
//横方向のアライメント
LGPStrFormat.SetLineAlignment(TStringAlignment(Form1.RadioGroup2.ItemIndex));
//文字列の末尾の空白文字の扱い
if Form1.CheckBox1.Checked then begin
LGPStrFormat.SetFormatFlags(StringFormatFlagsMeasureTrailingSpaces or
StringFormatFlagsNoFitBlackBox);
end;
//ブラシで文字の色を設定
LGPBrush := TGPSolidBrush.Create(MakeColor(255, 0, 0, 0));
//確認用の矩形を描画するペンを設定
LGPPen := TGPPen.Create(aclBlack);
//描画先をこのTMyPanelのCanvasに指定して、TGPGraphicsのオブジェクトを生成
LGPGraphic := TGPGraphics.Create(Canvas.Handle);
//描画領域を示す矩形を描画
LGPGraphic.DrawRectangle(LGPPen, LGPRect);
//Canvasに文字列を描画
LGPGraphic.DrawString('Delphi ', -1, LGPFont, LGPRect, LGPStrFormat, LGPBrush);
//Createしたオブジェクトは解放処理する
LGPPen.Free;
LGPFont.Free;
LGPStrFormat.Free;
LGPBrush.Free;
LGPGraphic.Free;
end;
end.
改行文字で区切られた複数行の文字列も、書式の設定が使えます。そのテストプログラムです。
複数行の場合、StringFormatFlagsNoWrap を指定すると、折り返し表示をしなくなります。 |
 |
図17
設計時画面 |
 |
図18
デフォルトの設定の場合 |
 |
図19
左右の中央に描画 |
 |
図20
折り返し表示なし |
 |
図21
「メイリオ」にした場合 |
リスト6
複数行の文字列のアライメント設定のテストプログラム |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, StdCtrls, GDIPAPI, GDIPOBJ;
type
TMyPanel = class(TPanel)
private
FStringList : TStringList;
protected
procedure Paint; override;
procedure SetParent(AParent: TWinControl); override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
TForm1 = class(TForm)
RadioGroup1: TRadioGroup;
RadioGroup2: TRadioGroup;
CheckBox1: TCheckBox;
procedure FormCreate(Sender: TObject);
procedure RadioGroup1Click(Sender: TObject);
procedure RadioGroup2Click(Sender: TObject);
procedure CheckBox1Click(Sender: TObject);
private
{ Private 宣言 }
MyPanel : TMyPanel;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses
TypInfo;
{$R *.DFM}
//=============================================================================
// フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
var
i : Integer;
begin
Caption := 'GDI+ 複数行の表示';
//描画するコントロールを生成
MyPanel := TMyPanel.Create(Self);
with MyPanel do begin
Parent := Self;
SetBounds(5, 110, Self.ClientWidth - 10, Self.ClientHeight - 115);
DoubleBuffered := True;
ControlStyle := MyPanel.ControlStyle + [csOpaque];
BevelOuter := bvNone;
Visible := True;
Color := clWhite;
ParentBackground := False;
Anchors := [akLeft, akTop, akRight, akBottom];
end;
//アライメントの選択項目を作成
for i := 0 to 2 do begin
RadioGroup1.Items.Add(GetEnumName(TypeInfo(TStringAlignment), i));
end;
RadioGroup2.Items.Text := RadioGroup1.Items.Text;
RadioGroup1.ItemIndex := 0;
RadioGroup2.ItemIndex := 0;
//自動改行の設定
CheckBox1.Caption := 'StringFormatFlagsNoWrap';
end;
//=============================================================================
// RadioGroup1のOnClickイベント
// 選択したら、MyPanel1を再描画
//=============================================================================
procedure TForm1.RadioGroup1Click(Sender: TObject);
begin
if not Assigned(MyPanel) then exit;
MyPanel.Invalidate;
end;
//=============================================================================
// RadioGroup2のOnClickイベント
// 選択したら、MyPanel1を再描画
//=============================================================================
procedure TForm1.RadioGroup2Click(Sender: TObject);
begin
if not Assigned(MyPanel) then exit;
MyPanel.Invalidate;
end;
//=============================================================================
// ChekcBoox1のOnClickイベント
// 操作したら、MyPanel1を再描画
//=============================================================================
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
if not Assigned(MyPanel) then exit;
MyPanel.Invalidate;
end;
{ TMyPanel }
//-----------------------------------------------------------------------------
// コンストラクタ
// ディスクから読み出すファイルのテキストを格納するTStringListを生成
//-----------------------------------------------------------------------------
constructor TMyPanel.Create(AOwner: TComponent);
begin
inherited;
FStringList := TStringList.Create;
end;
//-----------------------------------------------------------------------------
// デストラクタ
//-----------------------------------------------------------------------------
destructor TMyPanel.Destroy;
begin
FreeAndNil(FStringList);
inherited;
end;
//-----------------------------------------------------------------------------
// SetParentメソッド
// ディスクからテキストファイルを読み出す
//-----------------------------------------------------------------------------
procedure TMyPanel.SetParent(AParent: TWinControl);
begin
inherited;
if not Assigned(FStringList) then exit;
FStringList.LoadFromFile('AAA.txt');
end;
//-----------------------------------------------------------------------------
// TMyPanelクラスのPaintメソッド
// 実際の描画コード
//
// Form1の値を参照しているが、本来はTMyPanelのプロパティにすべき
//-----------------------------------------------------------------------------
procedure TMyPanel.Paint;
var
LGPGraphic : TGPGraphics;
LGPFont : TGPFont;
LGPStrFmt : TGPStringFormat;
LGPBrush : TGPSolidBrush;
LGPPen : TGPPen;
LGPRect : TGPRectF;
begin
inherited;
//描画範囲の矩形領域を設定
LGPRect := MakeRect(20.0, 20.0, 250.0, 150.0);
//TGPFontのオブジェクトを生成し設定
//文字のサイズをポイント数で指定
LGPFont := TGPFont.Create('MS Pゴシック', 10, FontStyleRegular, UnitPoint);
//TGPStringFormatを生成してアライメントを設定
LGPStrFmt := TGPStringFormat.Create;
//横方向のアライメント
LGPStrFmt.SetAlignment(TStringAlignment(Form1.RadioGroup1.ItemIndex));
//横方向のアライメント
LGPStrFmt.SetLineAlignment(TStringAlignment(Form1.RadioGroup2.ItemIndex));
//自動改行の設定
if Form1.CheckBox1.Checked then begin
LGPStrFmt.SetFormatFlags(StringFormatFlagsNoWrap);
end;
//ブラシで文字の色を設定
LGPBrush := TGPSolidBrush.Create(MakeColor(255, 0, 0, 0));
//確認用の矩形を描画するペンを設定
LGPPen := TGPPen.Create(aclBlack);
//描画先をこのTMyPanelのCanvasに指定して、TGPGraphicsのオブジェクトを生成
LGPGraphic := TGPGraphics.Create(Canvas.Handle);
//描画領域を示す矩形を描画
LGPGraphic.DrawRectangle(LGPPen, LGPRect);
//Canvasにディスクから読み出したテキストを描画
LGPGraphic.DrawString(FStringList.Text, -1, LGPFont, LGPRect, LGPStrFmt, LGPBrush);
//Createしたオブジェクトは解放処理する
LGPPen.Free;
LGPFont.Free;
LGPStrFmt.Free;
LGPBrush.Free;
LGPGraphic.Free;
end;
end.
システムにインストールされているフォントの一覧を取得するサンプルです。
TGPInstalledFontCollection の GetFamilies 関数を使用します。 |
 |
図22
設計時画面
|
 |
図23
実行画面
- TListBox のフォント名をクリックすると、そのフォントでフォント名の文字列を描画する
- 環境によっては、描画しないフォントがある
|
リスト7
システムにインストールされているフォント情報を取得するサンプル |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, StdCtrls, GDIPAPI, GDIPOBJ;
type
TMyPanel = class(TPanel)
private
FpFontFamily : array of TGPFontFamily;
FFontNumber : Integer;
FFontCount : Integer;
FFontList : TStringList;
procedure SetFontNumber(const Value: Integer);
protected
procedure Paint; override;
procedure SetParent(AParent: TWinControl); override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
property FontNumber : Integer read FFontNumber write SetFontNumber;
property FontCount : Integer read FFontCount;
property FontList : TStringList read FFontList;
end;
TForm1 = class(TForm)
ListBox1: TListBox;
procedure FormCreate(Sender: TObject);
procedure ListBox1Click(Sender: TObject);
private
{ Private 宣言 }
MyPanel : TMyPanel;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
//=============================================================================
// フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
Caption := 'GDI+ インストール済みのフォント';
ListBox1.Anchors := [akLeft, akTop, akBottom];
//描画するコントロールを生成
MyPanel := TMyPanel.Create(Self);
with MyPanel do begin
Parent := Self;
SetBounds(ListBox1.Width + 10, 5, Self.ClientWidth - 105, Self.ClientHeight - 10);
DoubleBuffered := True;
ControlStyle := MyPanel.ControlStyle + [csOpaque];
BevelOuter := bvNone;
Visible := True;
Color := clWhite;
ParentBackground := False;
Anchors := [akLeft, akTop, akRight, akBottom];
end;
ListBox1.Items := MyPanel.FontList;
ListBox1.ItemIndex := 0;
end;
//=============================================================================
// ListBox1のOnClickイベント
// ListBox1で選択したフォントを表示する
//=============================================================================
procedure TForm1.ListBox1Click(Sender: TObject);
begin
if not Assigned(MyPanel) then exit;
MyPanel.FontNumber := ListBox1.ItemIndex;
end;
{ TMyPanel }
//-----------------------------------------------------------------------------
// コントラクタ
//-----------------------------------------------------------------------------
constructor TMyPanel.Create(AOwner: TComponent);
begin
inherited;
SetLength(FpFontFamily, 0);
FFontCount := 0;
FFontNumber := -1;
FFontList := TStringList.Create;
end;
//-----------------------------------------------------------------------------
// デコントラクタ
//-----------------------------------------------------------------------------
destructor TMyPanel.Destroy;
var
i : Integer;
begin
//Createしたオブジェクトは解放処理する
FreeAndNil(FFontList);
for i := 0 to Length(FpFontFamily) - 1 do begin
FpFontFamily[i].Free;
end;
inherited;
end;
//-----------------------------------------------------------------------------
// SetParentメソッド
// 親コントロールが設定されたら、フォントの一覧を取得し、属性を配列に格納
//-----------------------------------------------------------------------------
procedure TMyPanel.SetParent(AParent: TWinControl);
var
LInstallFontCollection : TGPInstalledFontCollection;
LCount : Integer;
LFontCount : Integer;
LFontName : string;
i : Integer;
begin
inherited;
if not Assigned(AParent) then exit;
//既に取得済みなら取得のコードを実行しない
if FFontCount > 0 then exit;
//システムにインストールされているフォントコレクションのオブジェクトを生成
LInstallFontCollection := TGPInstalledFontCollection.Create;
//インストールされてるいるフォント数を取得
LCount := LInstallFontCollection.GetFamilyCount;
//情報格納用の配列のサイズを設定
SetLength(FpFontFamily, LCount);
//配列の各要素にTGPFontFamilyオブジェクトを生成
for i := 0 to LCount - 1 do begin
FpFontFamily[i] := TGPFontFamily.Create;
end;
//配列に全てのフォント情報を格納する
LFontCount := 0;
LInstallFontCollection.GetFamilies(LCount, FpFontFamily, LFontCount);
//FontListプロパティにフォント名を格納
for i := 0 to LCount - 1 do begin
FpFontFamily[i].GetFamilyName(LFontName);
FFontList.Add(LFontName);
end;
//FFontCountプロパティの値の設定と、表示するフォント番号を設定
FFontCount := LCount;
FFontNumber := 0;
//Createしたオブジェクトは解放処理する
LInstallFontCollection.Free;
end;
//-----------------------------------------------------------------------------
// FontNumaberプロパティの設定用メソッド
//-----------------------------------------------------------------------------
procedure TMyPanel.SetFontNumber(const Value: Integer);
var
LFlag : Boolean;
begin
if FFontCount = 0 then exit;
LFlag := (Value >=0) and (Value <= (FFontCount - 1));
if LFlag and (FFontNumber <> Value) then begin
FFontNumber := Value;
Invalidate;
end;
end;
//-----------------------------------------------------------------------------
// TMyPanelクラスのPaintメソッド
// 実際の描画コード
// FFontNumber番目のフォントで、そのフォント名を描画
//-----------------------------------------------------------------------------
procedure TMyPanel.Paint;
var
LGPGraphic : TGPGraphics;
LGPFont : TGPFont;
LGPStrFormat : TGPStringFormat;
LGPBrush : TGPSolidBrush;
LGPDrawRect : TGPRectF;
LFontName : string;
begin
inherited;
if FFontCount = 0 then exit;
//描画の矩形領域を設定
LGPDrawRect := MakeRect(20.0, 20.0, 250.0, 150.0);
//TGPFontのオブジェクトを生成し設定
//第1引数は、取得しておいたTGPFontFamilyのFFontNumber番目の値
//フォントスタイルは指定なし。サイズをポイント数で指定
LGPFont := TGPFont.Create(FpFontFamily[FFontNumber],
30,
FontStyleRegular,
UnitPoint);
//フォント名を取得する
FpFontFamily[FFontNumber].GetFamilyName(LFontName);
//TGPStringFormatを生成する
//特に何も設定しないでデフォルトで使用
LGPStrFormat := TGPStringFormat.Create;
//ブラシで文字の色を設定
LGPBrush := TGPSolidBrush.Create(MakeColor(255, 0, 0, 0));
//描画先をこのTMyPanelのCanvasに指定して、TGPGraphicsのオブジェクトを生成
LGPGraphic := TGPGraphics.Create(Canvas.Handle);
//そのCanvasにフォント名を描画
LGPGraphic.DrawString(LFontName,
- 1,
LGPFont,
MakePoint(10.0, 10.0),
LGPStrFormat,
LGPBrush);
//Createしたオブジェクトは解放処理する
LGPFont.Free;
LGPStrFormat.Free;
LGPBrush.Free;
LGPGraphic.Free;
end;
end.
| 08_アンチエイリアシング - SetTextRenderingHint |
GDI+ のオブジェクトに対する操作の内、アンチエイリアシングやスムージングに関する関数には、オブジェクトに応じて、次の表のものがあります。
コミュニティの場では、「滑らかにしたい」とか「ギザギサ (ジャギー)」とか表現されている状態を改善するための関数ということになります。
文字列は、実際にはレンダリング関係の処理の設定のようですが、AntiAlias を含むフラグを指定すると、アンチエイリアシング処理を行ってくれます。この機能を確認するテストです。 |
表3
GDI+ のアンチエイリアス (スムージング) 処理関係の関数 |
| オブジェクト |
関数 |
関数の引数の型 |
| 画像 |
TGPGraphic.SetInterpolationMode |
TInterpolationMode |
| 図形 |
TGPGraphics.SetSmoothingMode |
TSmoothingMode |
| 文字列 |
TGPGraphic.SetTextRenderingHint |
TTextRenderingHint |
表4
TextRenderingHint 列挙型の値。SetTextRenderingHint 関数の引数に、この値を指定する |
| TextRenderingHintSystemDefault |
| TextRenderingHintSingleBitPerPixelGridFit |
| TextRenderingHintSingleBitPerPixel |
| TextRenderingHintAntiAliasGridFit |
| TextRenderingHintAntiAlias |
| TextRenderingHintClearTypeGridFit |
 |
図24
設計時画面 |
 |
図25
実行時画面
- 左はデフォルトの設定での描画
- 右は AntiAlias
- GDI+ ではデフォルトのままでもある程度のアンチエイリアス処理をする
|
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, StdCtrls, GDIPAPI, GDIPOBJ;
type
TMyPanel = class(TPanel)
protected
procedure Paint; override;
end;
TForm1 = class(TForm)
RadioGroup1: TRadioGroup;
procedure FormCreate(Sender: TObject);
procedure RadioGroup1Click(Sender: TObject);
private
{ Private 宣言 }
MyPanel : TMyPanel;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
//=============================================================================
// フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
Caption := 'GDI+ TextRenderingHint';
//描画するコントロールを生成
MyPanel := TMyPanel.Create(Self);
with MyPanel do begin
Parent := Self;
SetBounds(5, 120, Self.ClientWidth - 10, Self.ClientHeight - 125);
DoubleBuffered := True;
ControlStyle := MyPanel.ControlStyle + [csOpaque];
BevelOuter := bvNone;
Visible := True;
Color := clWhite;
ParentBackground := False;
Anchors := [akLeft, akTop, akRight, akBottom];
end;
RadioGroup1.Items.CommaText := 'TextRenderingHintSingleBitPerPixelGridFit,' +
'TextRenderingHintSingleBitPerPixel,' +
'TextRenderingHintAntiAliasGridFit,' +
'TextRenderingHintAntiAlias,' +
'TextRenderingHintClearTypeGridFit';
RadioGroup1.ItemIndex := 0;
end;
//=============================================================================
// RadioGroup1のOnClickイベント処理
//=============================================================================
procedure TForm1.RadioGroup1Click(Sender: TObject);
begin
if not Assigned(MyPanel) then exit;
MyPanel.Invalidate;
end;
{ TMyPanel }
//-----------------------------------------------------------------------------
// TMyPanelクラスのPaintメソッド
// 実際の描画コード
//
// Form1の値を参照しているが、本来はTMyPanelのプロパティにすべき
//-----------------------------------------------------------------------------
procedure TMyPanel.Paint;
var
LText : string;
LFontSize : Single;
LGPGraphic : TGPGraphics;
LGPFont : TGPFont;
LGPBrush : TGPSolidBrush;
LRenderNo : TTextRenderingHint;
begin
inherited;
LText := '山';
LFontSize := 140;
//TGPFontとTGPSolidBrushのオブジェクトを生成し設定
LGPFont := TGPFont.Create('HG行書体', LFontSize, FontStyleRegular, UnitPixel);
LGPBrush := TGPSolidBrush.Create(aclBlack);
//描画先をこのTMyPanelのCanvasに指定して、TGPGraphicsのオブジェクトを生成
LGPGraphic := TGPGraphics.Create(Canvas.Handle);
//そのCanvasに文字列を描画
LGPGraphic.SetTextRenderingHint(TextRenderingHintSystemDefault);
LGPGraphic.DrawString(LText, - 1, LGPFont, MakePoint(0.0, 0.0), LGPBrush);
//レンダリングの設定
//...AntiAilas...にすればアンチエイリアスになる
case Form1.RadioGroup1.ItemIndex of
0: LRenderNo := TextRenderingHintSingleBitPerPixelGridFit;
1: LRenderNo := TextRenderingHintSingleBitPerPixel;
2: LRenderNo := TextRenderingHintAntiAliasGridFit;
3: LRenderNo := TextRenderingHintAntiAlias;
4: LRenderNo := TextRenderingHintClearTypeGridFit;
end;
//レンダリングした文字列を描画
LGPGraphic.SetTextRenderingHint(LRenderNo);
LGPGraphic.DrawString(LText, -1, LGPFont, MakePoint(LFontSize, 0.0), LGPBrush);
//Createしたオブジェクトは解放処理する
LGPFont.Free;
LGPBrush.Free;
LGPGraphic.Free;
end;
end.
| 09_文字列の幅と高さ - MeasureString |
文字列の幅と高さを取得するサンプルです。
VCL では、TCanvas.TextWidth、TCanvas.TextHeight で取得できますが、GDI+ では MeasureString 関数を使用します。ただし、描画領域が正しく取得できるのは、DrawString の関数の文字列書式の設定として、TGPStringFormat.GenericDefault を指定した場合だけです。
このフラグは、左端寄せ、上端寄せでの描画です。したがって、複数行の文字列描画で、他の書式を設定して描画した文字列では正確に取得できません。
更に詳細に描画領域を求めるには、TGPFontFamily オブジェクトに
の関数があります。これらが使えるかも知れません。 |
 |
図26
設計時画面 |
 |
図27
GenericDefault の場合 |
 |
図28
GenericTypographic の場合 |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, StdCtrls, GDIPAPI, GDIPOBJ;
type
TMyPanel = class(TPanel)
protected
procedure Paint; override;
private
procedure DrawText(AStrText: String; APoint: TGPPointF;
AFontSize: Single; AFontStyle: FontStyle);
end;
TForm1 = class(TForm)
RadioGroup1: TRadioGroup;
procedure FormCreate(Sender: TObject);
procedure RadioGroup1Click(Sender: TObject);
private
{ Private 宣言 }
MyPanel : TMyPanel;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
//=============================================================================
// フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
Caption := 'GDI+ 文字列の幅と高さの取得';
//描画するコントロールを生成
MyPanel := TMyPanel.Create(Self);
with MyPanel do begin
Parent := Self;
SetBounds(5, 65, Self.ClientWidth - 10, Self.ClientHeight - 70);
DoubleBuffered := True;
ControlStyle := MyPanel.ControlStyle + [csOpaque];
BevelOuter := bvNone;
Visible := True;
Color := clWhite;
ParentBackground := False;
Anchors := [akLeft, akTop, akRight, akBottom];
end;
//取得する属性の設定
RadioGroup1.Items.CommaText := 'TGPStringFormat.GenericDefault,' +
'TGPStringFormat.GenericTypographic';
RadioGroup1.ItemIndex := 0;
end;
//=============================================================================
// RadioGroup1のOnClickイベント
//=============================================================================
procedure TForm1.RadioGroup1Click(Sender: TObject);
begin
if not Assigned(MyPanel) then exit;
MyPanel.Invalidate;
end;
{ TMyPanel }
//-----------------------------------------------------------------------------
// TMyPanelクラスのPaintメソッド
// 実際の描画コードこの下のDrawTextで実行する
//-----------------------------------------------------------------------------
procedure TMyPanel.Paint;
var
LStartPoint : TGPPointF;
LFontSize : Single;
begin
inherited;
LFontSize := 30.0;
//フォントスタイルは通常で英大文字
LStartPoint := MakePoint(20.0, 20.0);
DrawText('DELPHI', LStartPoint, LFontSize, FontStyleRegular);
//フォントスタイルは通常で英小文字
LStartPoint := MakePoint(20.0, 20.0 + (LFontSize + 20.0));
DrawText('font size', LStartPoint, LFontSize, FontStyleRegular);
//フォントスタイルは通常で漢字
LStartPoint := MakePoint(20.0, 20.0 + (LFontSize + 20.0) * 2);
DrawText('文字列', LStartPoint, LFontSize, FontStyleRegular);
//斜体フォントスで英大文字
LStartPoint := MakePoint(20.0, 20.0 + (LFontSize + 20.0) * 3);
DrawText('DELPHI', LStartPoint, LFontSize, FontStyleItalic);
//斜体フォントスで英小文字
LStartPoint := MakePoint(20.0, 20.0 + (LFontSize + 20.0) * 4);
DrawText('font size', LStartPoint, LFontSize, FontStyleItalic);
//斜体フォントスで漢字
LStartPoint := MakePoint(20.0, 20.0 + (LFontSize + 20.0) * 5);
DrawText('文字列', LStartPoint, LFontSize, FontStyleItalic);
end;
//-----------------------------------------------------------------------------
// 実際の描画コードを実行するメソッド
//-----------------------------------------------------------------------------
procedure TMyPanel.DrawText(AStrText: String; APoint: TGPPointF;
AFontSize: Single; AFontStyle: FontStyle);
var
LSizeRectF : TGPRectF;
LGPGraphic : TGPGraphics;
LGPFont : TGPFont;
LGPBrush : TGPSolidBrush;
LGPPen : TGPPen;
begin
inherited;
//TGPFontとTGPSolidBrushのオブジェクトを生成し設定
//フォントのサイズとスタイルは引数の値を使用
LGPFont := TGPFont.Create('Times New Roman', AFontSize, AFontStyle, UnitPixel);
LGPBrush := TGPSolidBrush.Create(aclBlack);
//描画先をこのTMyPanelのCanvasに指定して、TGPGraphicsのオブジェクトを生成
LGPGraphic := TGPGraphics.Create(Canvas.Handle);
//文字列を描画する前に、描画領域のサイズを取得
LGPGraphic.MeasureString(AStrText, -1, LGPFont, APoint, LSizeRectF);
//矩形を描画するペンのオブジェクトを生成して領域を囲む矩形を描画
LGPPen := TGPPen.Create(aclBlack, 1);
LGPGraphic.DrawRectangle(LGPPen, LSizeRectF);
//Canvasに文字列を描画
//描画する文字列、描画開始点、文字サイズ(ピクセル)は引数の値を使用
case Form1.RadioGroup1.ItemIndex of
0:
begin
LGPGraphic.DrawString(AStrText,
-1,
LGPFont,
APoint,
TGPStringFormat.GenericDefault,
LGPBrush);
end;
1:
begin
LGPGraphic.DrawString(AStrText,
-1,
LGPFont,
APoint,
TGPStringFormat.GenericTypographic,
LGPBrush);
end;
end;
//Createしたオブジェクトは解放処理する
LGPPen.Free;
LGPFont.Free;
LGPBrush.Free;
LGPGraphic.Free;
end;
end.
| 10_パス文字列や図形、画像の幅と高さ - GetBounds |
同じ文字列でも、パスにした文字列は図形です。図形の描画領域は、GetBounds 関数で取得できます。画像も取得できますが、画像の場合は、表示のサイズではなく、元の画像のサイズとなります。
このサンプルでは、枠線がパスの図形に隠れないように、パスを描画した後に領域の矩形を描画していますが、矩形領域は、図形を描く前に取得できます。
GDI+ で文字列や図形をパスにするには、
- TGPGraphicsPath のオブジェクトを生成
- TGPGraphicsPath.AddXXX の名前の関数で、文字列や図形を描画
- TGPGraphics.FillPath でパスの内部を塗潰す (塗潰す必要がない場合は不要)
- TGPGraohics.DrawPath で輪郭線を描画 (輪郭線を描かなければ不要)
- 必要であれば、 TGPGraphicsPath.AddPath でパスを結合したパスを作成
という手順でコーディングします。AddXXX の描画関数には、円、楕円、ベジェ曲線等、TCanvas で使用可能な関数と同じものが用意されています。BeginPath、EndPath で構成するよりも扱いやすいと言えるでしょう。
ただし、引数の種類に注意が必要です。例えば、文字列の AddString 関数の場合、TGPFontFamily と TGPStringFormat
のオブジェクトを必ず使用します。 |
 |
図29
設計時画面 |
 |
図30
実行画面
|
リスト10
パス文字列の幅と高さの取得には GetBounds
関数を使用する |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, StdCtrls, GDIPAPI, GDIPOBJ;
type
TMyPanel = class(TPanel)
protected
procedure Paint; override;
end;
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private 宣言 }
MyPanel : TMyPanel;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
//=============================================================================
// フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
Caption := 'GDI+ パス図形の領域取得 GetBounds';
//描画するコントロールを生成
MyPanel := TMyPanel.Create(Self);
with MyPanel do begin
Parent := Self;
SetBounds(5, 5, Self.ClientWidth - 10, Self.ClientHeight - 10);
DoubleBuffered := True;
ControlStyle := MyPanel.ControlStyle + [csOpaque];
BevelOuter := bvNone;
Visible := True;
Color := clWhite;
ParentBackground := False;
Anchors := [akLeft, akTop, akRight, akBottom];
end;
end;
{ TMyPanel }
//-----------------------------------------------------------------------------
// TMyPanelクラスのPaintメソッド
// 実際の描画コード
// 2つのパス文字列を作成して表示
// 作成したパス図形の領域の枠線を描画
//-----------------------------------------------------------------------------
procedure TMyPanel.Paint;
var
LSizeRectF : TGPRectF;
LStrText : String;
LFontSize : Single;
LGPGraphic : TGPGraphics;
LGPBrush : TGPSolidBrush;
LGPFontFamily : TGPFontFamily;
LGPStrFormat : TGPStringFormat;
LGPPath : TGPGraphicsPath;
LGPPen : TGPPen;
begin
inherited;
LStrText := 'DELPHI';
LFontSize := 60;
//パス内部を塗潰すBrushを生成
LGPBrush := TGPSolidBrush.Create(aclSkyBlue);
//AddStringの引数に必要なTGPFontFamilyとTGPStringFormatを生成
LGPFontFamily := TGPFontFamily.Create('Arial Black');
LGPStrFormat := TGPStringFormat.Create();
//パス作成開始
LGPPath := TGPGraphicsPath.Create;
//パスに文字列を追加
LGPPath.AddString(LStrText,
- 1,
LGPFontFamily,
FontStyleRegular,
LFontSize,
MakePoint(10.0, 10.0),
LGPStrFormat);
//描画先をこのTMyPanelのCanvasに指定して、TGPGraphicsのオブジェクトを生成
LGPGraphic := TGPGraphics.Create(Canvas.Handle);
//バス内部を塗潰す
LGPGraphic.FillPath(LGPBrush, LGPPath);
//パスの全体のサイズを取得
LGPPath.GetBounds(LSizeRectF);
//図形の取り囲む線を描画するためのペンを生成
LGPPen := TGPPen.Create(aclBlack, 1);
//パス全体を囲む矩形を描画
LGPGraphic.DrawRectangle(LGPPen, LSizeRectF);
//次のパスを作成する準備
//上と違うのは、斜体文字とし、位置を下にずらしただけ
LGPPath.Free;
LGPPath := TGPGraphicsPath.Create;
LGPPath.AddString(LStrText,
- 1,
LGPFontFamily,
FontStyleItalic,
LFontSize,
MakePoint(10.0, 90.0),
LGPStrFormat);
LGPGraphic.FillPath(LGPBrush, LGPPath);
LGPPath.GetBounds(LSizeRectF);
LGPGraphic.DrawRectangle(LGPPen, LSizeRectF);
//Createしたオブジェクトは解放処理する
LGPFontFamily.Free;
LGPStrFormat.Free;
LGPPen.Free;
LGPPath.Free;
LGPBrush.Free;
LGPGraphic.Free;
end;
end.
JUNKI さんのところにサンプルがあります。筆者も真似してやってみました。
視覚的な効果は、背景の色等も影響するようです。 |
 |
図31
実行結果 |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, StdCtrls, GDIPAPI, GDIPOBJ;
type
TMyPanel = class(TPanel)
protected
procedure Paint; override;
end;
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private 宣言 }
MyPanel : TMyPanel;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
//=============================================================================
// フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
Caption := 'GDI+ エンポス文字列';
//描画するコントロールを生成
MyPanel := TMyPanel.Create(Self);
with MyPanel do begin
Parent := Self;
SetBounds(5, 5, Self.ClientWidth - 10, Self.ClientHeight - 10);
DoubleBuffered := True;
ControlStyle := MyPanel.ControlStyle + [csOpaque];
BevelOuter := bvNone;
Visible := True;
Color := $00D0D0D0;
ParentBackground := False;
Anchors := [akLeft, akTop, akRight, akBottom];
end;
end;
{ TMyPanel }
//-----------------------------------------------------------------------------
// TMyPanelクラスのPaintメソッド
// 実際の描画コード
//-----------------------------------------------------------------------------
procedure TMyPanel.Paint;
var
LStrText : String;
LGPGraphic : TGPGraphics;
LGPFont : TGPFont;
LGPBrush : TGPSolidBrush;
begin
inherited;
LStrText := 'Delphi';
//TGFontとTGPSolidBrushのオブジェクトを生成し設定
LGPFont := TGPFont.Create('Times New Roman', 55, FontStyleBold, UnitPoint);
LGPBrush := TGPSolidBrush.Create(MakeColor(255, 0, 0, 0));
//描画先をこのTMyPanelのCanvasに指定して、TGPGraphicsのオブジェクトを生成
LGPGraphic := TGPGraphics.Create(Canvas.Handle);
//そのCanvasに文字列を描画
LGPBrush.SetColor(aclWhite);
LGPGraphic.DrawString(LStrText, - 1, LGPFont, MakePoint(0.0, 0.0), LGPBrush);
LGPBrush.SetColor(aclDarkGray);
LGPGraphic.DrawString(LStrText, - 1, LGPFont, MakePoint(4.0, 4.0), LGPBrush);
LGPBrush.SetColor(aclBlack);
LGPGraphic.DrawString(LStrText, - 1, LGPFont, MakePoint(2.0, 2.0), LGPBrush);
LGPBrush.SetColor(aclBlack);
LGPGraphic.DrawString(LStrText, - 1, LGPFont, MakePoint(0.0, 90.0), LGPBrush);
LGPBrush.SetColor(aclWhite);
LGPGraphic.DrawString(LStrText, - 1, LGPFont, MakePoint(4.0, 92.0), LGPBrush);
LGPBrush.SetColor(aclGray);
LGPGraphic.DrawString(LStrText, - 1, LGPFont, MakePoint(2.0, 91.0), LGPBrush);
//Createしたオブジェクトは解放処理する
LGPFont.Free;
LGPBrush.Free;
LGPGraphic.Free;
end;
end.
|