プログラミング モデルの変更点

次のセクションでは、Windows GDI+ でのプログラミングと Windows グラフィックス デバイス インターフェイス (GDI) を使用したプログラミングとは異なるいくつかの方法について説明します。

デバイス コンテキスト、ハンドル、およびグラフィックス オブジェクト

GDI (以前のバージョンの Windows に含まれるグラフィックス デバイス インターフェイス) を使用してプログラムを記述した場合は、デバイス コンテキスト (DC) の概念をよく理解しています。 デバイス コンテキストは、特定のディスプレイ デバイスの機能と、そのデバイスでのアイテムの描画方法を指定する属性に関する情報を格納するために Windows によって使用される構造です。 ビデオディスプレイのデバイスコンテキストも、ディスプレイ上の特定のウィンドウに関連付けられます。 まず、デバイス コンテキスト (HDC) へのハンドルを取得し、そのハンドルを、実際に描画を行う GDI 関数に引数として渡します。 また、デバイス コンテキストの属性を取得または設定する GDI 関数にハンドルを引数として渡します。

GDI+ を使用する場合は、GDI を使用する場合と同じように、ハンドルとデバイス コンテキストに関する必要はありません。 Graphics オブジェクトを作成し、そのメソッドを使い慣れたオブジェクト指向のスタイル (myGraphicsObject.DrawLine(parameters) で呼び出すだけです。 Graphics オブジェクトは、デバイス コンテキストが GDI の中心にあるのと同じように、GDI+ の中核をなします。 デバイス コンテキストと Graphics オブジェクトは同様の役割を果たしますが、デバイス コンテキスト (GDI) で使用されるハンドルベースのプログラミング モデルと 、Graphics オブジェクト (GDI+) で使用されるオブジェクト指向モデルには、いくつかの基本的な違いがあります。

Graphics オブジェクトは、デバイス コンテキストと同様に、画面上の特定のウィンドウに関連付けされ、アイテムの描画方法を指定する属性 (スムージング モードやテキスト レンダリング ヒントなど) が含まれています。 ただし、 Graphics オブジェクトは、デバイス コンテキストとしてペン、ブラシ、パス、イメージ、またはフォントに関連付けられません。 たとえば、GDI では、デバイス コンテキストを使用して線を描画する前に、 SelectObject を呼び出してペン オブジェクトをデバイス コンテキストに関連付ける必要があります。 これは、デバイス コンテキストへのペンの選択と呼ばれます。 デバイス コンテキストで描画されたすべての線は、別のペンを選択するまでそのペンを使用します。 GDI+ では、引数として Pen オブジェクトを Graphics クラスの DrawLine メソッドに渡します。 特定の Pen オブジェクトを Graphics オブジェクトに関連付けなくても、一連の DrawLine 呼び出しごとに異なる Pen オブジェクトを使用できます。

線を描画する 2 つの方法

次の 2 つの例では、それぞれ、位置 (20,10) から位置 (200,100) までの幅 3 の赤い線を描画します。 最初の例では GDI を呼び出し、2 番目の例では C++ クラス インターフェイスを介して GDI+ を呼び出します。

GDI を使用した線の描画

GDI で線を描画するには、デバイス コンテキストとペンの 2 つのオブジェクトが必要です。 BeginPaint を呼び出してデバイス コンテキストへのハンドルを取得し、CreatePen を呼び出してペンへのハンドルを取得します。 次に、 SelectObject を呼び出して、デバイス コンテキストにペンを選択します。 MoveToEx を呼び出してペン位置を (20, 10) に設定し、LineTo を呼び出してそのペン位置から (200, 100) に線を描画します。 MoveToEx と LineTo は どちらも引数として hdc を受け取ります。

HDC          hdc;
PAINTSTRUCT  ps;
HPEN         hPen;
HPEN         hPenOld;
hdc = BeginPaint(hWnd, &ps);
   hPen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0));
   hPenOld = (HPEN)SelectObject(hdc, hPen);
   MoveToEx(hdc, 20, 10, NULL);
   LineTo(hdc, 200, 100);
   SelectObject(hdc, hPenOld);
   DeleteObject(hPen);
EndPaint(hWnd, &ps);

GDI+ と C++ クラス インターフェイスを使用して行を描画する

GDI+ と C++ クラス インターフェイスを使用して線を描画するには、 Graphics オブジェクトと Pen オブジェクトが必要です。 これらのオブジェクトへのハンドルは Windows に要求しません。 代わりに、コンストラクターを使用して Graphics クラス ( Graphics オブジェクト) のインスタンスと Pen クラス ( Pen オブジェクト) のインスタンスを作成します。 行の描画には、Graphics クラスの Graphics::D rawLine メソッドを呼び出す必要があります。 Graphics::D rawLine メソッドの最初のパラメーターは、Pen オブジェクトへのポインターです。 これは、前の GDI の例に示すように、デバイス コンテキストにペンを選択するよりも簡単で柔軟なスキームです。

HDC          hdc;
PAINTSTRUCT  ps;
Pen*         myPen;
Graphics*    myGraphics;
hdc = BeginPaint(hWnd, &ps);
   myPen = new Pen(Color(255, 255, 0, 0), 3);
   myGraphics = new Graphics(hdc);
   myGraphics->DrawLine(myPen, 20, 10, 200, 100);
   delete myGraphics;
   delete myPen;
EndPaint(hWnd, &ps);

ペン、ブラシ、パス、イメージ、およびパラメーターとしてのフォント

前の例では、描画メソッドを提供する Graphics オブジェクトとは別に Pen オブジェクトを作成および管理できることを示しています。 BrushGraphicsPathImageFont の各オブジェクトは、 Graphics オブジェクトとは別に作成および管理することもできます。 Graphics クラスによって提供される描画メソッドの多くは、引数として BrushGraphicsPathImage、または Font オブジェクトを受け取ります。 たとえば、 Brush オブジェクトのアドレスは FillRectangle メソッドに引数として渡され、 GraphicsPath オブジェクトのアドレスは 引数として Graphics::D rawPath メソッドに渡されます。 同様に、 Image オブジェクトと Font オブジェクトのアドレスは 、DrawImage メソッドと DrawString メソッドに渡されます。 これは GDI とは対照的に、デバイス コンテキストにブラシ、パス、イメージ、またはフォントを選択し、描画関数の引数としてデバイス コンテキストにハンドルを渡します。

メソッドのオーバーロード

GDI+ メソッドの多くはオーバーロードされています。つまり、複数のメソッドが同じ名前を共有しますが、パラメーター リストは異なります。 たとえば、Graphics クラスの DrawLine メソッドは次の形式になります。

Status DrawLine(IN const Pen* pen,
                IN REAL x1,
                IN REAL y1,
                IN REAL x2,
                IN REAL y2);
Status DrawLine(IN const Pen* pen,
                IN const PointF& pt1,
                IN const PointF& pt2);
Status DrawLine(IN const Pen* pen,
                IN INT x1,
                IN INT y1,
                IN INT x2,
                IN INT y2);
    
Status DrawLine(IN const Pen* pen,
                IN const Point& pt1,
                IN const Point& pt2);

上の 4 つの DrawLine バリエーションはすべて、 Pen オブジェクトへのポインター、開始点の座標、終了点の座標を受け取ります。 最初の 2 つのバリエーションは座標を浮動小数点数として受け取り、最後の 2 つのバリエーションは座標を整数として受け取ります。 1 番目と 3 番目のバリエーションは 4 つの個別の数値のリストとして座標を受け取り、2 番目と 4 番目のバリエーションは Point (または PointF) オブジェクトのペアとして座標を受け取ります。

現在位置がなくなった

前に示した DrawLine メソッドでは、行の始点と終点の両方が引数として受け取られたことに注意してください。 これは、(x1, y1) から始まり (x2, y2) で終わる線を描画するために、MoveToEx を呼び出して現在のペン位置と LineTo を設定する GDI スキームからの逸脱です。 GDI+ 全体として、現在位置の概念を破棄しました。

描画と塗りつぶしの個別のメソッド

GDI+ は、アウトラインを描画し、四角形などの図形の内部を塗りつぶす場合、GDI よりも柔軟性が高くなります。 GDI には、アウトラインを描画し、四角形の内部を 1 つのステップで塗りつぶす Rectangle 関数があります。 アウトラインは現在選択されているペンで描画され、内部は現在選択されているブラシで塗りつぶされます。

hBrush = CreateHatchBrush(HS_CROSS, RGB(0, 0, 255));
hPen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0));
SelectObject(hdc, hBrush);
SelectObject(hdc, hPen);
Rectangle(hdc, 100, 50, 200, 80);

GDI+ には、アウトラインを描画し、四角形の内部を塗りつぶす個別のメソッドがあります。 Graphics クラスの DrawRectangle メソッドは、Pen オブジェクトのアドレスをパラメーターの 1 つとして持ち、FillRectangle メソッドは Brush オブジェクトのアドレスをパラメーターの 1 つとして持ちます。

HatchBrush* myHatchBrush = new HatchBrush(
   HatchStyleCross,
   Color(255, 0, 255, 0),
   Color(255, 0, 0, 255));
Pen* myPen = new Pen(Color(255, 255, 0, 0), 3);
myGraphics.FillRectangle(myHatchBrush, 100, 50, 100, 30);
myGraphics.DrawRectangle(myPen, 100, 50, 100, 30);

GDI+ の FillRectangle メソッドと DrawRectangle メソッドは、四角形の左端、上端、幅、および高さを指定する引数を受け取ります。 これは、四角形の左端、右端、上端、下端を指定する引数を受け取る GDIRectangle 関数とは対照的です。 また、GDI+ の Color クラスのコンストラクターには 4 つのパラメーターがあることにも注意してください。 最後の 3 つのパラメーターは、通常の赤、緑、青の値です。最初のパラメーターはアルファ値で、描画する色と背景色をブレンドする範囲を指定します。

リージョンの構築

GDI には、リージョンを作成するための関数 (CreateRectRgn、CreateEllpticRgn、CreateRoundRectRgn、CreatePolygonRgn、CreatePolyPolygonRgn) が用意されています。 GDI+ の Region クラスには、四角形、楕円、丸み付き四角形、および多角形を引数として受け取る類似のコンストラクターが必要な場合がありますが、これは当たりません。 GDI+ の Region クラスは、 Rect オブジェクト参照を受け取るコンストラクターと 、GraphicsPath オブジェクトのアドレスを受け取る別のコンストラクターを提供します。 楕円、丸い四角形、または多角形に基づいて領域を構築する場合は、 GraphicsPath オブジェクト (楕円を含むなど) を作成し、その GraphicsPath オブジェクトのアドレスを Region コンストラクターに渡すことで簡単に作成できます。

GDI+ を使用すると、図形とパスを組み合わせることで複雑な領域を簡単に形成できます。 Region クラスには Union メソッドと Intersect メソッドがあり、パスまたは別のリージョンを使用して既存のリージョンを拡張するために使用できます。 GDI+ スキームの優れた機能の 1 つは、引数として Region コンストラクターに渡されたときに GraphicsPath オブジェクトが破棄されないことです。 GDI では、 PathToRegion 関数を使用してパスをリージョンに変換できますが、パスはプロセスで破棄されます。 また、引数として Union メソッドまたは Intersect メソッドにアドレスが渡された場合、 GraphicsPath オブジェクトは破棄されないため、特定のパスを複数の個別の領域の文書パーツとして使用できます。 次の例を参照してください。 onePath は、既に初期化されている GraphicsPath オブジェクト (単純または複雑) へのポインターであるとします。

Region  region1(rect1);
Region  region2(rect2);
region1.Union(onePath);
region2.Intersect(onePath);