グラフィックオブジェクト
MFCにはビットマップ、パレット、ブラシ、ペン、リージョン、フォントといったGDI(Graphical Device Interface)オブジェクトの階層も含まれています。この階層の基本となるのが、抽象クラスのCGdiObjectです。CGdiObjectは、HBITMAP、HPALETTE、HBRUSH、HPEN、HRGN、またはHFONT型の添付オブジェクトを含んだHANDLEをカプセル化したものです。この基本クラスから派生したクラスには、次のものがあります。
- CBitmap
ビットマップを操作するクラス - CPallete
Windowsパレットをカプセル化したクラス - CBrush
ブラシをカプセル化したクラス。ペイントと塗りつぶしで使用します - CPen
ペンをカプセル化したクラス。線の描画で使用します - CRgn
リージョン(ウィンドウ内の楕円または多角形の領域)をカプセル化したクラス。クリッピングで使用します - CFont
フォントをカプセル化したクラス。テキストの描画で使用します
以下では、ペン、ブラシ、ビットマップ、フォントを使って線、シェイプ、イメージ、テキストを描画する方法について説明します。
ペンの使用方法
ペンは、線を描画するときに使うグラフィックオブジェクトです。さまざまな種類のペンを作成できます。
- 実線(PS_SOLID)
- 破線(PS_DASH)
- 点線(PS_DOT)
- 1点鎖線(PS_DASHDOT)
破線と点線 - 2点鎖線(PS_DASHDOTDOT)
1つの破線と2つの点線 - コスメティック(PS_COSMETIC)
3つの属性、すなわち幅(デバイス単位)、スタイル、色を持つ - ジオメトリック(PS_GEOMETRIC)
コスメティックペンのすべての属性に加えて、パターン、オプションのハッチ、線端のスタイル、結合のスタイルを持つ
ペンの使用例1
次に示す1番目の例では、1ピクセル幅の実線の赤色のペンを作成し、そのペンを使って四角形を描画します(4本の線を結合します)。オブジェクトを選択するときにSelectObject()を呼び出すことに注意してください。この関数は任意の種類のGDIオブジェクトを受け取り、置き換えられた同じ種類の古いオブジェクトへのポインタを返します。このポインタを保持しておいて、新しいオブジェクトが不要になったら古いオブジェクトを復元する必要があります。
void CChildView::OnPaint()
{
CPaintDC dc(this);
CRect rc;
GetClientRect(rc);
rc.DeflateRect(50, 50, 50, 50);
// create a solid, red, 1 pixel pen
CPen pen(PS_SOLID, 1, RGB(255, 0, 0));
// select the pen into the device context
CPen* oldpen = (CPen*)dc.SelectObject(&pen);
// draw a rectangle
dc.MoveTo(rc.left, rc.top);
dc.LineTo(rc.right, rc.top);
dc.LineTo(rc.right, rc.bottom);
dc.LineTo(rc.left, rc.bottom);
dc.LineTo(rc.left, rc.top);
// select the old pen back
dc.SelectObject(oldpen);
}

ペンの使用例2
2番目の例では、別の種類のペンを作成します。実線ペンを除く他のすべてのペンでは、1デバイス単位の幅だけが有効です。他の値を設定すると、実線ペンが作成されます。
void CChildView::OnPaint()
{
CPaintDC dc(this);
CRect rc;
GetClientRect(rc);
rc.DeflateRect(50, 50, 50, 50);
// create a solid, red, 1 pixel pen
CPen pen_solid (PS_SOLID, 1, RGB(255, 0, 0));
CPen pen_dash (PS_DASH, 1, RGB(255, 0, 0));
CPen pen_dot (PS_DOT, 1, RGB(255, 0, 0));
CPen pen_dashdot (PS_DASHDOT, 1, RGB(255, 0, 0));
CPen pen_dashdotdot (PS_DASHDOTDOT, 1, RGB(255, 0, 0));
// select the pen into the device context
CPen* oldpen = (CPen*)dc.SelectObject(&pen_solid);
dc.MoveTo(rc.left, rc.top);
dc.LineTo(rc.right, rc.top);
dc.SelectObject(&pen_dash);
dc.MoveTo(rc.left, rc.top+25);
dc.LineTo(rc.right, rc.top+25);
dc.SelectObject(&pen_dot);
dc.MoveTo(rc.left, rc.top+50);
dc.LineTo(rc.right, rc.top+50);
dc.SelectObject(&pen_dashdot);
dc.MoveTo(rc.left, rc.top+75);
dc.LineTo(rc.right, rc.top+75);
dc.SelectObject(&pen_dashdotdot);
dc.MoveTo(rc.left, rc.top+100);
dc.LineTo(rc.right, rc.top+100);
// select the old pen back
dc.SelectObject(oldpen);
}

ペンの使用例3
最後の例では、ジオメトリックペンを作成します。これは、破線と点線から成り、幅は5ピクセルで、線端は丸型です。
void CChildView::OnPaint()
{
CPaintDC dc(this);
CRect rc;
GetClientRect(rc);
rc.DeflateRect(50, 50, 50, 50);
// compute the width for the pen in device units
int width = -MulDiv(5, dc.GetDeviceCaps(LOGPIXELSY), 72);
// create a geometric pen
LOGBRUSH logBrush;
logBrush.lbStyle = BS_SOLID;
logBrush.lbColor = RGB(255, 0, 0);
CPen pen(PS_DASHDOT|PS_GEOMETRIC|PS_ENDCAP_ROUND, width,
&logBrush);
// select the pen into the device context
CPen* oldpen = (CPen*)dc.SelectObject(&pen);
// draw a rectangle
dc.MoveTo(rc.left, rc.top);
dc.LineTo(rc.right, rc.top);
dc.LineTo(rc.right, rc.bottom);
dc.LineTo(rc.left, rc.bottom);
dc.LineTo(rc.left, rc.top);
// select the old pen back
dc.SelectObject(oldpen);
}

