|
Delphi Programming / Object Pascal
[掲載 2017年05月02日] [更新 2017年05月24日] GDI+ 関係サンプル |
GDI+ 関係サンプル
G014_四角形・角丸四角形の描画 |
動作確認等 |
Windows 7 U64(SP1) + Delphi XE(UP1) Pro |
|
G014_GDIPlus_Rectangle.zip [1751 KB] 2017年05月24日版 (EXE 同梱) |
GDI+ を使用して四角形,つまり矩形を描画するサンプルです.他のサンプルでも四角形を描画するコードがありますが,単独のサンプルとして掲載しておきます.
四角形内部の塗り潰しにはブラシを使用します.各種のブラシが GDI+ で利用できます. |
[備考]
多角形は TGPGraphic.DrawPolygon で描画できます.
パスの場合は TGPGraphicsPath.AddPolygon で作成できます.座標値の配列を使用する場合は以下の記事を参考にしてください.静的配列の使用例と動的配列の使用法の説明があります.
|
実際に四角形を描画するサンプルです.以下の手順で実行しています.
- 四角形の輪郭線の描画に使用する色と線の太さを指定して TGPPen を生成する
- 四角形の内部の塗り潰しの色を指定して TGPSolidBrush を生成する
- 四角形のサイズを MakeRect で設定する
- 四角形の内部を TGPGraphics.FillRectangle で塗り潰す
- 四角形の輪郭線を TGPGraphics.DrawRectangle で描画する
|
|
図1
設計時画面
|
|
図2
実行結果
- [Button1] をクリックすると塗り潰しの色が変更できる
|
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
FBrushColor : Cardinal;
end;
TForm1 = class(TForm)
Button1: TButton;
ColorDialog1: TColorDialog;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
MyPanel : TMyPanel;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
//=============================================================================
// フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
Caption := 'GDI+ 四角形の描画';
//TMyPanelを生成して配置
MyPanel := TMyPanel.Create(Self);
with MyPanel do begin
Parent := Self;
Left := 5;
Top := 35;
Width := Self.ClientWidth - 10;
Height := Self.ClientHeight - Top - 5;
Anchors := [akLeft, akTop, akRight, akBottom];
Color := clWhite;
ParentBackground := False;
DoubleBuffered := True;
FBrushColor := aclAntiqueWhite;
end;
end;
//=============================================================================
// ブラシの色を変更する
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
ColorDialog1.Color := ARGBToColorRef(MyPanel.FBrushColor);
if ColorDialog1.Execute then begin
MyPanel.FBrushColor := ColorRefToARGB(ColorDialog1.Color);
end;
MyPanel.Invalidate;
end;
{ TMyPanel }
//-----------------------------------------------------------------------------
// TMyPanelクラスのPaintメソッド
// 実際の描画コード
// 四角形の例
//-----------------------------------------------------------------------------
procedure TMyPanel.Paint;
var
LGPGraphic : TGPGraphics;
LGPPen : TGPPen;
LGPBrush : TGPSolidBrush;
LGPRect : TGPRect;
LLeft : Integer;
LTop : Integer;
LWidth : Integer;
LHeight : Integer;
LPenWidth : Integer;
begin
inherited;
LLeft := 20;
LTop := 20;
LWidth := 230;
LHeight := 130;
LPenWidth := 3;
//ペンのオブジェクトを生成
LGPPen := TGPPen.Create(aclGreen, LPenWidth);
//TGPSolidBrushを生成
LGPBrush := TGPSolidBrush.Create(FBrushColor);
//四角形のサイズを指定
LGPRect := MakeRect(LLeft, LTop, LWidth, LHeight);
//TGPGraphicsオブジェクトを生成
LGPGraphic := TGPGraphics.Create(Canvas.Handle);
//内部を塗り潰す
//塗り潰す必要がなければ実行する必要はない(ブラシの設定も不要)
LGPGraphic.FillRectangle(LGPBrush, LGPRect);
//四角形を描画
//線の描画関係の関数名はDrawXXXX
LGPGraphic.DrawRectangle(LGPPen, LGPRect);
//Createしたオブジェクトは解放処理する
LGPPen.Free;
LGPBrush.Free;
LGPGraphic.Free;
end;
end.
VCL には角の丸い四角形を描画する TCanvas.RoundRectメソッドがありますが,GDI+ には同様のメソッドは実装されていません.リージョンあるいはパスを使用すると描画できます.
GDI+ はどちらかと言うとパスの機能が充実しています.以下はパスを使用する例です. |
|
図3
設計時画面
|
|
図4
実行結果
- [Button1] をクリックすると塗り潰しの色が変更できる
|
本サンプルでは円弧のパスの作成順番を右回りで作成しています.
パスを作成すると追加順に結合されていきます.TGPGraphicsPath.CloseFigure メソッドを実行すると,最初に作成したパスと最後に作成したパスが結合して閉じた図形になります.したがって,パスの作成順序が異なると,下図のように期待する結果とならない場合があります. |
|
図5
パスの作成順序に注意
- 左上の円弧のパスの次に右下の円弧のパスを作成した場合
|
左回り (反時計回り) でパスを追加していく場合は以下のように書けます.
GDI+ の角度はデフォルトでは度単位で,時計回りの方向が正の値です.左回りの反時計方向は負の値になりますから,描画範囲の角度を負の値にします. |
//左上
LGPPath.AddArc(LLeft, LTop, LSize, LSize, 270, -90);
//左下
LGPPath.AddArc(LLeft, LTop + LHeight - LSize, LSize, LSize, 180, -90);
//右下
LGPPath.AddArc(LLeft + LWidth - LSize, LTop + LHeight - LSize, LSize, LSize, 90, -90);
//右上
LGPPath.AddArc(LLeft + LWidth - LSize, LTop, LSize, LSize, 0, -90);
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
FBrushColor : Cardinal;
end;
TForm1 = class(TForm)
Button1: TButton;
ColorDialog1: TColorDialog;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
MyPanel : TMyPanel;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
//=============================================================================
// フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
Caption := 'GDI+ 角が丸い四角形の描画';
//TMyPanelを生成して配置
MyPanel := TMyPanel.Create(Self);
with MyPanel do begin
Parent := Self;
Left := 5;
Top := 35;
Width := Self.ClientWidth - 10;
Height := Self.ClientHeight - Top - 5;
Anchors := [akLeft, akTop, akRight, akBottom];
Color := clWhite;
ParentBackground := False;
DoubleBuffered := True;
FBrushColor := aclYellow;
end;
end;
//=============================================================================
// ブラシの色を変更する
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
ColorDialog1.Color := ARGBToColorRef(MyPanel.FBrushColor);
if ColorDialog1.Execute then begin
MyPanel.FBrushColor := ColorRefToARGB(ColorDialog1.Color);
end;
MyPanel.Invalidate;
end;
{ TMyPanel }
//-----------------------------------------------------------------------------
// TMyPanelクラスのPaintメソッド
// 実際の描画コード
// 角が丸い四角形の例
// 本サンプルでは矩形そのものは描画しない.作成したパスだけを描画する
//-----------------------------------------------------------------------------
procedure TMyPanel.Paint;
var
LGPGraphic : TGPGraphics;
LGPPath : TGPGraphicsPath;
LGPPen : TGPPen;
LGPBrush : TGPSolidBrush;
LLeft : Integer;
LTop : Integer;
LWidth : Integer;
LHeight : Integer;
LPenWidth : Integer;
LSize : Integer;
begin
inherited;
LLeft := 20;
LTop := 20;
LWidth := 230;
LHeight := 130;
LPenWidth := 3;
LSize := 32;
//ペンのオブジェクトを生成
LGPPen := TGPPen.Create(aclBlack, LPenWidth);
//TGPSolidBrushを生成
LGPBrush := TGPSolidBrush.Create(FBrushColor);
//TGPGraphicsオブジェクトを生成
LGPGraphic := TGPGraphics.Create(Canvas.Handle);
//---------------------------------------------------------------------------
// パスの作成開始
// 矩形領域の位置とサイズの値を元に円弧のパスを作成
// パスの追加はTGPGraphicsPath.AddXXX
//---------------------------------------------------------------------------
LGPPath := TGPGraphicsPath.Create;
//パスに円弧を追加していく(指定直径の1/4の円)
//左上
LGPPath.AddArc(LLeft, LTop, LSize, LSize, 180, 90);
//右上
LGPPath.AddArc(LLeft + LWidth - LSize, LTop, LSize, LSize, 270, 90);
//右下
LGPPath.AddArc(LLeft + LWidth - LSize, LTop + LHeight - LSize, LSize, LSize, 0, 90);
//左下
LGPPath.AddArc(LLeft, LTop + LHeight - LSize, LSize, LSize, 90, 90);
//作成したパスを結合して閉じた図形にする
LGPPath.CloseFigure();
//---------------------------------------------------------------------------
// パスの作成終了
//---------------------------------------------------------------------------
//パスの内部を塗り潰す
//塗り潰す必要がなければ実行する必要はない(ブラシの設定も不要)
LGPGraphic.FillPath(LGPBrush, LGPPath);
//パスの輪郭を描画
//パスや線の描画関係の関数名はDrawXXXX
LGPGraphic.DrawPath(LGPPen, LGPPath);
//Createしたオブジェクトは解放処理する
LGPPen.Free;
LGPBrush.Free;
LGPGraphic.Free;
end;
end.
03_GDI+ によるバルーンヒントウィンドウのような図形 |
前項のサンプルコードを少し変更して,パスに三角形を追加すると,下図のようなバルーンヒントウィンドウのような図形が描画できます.
実用的にするには,どの変数をプロパティにするとか,矢印としての三角形の描画位置と矩形の描画位置の関係をどうするかを考える必要があります.少し面倒かも知れません. |
|
図6
実行結果 |
リスト3
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;
public
FBrushColor : Cardinal;
end;
TForm1 = class(TForm)
Button1: TButton;
ColorDialog1: TColorDialog;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
MyPanel : TMyPanel;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
//=============================================================================
// フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
Caption := 'GDI+ バルーンヒントウィンドウ';
//TMyPanelを生成して配置
MyPanel := TMyPanel.Create(Self);
with MyPanel do begin
Parent := Self;
Left := 5;
Top := 35;
Width := Self.ClientWidth - 10;
Height := Self.ClientHeight - Top - 5;
Anchors := [akLeft, akTop, akRight, akBottom];
Color := clWhite;
ParentBackground := False;
DoubleBuffered := True;
FBrushColor := aclYellow;
end;
end;
//=============================================================================
// ブラシの色を変更する
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
ColorDialog1.Color := ARGBToColorRef(MyPanel.FBrushColor);
if ColorDialog1.Execute then begin
MyPanel.FBrushColor := ColorRefToARGB(ColorDialog1.Color);
end;
MyPanel.Invalidate;
end;
{ TMyPanel }
//-----------------------------------------------------------------------------
// TMyPanelクラスのPaintメソッド
// 実際の描画コード
// バルーンヒントウィンドウのような図形
//-----------------------------------------------------------------------------
procedure TMyPanel.Paint;
var
LGPGraphic : TGPGraphics;
LGPPath : TGPGraphicsPath;
LGPPen : TGPPen;
LGPBrush : TGPSolidBrush;
LLeft : Integer;
LTop : Integer;
LWidth : Integer;
LHeight : Integer;
LPenWidth : Integer;
LSize : Integer;
LArrowStartX : Integer;
LArrowStartY : Integer;
LArrowEndX : Integer;
LArrowEndY : Integer;
LArrowHeight : Integer;
LArrowWidth : Integer;
LArrowShift : Integer;
LPoints : array of TGPPoint;
begin
inherited;
LPenWidth := 3;
LArrowHeight := 70;
LArrowWidth := 30;
LArrowShift := 25;
LArrowStartX := 70;
LArrowStartY := 200;
LArrowEndX := LArrowStartX + LArrowShift;
LArrowEndY := LArrowStartY - LArrowHeight;
//矩形のサイズと位置の設定
LSize := 32;
LWidth := 200;
LHeight := 100;
LLeft := (LArrowEndX - LArrowWidth div 2) - LSize;
LTop := LArrowEndY - LHeight;
//ペンのオブジェクトを生成
LGPPen := TGPPen.Create(aclBlack, LPenWidth);
//TGPSolidBrushを生成
LGPBrush := TGPSolidBrush.Create(FBrushColor);
//TGPGraphicsオブジェクトを生成
LGPGraphic := TGPGraphics.Create(Canvas.Handle);
//---------------------------------------------------------------------------
// パスの作成開始
// 以下のコードでは次の値を使用
// 矢印の始点と終点のX,Y座標値
// 矢印の幅(三角形の底辺の寸法)
// 矩形の位置とサイズ
//
// パスの追加はTGPGraphicsPath.AddXXX
//---------------------------------------------------------------------------
LGPPath := TGPGraphicsPath.Create;
//矢印部分の直線を描く座標を設定
SetLength(LPoints, 3);
LPoints[1] := MakePoint(LArrowStartX, LArrowStartY);
if (LArrowEndX = LLeft) or (LArrowEndX = LLeft + LWidth) then begin
LPoints[0] := MakePoint(LArrowEndX, LArrowEndY + LArrowWidth div 2);
LPoints[2] := MakePoint(LArrowEndX, LArrowEndY - LArrowWidth div 2);
end else begin
LPoints[0] := MakePoint(LArrowEndX + LArrowWidth div 2, LArrowEndY);
LPoints[2] := MakePoint(LArrowEndX - LArrowWidth div 2, LArrowEndY);
end;
//パスに円弧を追加していく(指定直径の1/4の円)
//左上
LGPPath.AddArc(LLeft, LTop, LSize, LSize, 180, 90);
if (LArrowEndY = LTop) then begin
LGPPath.AddLine(LPoints[2], LPoints[1]);
LGPPath.AddLine(LPoints[1], LPoints[0]);
end;
//右上
LGPPath.AddArc(LLeft + LWidth - LSize, LTop, LSize, LSize, 270, 90);
if (LArrowEndX = LLeft + LWidth) then begin
LGPPath.AddLine(LPoints[2], LPoints[1]);
LGPPath.AddLine(LPoints[1], LPoints[0]);
end;
//右下
LGPPath.AddArc(LLeft + LWidth - LSize, LTop + LHeight - LSize, LSize, LSize, 0, 90);
if (LArrowEndY = LTop + LHeight) then begin
LGPPath.AddLine(LPoints[0], LPoints[1]);
LGPPath.AddLine(LPoints[1], LPoints[2]);
end;
//左下
LGPPath.AddArc(LLeft, LTop + LHeight - LSize, LSize, LSize, 90, 90);
if (LArrowEndX = LLeft) then begin
LGPPath.AddLine(LPoints[0], LPoints[1]);
LGPPath.AddLine(LPoints[1], LPoints[2]);
end;
//作成したパスを結合して閉じた図形にする
LGPPath.CloseFigure();
//---------------------------------------------------------------------------
// パスの作成終了
//---------------------------------------------------------------------------
//パスの内部を塗り潰す
//塗り潰す必要がなければ実行する必要はない(ブラシの設定も不要)
LGPGraphic.FillPath(LGPBrush, LGPPath);
//パスの輪郭を描画
//パスや線の描画関係の関数名はDrawXXXX
LGPGraphic.DrawPath(LGPPen, LGPPath);
//Createしたオブジェクトは解放処理する
LGPPen.Free;
LGPBrush.Free;
LGPGraphic.Free;
end;
end.
上のコードは矩形の下側に矢印を描画する例です.
以下は上のコードの動作確認に使用した設定値の例です.これらの設定は,矩形の位置とサイズを決定してから矢印の位置を設定するか,その逆,あるいは別の設定手順があるかも知れません. |
//----------------------------------------------------------------------------
// 矩形の上に矢印を描画する例
//----------------------------------------------------------------------------
LArrowHeight := 70;
LArrowWidth := 30;
LArrowShift := 20;
LArrowStartX := 70;
LArrowStartY := 50;
LArrowEndX := LArrowStartX + LArrowShift;
LArrowEndY := LArrowStartY + LArrowHeight;
//矩形のサイズと位置の設定
LSize := 32;
LWidth := 200;
LHeight := 100;
LLeft := (LArrowEndX - LArrowWidth div 2) - LSize;
LTop := LArrowEndY;
//----------------------------------------------------------------------------
// 矩形の左側に矢印を描画する例
//----------------------------------------------------------------------------
LArrowHeight := 50;
LArrowWidth := 20;
LArrowShift := 0;
LArrowStartX := 60;
LArrowStartY := 100;
LArrowEndX := LArrowStartX + LArrowHeight;
LArrowEndY := LArrowStartY - LArrowShift;
//矩形のサイズと位置の設定
LSize := 32;
LWidth := 200;
LHeight := 100;
LLeft := LArrowEndX;
LTop := LArrowEndY - 50;
//----------------------------------------------------------------------------
// 矩形の右側に矢印を描画する例
//----------------------------------------------------------------------------
LArrowHeight := 50;
LArrowWidth := 20;
LArrowShift := 0;
LArrowStartX := 300;
LArrowStartY := 100;
LArrowEndX := LArrowStartX - LArrowHeight;
LArrowEndY := LArrowStartY - LArrowShift;
//矩形のサイズと位置の設定
LSize := 32;
LWidth := 200;
LHeight := 100;
LLeft := LArrowEndX - LWidth;
LTop := LArrowEndY - 50;
//----------------------------------------------------------------------------
|