|
Delphi Programming / Object Pascal
[掲載 2017年05月24日] [更新 2017年05月24日] GDI+ 関係サンプル |
GDI+ 関係サンプル
G016_直線の端点を矢印にする |
動作確認等 |
Windows 7 U64(SP1) + Delphi XE(UP1) Pro |
|
G016_GDIPlus_ArrowLine.zip [2,424 KB] 2017年05月24日版 (EXE 同梱) |
01_TGPAdjustableArrowCap を使用した矢印付き直線の描画 |
GDI+ で矢印付きの直線を描画するには TGPAdjustableArrowCap が利用できます.
- 矢印の幅と高さを指定して TGPAdjustableArrowCap オブジェクトを生成
- TGPPen の SetCustomStartCap または SetCustomEndCap メソッドで設定
- その TGPPen を使用して TGPGraphics.DrawLine メソッドで線を描画
という手順になります.始点と終点の矢印の形状は別々に設定できます.矢印の三角形の高さに相当するのが矢印の高さです.三角形の底辺の長さが矢印の幅になります.この値は,線の太さ (幅) の倍数で指定します.したがって,線の太さが変わると自動的に矢印のサイズも変わります. |
[備考]
連続した直線は TGPGraphic.DrawLines で描画できます.
パスの場合は TGPGraphicsPath.AddLines で作成できます.座標値の配列を使用する場合は以下の記事を参考にしてください.静的配列の使用例と動的配列の使用法の説明があります.
|
|
図1
実行結果 |
リスト1
TGPAdjustableArrowCap を使用すると矢印付きの直線を描画できる |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls, GDIPOBJ, GDIPAPI, GDIPUTIL;
type
TMyPanel = class(TPanel)
protected
procedure Paint; override;
procedure DrawImage(ACanvas: TCanvas);
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
Self.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;
end;
end;
{ TMyPanel }
//-----------------------------------------------------------------------------
// 実際の描画コード
// 直線を描画する時の端点の形状(ャップ)を矢印にする
//
// ACanvas : 描画先のTCanas
//-----------------------------------------------------------------------------
procedure TMyPanel.DrawImage(ACanvas: TCanvas);
var
LGPGraphics : TGPGraphics;
LGPPen : TGPPen;
LGPStartArrow : TGPAdjustableArrowCap;
LGPEndArrow : TGPAdjustableArrowCap;
LLineLength : Integer;
LPosX : Integer;
LPosY : Integer;
begin
//直線の長さと描画開始X座標値
LLineLength := 280;
LPosX := 20;
//始点と終端の矢印のオブジェクトを生成
//最初の引数は矢印の高さ(三角形の高さ)
//次の引数は矢印の幅(三角形の底辺の値)
//これらの値は線の太さの倍数で指定する
//最後の引数がFalseの時は塗り潰しなし
LGPStartArrow := TGPAdjustableArrowCap.Create(8, 8, False);
LGPEndArrow := TGPAdjustableArrowCap.Create(8, 8, True);
//線を描画するために使用するTGPPenの生成
//生成した端点形状の情報をセット
LGPPen := TGPPen.Create(MakeColor(255, 0, 0, 0));
LGPPen.SetCustomStartCap(LGPStartArrow);
LGPPen.SetCustomEndCap(LGPEndArrow);
//描画先を指定してTGPGraphics生成
LGPGraphics := TGPGraphics.Create(ACanvas.Handle);
//TGPPenを使用して線を描画
LPosY := 20;
LGPGraphics.DrawLine(LGPPen, LPosX, LPosY, LPosX + LLineLength, LPosY);
//線の太さを変更して描画
LPosY := 70;
LGPPen.SetWidth(5.0);
LGPGraphics.DrawLine(LGPPen, LPosX, LPosY, LPosX + LLineLength, LPosY);
//線の太さを変更して描画
LPosY := 150;
LGPPen.SetWidth(10.0);
LGPGraphics.DrawLine(LGPPen, LPosX, LPosY, LPosX + LLineLength, LPosY);
LGPStartArrow.Free;
LGPEndArrow.Free;
LGPPen.Free;
LGPGraphics.Free;
end;
//-----------------------------------------------------------------------------
// TMyPanelのPaintメソッド
// CanvasをTImage.CanvasにすればTImageへの描画となる
//-----------------------------------------------------------------------------
procedure TMyPanel.Paint;
begin
inherited;
DrawImage(Canvas);
end;
end.
TSpinEdit の値で矢印の幅と高さを設定して,その結果を確認できるようにしたサンプルです.
|
|
図2
実行開始時の画面 |
|
図3
設定例
- 左の TSpinEdit が矢印の幅 (三角形の底辺の寸法)
- 右の TSpinEdit が高さの設定用
- これらは線の太さの倍数値 (Single 型)
|
リスト2
矢印の幅と高さを変更して結果を確認するサンプル |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls, GDIPOBJ, GDIPAPI, GDIPUTIL, Spin, ExtDlgs;
type
TMyPanel = class(TPanel)
private
FArrowWidth : Integer;
FArrowHeight : Integer;
procedure SetFArrowWidth(const Value: Integer);
procedure SetFArrowHeight(const Value: Integer);
protected
procedure Paint; override;
procedure DrawImage(ACanvas: TCanvas);
public
constructor Create(AOwner: TComponent); override;
property ArrowWidth : Integer read FArrowWidth write SetFArrowWidth;
property ArrowHeight : Integer read FArrowHeight write SetFArrowHeight;
end;
TForm1 = class(TForm)
SpinEdit1: TSpinEdit;
SpinEdit2: TSpinEdit;
OpenPictureDialog1: TOpenPictureDialog;
procedure FormCreate(Sender: TObject);
procedure SpinEdit1Change(Sender: TObject);
procedure SpinEdit2Change(Sender: TObject);
private
{ Private 宣言 }
MyPanel : TMyPanel;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//=============================================================================
// フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
Self.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;
end;
SpinEdit1.Value := MyPanel.ArrowWidth;
SpinEdit2.Value := MyPanel.ArrowHeight;
end;
//=============================================================================
// SpinEdit1のOnChangeイベント処理
// TMyPanelのArrowWidthプロパティ設定
//=============================================================================
procedure TForm1.SpinEdit1Change(Sender: TObject);
begin
MyPanel.ArrowWidth := SpinEdit1.Value;
end;
//=============================================================================
// SpinEdit2のOnChangeイベント処理
// TMyPanelのArrowHeightプロパティ設定
//=============================================================================
procedure TForm1.SpinEdit2Change(Sender: TObject);
begin
MyPanel.ArrowHeight := SpinEdit2.Value;
end;
{ TMyPanel }
//-----------------------------------------------------------------------------
// TMyPanelのコントラクタ
//-----------------------------------------------------------------------------
constructor TMyPanel.Create(AOwner: TComponent);
begin
inherited;
FArrowWidth := 8;
FArrowHeight := 8;
end;
//-----------------------------------------------------------------------------
// TMyPanelのArrowWidthプロパティ設定用メソッド
// 矢印の幅(三角形の底辺の長さ)の設定
// この値は線の太さの倍数値
//-----------------------------------------------------------------------------
procedure TMyPanel.SetFArrowWidth(const Value: Integer);
begin
if FArrowWidth <> Value then begin
FArrowWidth := Value;
Invalidate;
end;
end;
//-----------------------------------------------------------------------------
// TMyPanelのArrowHeightプロパティ設定用メソッド
// 矢印の高さ(三角形の高さ)の設定
// この値は線の太さの倍数値
//-----------------------------------------------------------------------------
procedure TMyPanel.SetFArrowHeight(const Value: Integer);
begin
if FArrowHeight <> Value then begin
FArrowHeight := Value;
Invalidate;
end;
end;
//-----------------------------------------------------------------------------
// 実際の描画コード
// 直線を描画する時の端点の形状(ャップ)を矢印にする
//
// ACanvas : 描画先のTCanas
//-----------------------------------------------------------------------------
procedure TMyPanel.DrawImage(ACanvas: TCanvas);
var
LGPGraphics : TGPGraphics;
LGPPen : TGPPen;
LGPStartArrow : TGPAdjustableArrowCap;
LGPEndArrow : TGPAdjustableArrowCap;
LLineLength : Integer;
LPosX : Integer;
LPosY : Integer;
begin
//直線の長さと描画開始X座標値
LLineLength := 280;
LPosX := 20;
//始点と終端の矢印のオブジェクトを生成
//最後の引数がFalseの時は塗り潰しなし
LGPStartArrow := TGPAdjustableArrowCap.Create(FArrowHeight, FArrowWidth, False);
LGPEndArrow := TGPAdjustableArrowCap.Create(FArrowHeight, FArrowWidth, True);
//線を描画するために使用するTGPPenの生成
//生成した端点形状の情報をセット
LGPPen := TGPPen.Create(MakeColor(255, 0, 0, 0));
LGPPen.SetCustomStartCap(LGPStartArrow);
LGPPen.SetCustomEndCap(LGPEndArrow);
//描画先を指定してTGPGraphics生成
LGPGraphics := TGPGraphics.Create(ACanvas.Handle);
//線の太さを指定して描画
LPosY := 50;
LGPPen.SetWidth(5.0);
LGPGraphics.DrawLine(LGPPen, LPosX, LPosY, LPosX + LLineLength, LPosY);
//線の太さを変更して描画
LPosY := 150;
LGPPen.SetWidth(10.0);
LGPGraphics.DrawLine(LGPPen, LPosX, LPosY, LPosX + LLineLength, LPosY);
LGPStartArrow.Free;
LGPEndArrow.Free;
LGPPen.Free;
LGPGraphics.Free;
end;
//-----------------------------------------------------------------------------
// TMyPanelのPaintメソッド
// CanvasをTImage.CanvasにすればTImageへの描画となる
//-----------------------------------------------------------------------------
procedure TMyPanel.Paint;
begin
inherited;
DrawImage(Canvas);
end;
end.
03_矢印のインセット ( 底辺の切り込み ) の深さを変更する |
矢印の底辺に切り込み (インセット) を入れることができます.
このインセットの値も線の太さの倍数指定します.TMyPanel には矢印の幅と高さのプロパティも実装していますが,本サンプルはインセットの値だけのテストにしています. |
|
図4
実行開始時の画面 |
|
図5
設定例 |
リスト3
矢印の底辺部の切り込みのサイズ (深さ) を設定して結果を確認するサンプル |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls, GDIPOBJ, GDIPAPI, GDIPUTIL, Spin, ExtDlgs;
type
TMyPanel = class(TPanel)
private
FArrowWidth : Integer;
FArrowHeight : Integer;
FArrowMiddle : Integer;
procedure SetFArrowWidth(const Value: Integer);
procedure SetFArrowHeight(const Value: Integer);
procedure SetFArrowMiddle(const Value: Integer);
protected
procedure Paint; override;
procedure DrawImage(ACanvas: TCanvas);
public
constructor Create(AOwner: TComponent); override;
property ArrowWidth : Integer read FArrowWidth write SetFArrowWidth;
property ArrowHeight : Integer read FArrowHeight write SetFArrowHeight;
property ArrowMiddle : Integer read FArrowMiddle write SetFArrowMiddle;
end;
TForm1 = class(TForm)
SpinEdit1: TSpinEdit;
OpenPictureDialog1: TOpenPictureDialog;
procedure FormCreate(Sender: TObject);
procedure SpinEdit1Change(Sender: TObject);
private
{ Private 宣言 }
MyPanel : TMyPanel;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//=============================================================================
// フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
Self.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;
end;
SpinEdit1.Value := MyPanel.ArrowMiddle;
end;
//=============================================================================
// SpinEdit1のOnChangeイベント処理
// TMyPanelのArrowMiddleプロパティ設定
//=============================================================================
procedure TForm1.SpinEdit1Change(Sender: TObject);
begin
MyPanel.ArrowMiddle := SpinEdit1.Value;//
end;
{ TMyPanel }
//-----------------------------------------------------------------------------
// TMyPanelのコントラクタ
//-----------------------------------------------------------------------------
constructor TMyPanel.Create(AOwner: TComponent);
begin
inherited;
FArrowWidth := 8;
FArrowHeight := 8;
FArrowMiddle := 0;
end;
//-----------------------------------------------------------------------------
// TMyPanelのArrowWidthプロパティ設定用メソッド
// 矢印の幅(三角形の底辺の長さ)の設定
// この値は線の太さの倍数値
//-----------------------------------------------------------------------------
procedure TMyPanel.SetFArrowWidth(const Value: Integer);
begin
if FArrowWidth <> Value then begin
FArrowWidth := Value;
Invalidate;
end;
end;
//-----------------------------------------------------------------------------
// TMyPanelのArrowHeightプロパティ設定用メソッド
// 矢印の高さ(三角形の高さ)の設定
// この値は線の太さの倍数値
//-----------------------------------------------------------------------------
procedure TMyPanel.SetFArrowHeight(const Value: Integer);
begin
if FArrowHeight <> Value then begin
FArrowHeight := Value;
Invalidate;
end;
end;
//-----------------------------------------------------------------------------
// TMyPanelのArrowMiddleプロパティ設定用メソッド
// 矢印のインセット(切り込み)の設定
// この値は線の太さの倍数値
//-----------------------------------------------------------------------------
procedure TMyPanel.SetFArrowMiddle(const Value: Integer);
begin
if FArrowMiddle <> Value then begin
FArrowMiddle := Value;
Invalidate;
end;
end;
//-----------------------------------------------------------------------------
// 実際の描画コード
// 直線を描画する時の端点の形状(ャップ)を矢印にする
//
// ACanvas : 描画先のTCanas
//-----------------------------------------------------------------------------
procedure TMyPanel.DrawImage(ACanvas: TCanvas);
var
LGPGraphics : TGPGraphics;
LGPPen : TGPPen;
LGPEndArrow : TGPAdjustableArrowCap;
LLineLength : Integer;
LPosX : Integer;
LPosY : Integer;
begin
//直線の長さと描画開始X座標値
LLineLength := 280;
LPosX := 20;
//終端の矢印のオブジェクトを生成
LGPEndArrow := TGPAdjustableArrowCap.Create(FArrowHeight, FArrowWidth);
//インセットの値を設定
LGPEndArrow.SetMiddleInset(FArrowMiddle);
//線を描画するために使用するTGPPenの生成
//生成した端点形状の情報をセット
LGPPen := TGPPen.Create(MakeColor(255, 0, 150, 80));
//この方にもSet...という各種の設定用メソッドがある
LGPPen.SetCustomEndCap(LGPEndArrow);
//描画先を指定してTGPGraphics生成
LGPGraphics := TGPGraphics.Create(ACanvas.Handle);
//線の太さを指定して描画
LPosY := 100;
LGPPen.SetWidth(10.0);
LGPGraphics.DrawLine(LGPPen, LPosX, LPosY, LPosX + LLineLength, LPosY);
LGPEndArrow.Free;
LGPPen.Free;
LGPGraphics.Free;
end;
//-----------------------------------------------------------------------------
// TMyPanelのPaintメソッド
// CanvasをTImage.CanvasにすればTImageへの描画となる
//-----------------------------------------------------------------------------
procedure TMyPanel.Paint;
begin
inherited;
DrawImage(Canvas);
end;
end.
ここまでのサンプルては,TGPPen.SetCustomStartCap, TGPPen.SetCustomEndCap で端点形状としての矢印を設定ししました.TGPPen の SetStartCap, SetEndCpa というメソッドでも端点形状を設定できます.これらのメソッドの引数には,GDI+ があらかじめ用意している定数名を使用します.
それらの定数名を使用した場合の確認テストです. |
|
図6
実行結果
- 一番上は LineCapFlat で,これがデフォルトの端点形状
|
リスト4
指定可能な端点形状の定数名による端点形状 |
//-----------------------------------------------------------------------------
// 実際の描画コード
// 直線を描画する時の端点形状
// TGPPen.SetStartCapとTGPPen.SetEndCapで指定可能な値の場合
//
// ACanvas : 描画先のTCanas
//-----------------------------------------------------------------------------
procedure TMyPanel.DrawImage(ACanvas: TCanvas);
var
LGPGraphics : TGPGraphics;
LGPPen : TGPPen;
LLineLength : Integer;
LPosX : Integer;
LPosY : Integer;
LIncY : Integer;
begin
//直線の長さと描画開始X座標値
LLineLength := 270;
LPosX := 30;
LIncY := 35;
//線を描画するために使用するTGPPenの生成
LGPPen := TGPPen.Create(MakeColor(255, 0, 150, 100));
LGPPen.SetWidth(10.0);
//描画先を指定してTGPGraphics生成
LGPGraphics := TGPGraphics.Create(ACanvas.Handle);
//端点の形状を指定して描画
LPosY := 50;
LGPPen.SetStartCap(LineCapFlat);
LGPPen.SetEndCap(LineCapFlat);
LGPGraphics.DrawLine(LGPPen, LPosX, LPosY, LPosX + LLineLength, LPosY);
//端点の形状を変更して描画
LPosY := LPosY + LIncY;
LGPPen.SetStartCap(LineCapSquare);
LGPPen.SetEndCap(LineCapSquare);
LGPGraphics.DrawLine(LGPPen, LPosX, LPosY, LPosX + LLineLength, LPosY);
//端点の形状を変更して描画
LPosY := LPosY + LIncY;
LGPPen.SetStartCap(LineCapRound);
LGPPen.SetEndCap(LineCapRound);
LGPGraphics.DrawLine(LGPPen, LPosX, LPosY, LPosX + LLineLength, LPosY);
//端点の形状を変更して描画
LPosY := LPosY + LIncY;
LGPPen.SetStartCap(LineCapTriangle);
LGPPen.SetEndCap(LineCapTriangle);
LGPGraphics.DrawLine(LGPPen, LPosX, LPosY, LPosX + LLineLength, LPosY);
//端点の形状を変更して描画
LPosY := LPosY + LIncY;
LGPPen.SetStartCap(LineCapNoAnchor);
LGPPen.SetEndCap(LineCapNoAnchor);
LGPGraphics.DrawLine(LGPPen, LPosX, LPosY, LPosX + LLineLength, LPosY);
//端点の形状を変更して描画
LPosY := LPosY + LIncY;
LGPPen.SetStartCap(LineCapSquareAnchor);
LGPPen.SetEndCap(LineCapSquareAnchor);
LGPGraphics.DrawLine(LGPPen, LPosX, LPosY, LPosX + LLineLength, LPosY);
//端点の形状を変更して描画
LPosY := LPosY + LIncY;
LGPPen.SetStartCap(LineCapRoundAnchor);
LGPPen.SetEndCap(LineCapRoundAnchor);
LGPGraphics.DrawLine(LGPPen, LPosX, LPosY, LPosX + LLineLength, LPosY);
//端点の形状を変更して描画
LPosY := LPosY + LIncY;
LGPPen.SetStartCap(LineCapDiamondAnchor);
LGPPen.SetEndCap(LineCapDiamondAnchor);
LGPGraphics.DrawLine(LGPPen, LPosX, LPosY, LPosX + LLineLength, LPosY);
//端点の形状を変更して描画
LPosY := LPosY + LIncY;
LGPPen.SetStartCap(LineCapArrowAnchor);
LGPPen.SetEndCap(LineCapArrowAnchor);
LGPGraphics.DrawLine(LGPPen, LPosX, LPosY, LPosX + LLineLength, LPosY);
LGPPen.Free;
LGPGraphics.Free;
end;
//-----------------------------------------------------------------------------
// TMyPanelのPaintメソッド
// CanvasをTImage.CanvasにすればTImageへの描画となる
//-----------------------------------------------------------------------------
procedure TMyPanel.Paint;
begin
inherited;
DrawImage(Canvas);
end;
|