次の方法で共有


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

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

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

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

GDI+ を使用する場合、GDI を使用する場合ほどハンドルやデバイス コンテキストを気にする必要はありません。 Graphics オブジェクトを作成し、そのメソッドを、使い慣れたオブジェクト指向スタイル (myGraphicsObject.DrawLine(parameters)) で呼び出すだけです。 デバイス コンテキストが GDI の中核であるのと同様に、 Graphics オブジェクトは 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::DrawLine メソッドを呼び出します。 Graphics::DrawLine メソッドの最初のパラメータは、 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);

ペン、ブラシ、パス、画像、フォントをパラメータとして

前の例では、 Pen オブジェクトは、描画メソッドを提供する Graphics オブジェクトとは別に作成および管理できることを示しています。 BrushGraphicsPathImage、および Font オブジェクトも、 Graphics オブジェクトとは別に作成および管理できます。 Graphics クラスによって提供される描画メソッドの多くは、引数として BrushGraphicsPathImage、または Font オブジェクトを受け取ります。 たとえば、 Brush オブジェクトのアドレスは FillRectangle メソッドに引数として渡され、 GraphicsPath オブジェクトのアドレスは Graphics::DrawPath メソッドに引数として渡されます。 同様に、 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 つのバリエーションは座標を整数として受け取ります。 最初と 3 番目のバリエーションは、4 つの個別の数値のリストとして座標を受け取りますが、2 番目と 4 番目のバリエーションは、Point (または PointF) オブジェクトのペアとして座標を受け取ります。

現在のポジションはもうありません

前述の DrawLine メソッドでは、線の開始点と終了点の両方が引数として受け取られることに注意してください。 これは、 MoveToEx を呼び出して現在のペンの位置を設定し、その後に LineTo を呼び出して (x1y1) から始まり (x2y2) で終わる線を描画する 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 メソッドには、そのパラメータの 1 つとして Pen オブジェクトのアドレスがあり、 FillRectangle メソッドには、そのパラメータの 1 つとして Brush オブジェクトのアドレスがあります。

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 メソッドは、四角形の左端、上端、幅、高さを指定する引数を受け取ることに注意してください。 これは、四角形の左端、右端、上端、下端を指定する引数を取る GDI Rectangle 関数とは対照的です。 また、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 つは、 GraphicsPath オブジェクトが Region コンストラクターに引数として渡されたときに破棄されないことです。 GDI では、 PathToRegion 関数を使用してパスを領域に変換できますが、その過程でパスは破棄されます。 また、 GraphicsPath オブジェクトのアドレスが Union メソッドまたは Intersect メソッドに引数として渡されても、そのオブジェクトは破棄されないため、特定のパスを複数の個別の領域の構成要素として使用できます。 これを次の例に示します。 onePath は、すでに初期化されている GraphicsPath オブジェクト (単純または複雑) へのポインターであると想定します。

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