Delphi Programming / Object Pascal
サイトのトップページへ リンクのページへ ロゴマーク
[掲載 2012年10月25日] [更新 2014年07月09日] GDI+ 関係サンプル
GDI+ 関係サンプル
概要
動作確認等 サンプルよって異なる
全てのサンプルがダウンロード可能 (実行ファイル同梱)
gdiplus.zip [1,144 KB] 2002年02月15日版 (Delphi XE 以前用)







GDI+ 関係サンプル


GDI+ は Windows XP で実装されたグラフィクスサブシステムですです.
GDI+を使うと,.NET Frameworkと同等のグラフィック機能を Windows API ベースのプログラムから使用することができます.GDI+ を使用しない場合は GDI による描画ということになります.

GDI+ の関数類は,Gdiplus.dll が提供しています.Delphi XE2 では GDI+ の API を利用するためライブラリが標準実装されました.
Microsoft Office 関連でも,少なくも Office XP, 2003 では GDI+ を使用しています.GDI+ のサンプルは,ネット上に多くありますが,若干のテストプログラムを作成してみました.
Delphi で使用可能な GDI+ Library には,この他,.NET Framework 互換の

   Delphi GDI+ Library for use with Delphi 2009 (version 1.2)

があります.MSDN の記事のほとんどが .NET Framework 対応のものですから,今後はこちらの方の利用を考えてもいいのかも知れません.Delphi XE2 に実装されているのが .NET 互換の方ではないので,今回は使用しませんでした.
上のリンクの Delphi 2009 以降で使用可能な .NET 互換の GDI+ には,Blur (ブラー) というガウスばかしのクラスがありますが,本サンプルで使用している GDI+ には実装されていません.Delphi XE2 の GDI+ ライブラリには,拡張された Blur クラスが実装されています.

GDI+ ライブラリの機能を使用するには,uses に GDIPAPI, GDIPOBJ 等を追加します.






Delphi XE 以前で GDI+ ライブラリを使用する ( gdiplus.zip )


Delphi XE 以前で GDI+を使用するには,本ページから GDI+ ライブラリ (2002年02月15日版) を別途ダウンロードしてください.
これは progdigy.com というサイトで提供されていたものですが,2013年07月11日現在入手できません.MPL1.1 のライセンスに基づき,当サイトで再配布しています..
次の手順で導入します.

  • gdiplus.zip をダウンロード
  • ダウンロードした gdiplus.zip を適当なフォルダに解凍
  • 解凍したフォルダ内の [pas] フォルダにパスを通す
  • uses に GDIPAPI と GDIPOBJ を追加する
Delphi 7 以前であれば,このまま使用できます.それ以降のバージョンでは,以下のエラーが発生して,プロジェクトのコンパイルに失敗します.

[DCC エラー] DirectDraw.pas(358): E2154 'IDirectDrawSurface' 型は終了処理が必要です - 構造体の可変部に置くことは許されません

ダウンロードした GDI+ のバージョン定義ファイル Jedi.inc は Delphi 7 までの対応です.そのために必要なコードが実行されないのが原因で発生します (情報源 : Dephi-fan の GDI+ を使う).
そこで,筆者は次のリストのように修正しました.つまり,Delphi のバージョンを全て Delphi 7 にごまかす設定です.この修正をしても,[ヒント] や [警告] は表示されますが,使用可能です.


リスト1
[pas] フォルダ内の Jedi.inc を修正.Delphi 7 以降全てで使用可能に
VERXXX to COMPILERX, DELPHIX and BCBX mappings の部分を以下に変更
//------------------------------------------------------------------------------
// VERXXX to COMPILERX, DELPHIX and BCBX mappings
//------------------------------------------------------------------------------

{$IF CompilerVersion > 14.99}
  {$DEFINE COMPILER7}
  {$IFDEF BCB}
    {$DEFINE BCB7}
    {$DEFINE BCB}
  {$ELSE}
    {$DEFINE DELPHI7}
    {$DEFINE DELPHI}
  {$ENDIF}
{$IFEND}


どうしても [ヒント] や [警告] が気になるのであれば,


は,大文字あるいは小文字に修正します.これは,主にメソッド名の先頭文字です.また,


は,下のコードのように,reintroduce 指令を追加します.


リスト2
reintroduce 指令を追加
    function Equals(region: TGPRegion; g: TGPGraphics): BOOL; reintroduce;




GDI+ における図形や画像等の描画先


GDI+ のグラフィックスのオブジェクト,TGPGraphics のインスタンス (実体) は,以下のように,描画対象の TCanvas のハンドルを引数に指定して作成します.

例えば,TBitmap の Canvas に描画する場合は,TBitmap.Canvas.Handle とします.
TImage の Canvas に描画する場合は,TImage.Canvas.Handle とします.
TBitmap や TImage はクラス名です.実際にはそれらのインスタンスの名前とします,Image1 であれば Image1.Canvas.Handle となります.


  //描画先を指定してTGPGraphicsオブジェクトを生成する
  LGPGraphic := TGPGraphics.Create(Canvas.Handle);


そして,この TGPGraphics の描画用のプロパティである色等を設定し,描画用のメソッドで図形や画像を描画します.すると,指定した TCanvas に図形なり画像が描画されることになります.描画先が TImage 等であれば描画結果は目に見えます.
TBitmap の場合は,描画コードを実行しても実際には目には見えません.処理結果としての,そのビットマップを何かに表示するとか,保存するとことになります.

ペンやブラシ等の設定は,TCanvas のようなプロパティではなく,それそれのオブジェクトを生成して設定します.ペンや線のプロパティを設定するためのオブジェクト類は,この TGPGraphics のオブジェクトがなくても,独立して設定できます.




  //描画座標値をポイントで指定
  P1 := MakePoint(20,  150);
  P2 := MakePoint(200, 150);
  //TGPPenのペンの設定で線を引く(描画する)
  LGPGraphic.DrawLine(LGPPen, P1, P2);




サンプルで使用している TMyPanel


サンプルの多くは,フォームに配置したパネル,あるいは,TPanel を継承した TMyPanel というコントロールの Paint メソッドで,その Canvas に画像や図形を描画しています.

アプリケーションを開発する際,多くの場合,複数のフォームあるいはユニットを使用します.そしてそれらのフォームあるいはユニットと変数のやりとりが必要となります.
この時,グローバルな変数を介するよりも,プロパティ,あるいはメソッド類で行うのが一般的です.このことを意識して TPanel の派生クラスを作成して,他のフォーム,ユニット内のクラスとのやりとりの代わりとしています.

描画コード自体は Paint メソッド以外にはありません.フォームの OnPaint イベント,あるいは,TPaintBox の OnPaint イベント等に,この TMyPanel メソッドのコードをコピーして貼り付け,コード内のプロパティ等の変数に直接値を代入すれば,ネット上の多くのサンプル,デモプログラムと同じように扱えます.

TImage に描画するサンプルもありますが,TImage は内部で「オフスクリーンビットマップ」というビットマップを生成して描画内容を表示します.そのため,描画内容を変更する際,一度描画内容をクリアしてから再度描画コードを実行するという作業が必要な場合があります.

TImage は,他のウィンドウが上に重なっても,描画の更新を内部で自動で実行してくれます.また重ね描画も自動で処理してくれます.GDI+ で描画する場合は,追加の描画もコードを追加しなければなりません.そのため,TImage のような追加描画の機能を実装するには,オフスクリーンビットマップのような仕組みが必要となることがあります.



[備考]
ほとんどのサンプルは,継承元を TPanel から TGraphicControl の TPaintBox に変更してもそのまま動作しますが,座標値の変換が必要な場合があります.





GDI+ を使用した描画コードの印刷


GDI+ の描画コードをプリンタに出力する時は,印刷のコーディングにもよりますが,次のように,描画コードを実行する前にマッピングが必要な場合があります.GDI+ の関数の中には,UnitPixelを引数で指定するものがあります.その場合は必要ありません.
この現象は,.NET 互換の GDI+ では必要ありません.なくても正しく印刷できます.


リスト3
GDI+ を使用した描画コードを印刷する際は,描画コードを実行する前にマッピングが必要
procedure TplResizeZLine.DrawRoutine(ACanvas: TCanvas; OffSetX: Integer=0;
  OffSetY: Integer=0);
var
  LGraphic : TGPGraphics;
begin

  //----------- 略 -------------------------

  LGraphic := TGPGraphics.Create(ACanvas.Handle);
  SetMapMode (ACanvas.Handle, MM_TEXT);
  LGraphic.SetPageUnit(UnitPixel);

  //----------- 描画コード ------------------

end;




サンプルプログラムのダウンロード方法とブロックの解除


各ページの上の方,最初の方に,下図のような画像があります.これをクリックしてください.サンプル単位ではなく,そのページのサンプルの一括ダウンロードとなっています.
各サンプルの個別ダウンロードの要望がありましたが,対応の予定はありません.
ダウンロードしたら [ブロックの解除] をしてください.




記事内のコードをコピーして利用する場合は,各サンプルコードの左上のコピーボタンをクリックするとクリップボードにコピーできます.