|
ペンを使った描画
今回はGDIオブジェクトのペンを使った描画方法です。では、さっそくダイアログベースでプロジェクトを作成し、次のようなダイアログを作ります。

ペンのスタイルをコンボボックスで、太さをスピンコントロール付きのエディットボックスで指定します。"色選択"ボタンが押されたら色選択ダイアログを表示します。選択されたスタイル、太さ、色で直線を描画します。
スタイルのコンボボックスにはあらかじめデータを入れておきましょう。Dataに「SOLID;DASH;DOT;DASHDOT;DASHDOTDOT;NULL;INSIDERFRAME;」を入れておきます。

次は、DDX変数を追加します。スタイルのコンボボックスにはCString型のValue変数、太さのスピンコントロールには、CSpinButtonCtrl型のControl変数を追加します。


現在の色を保持するために、ダイアログクラスに変数を追加します。色情報はCOLORREF型にします。

現在のペンを保持するために、ダイアログクラスにCPen型の変数を追加します。

次は、ペンの設定が変化したときにリアルタイムに描画しなおすために、イベントハンドラを追加しておきましょう。スタイルのコンボボックスにはCBN_SELCHANGE、太さのエディットボックスにはEN_CHANGEのイベントハンドラを追加します。


では、コードの方を実装していきましょう。OnInitDialog()でそれぞれの変数を初期化しておきます。
BOOL CDC3Dlg::OnInitDialog()
{
CDialog::OnInitDialog();
SetIcon(m_hIcon, TRUE); // 大きいアイコンの設定
SetIcon(m_hIcon, FALSE); // 小さいアイコンの設定
// TODO: 初期化をここに追加します。
{
CClientDC cdc(this);
m_color = (cdc.GetDCPenColor() != CLR_INVALID)
? cdc.GetDCPenColor() : RGB(0, 0, 0); // ペンの色
m_xcSpinWidth.SetPos32(1); // ペンの太さ
m_xvComboStyle = _T("SOLID"); // ペンのスタイル
UpdateData(FALSE);
}
return TRUE;
}
|
まずは、CClientDCクラスのオブジェクトを作ります。現在のペンの色はCDC::GetDCPenColor()関数で取得できます。
| COLORREF CDC::GetDCPenColor( ) const; |
| 説明: |
現在のペンの色を取得 |
| 引数: |
なし |
| 戻り値: |
現在のペンの色。取得できなかった場合はCLR_INVALID |
次は色選択ボタンのイベントハンドラです。現在のペンの色を変更します。これについては、詳しくは「色選択ダイアログ」を見てください。
// "色選択"ボタン押下
void CDC3Dlg::OnBnClickedBtnColorsel()
{
CColorDialog CColorDialog(m_color);
int err = 0;
// 色選択ダイアログ表示
if (CColorDialog.DoModal() == IDOK)
{
m_color = CColorDialog.GetColor();
Invalidate(FALSE);
}
return;
}
|
次はスタイルのコンボボックス選択変更、太さのエディットボックス更新のイベントハンドラです。ここではCWnd::Invalidate()関数を使って再描画しているだけです。
// Styleコンボ選択変更
void CDC3Dlg::OnCbnSelchangeComboStyle()
{
Invalidate(FALSE);
}
// Widthエディット更新
void CDC3Dlg::OnEnChangeEditWidth()
{
Invalidate(FALSE);
}
|
次はOnPaint()関数です。ここで、現在のペンを使って線分を描画します。
void CDC3Dlg::OnPaint()
{
CClientDC cdc(this);
int nPenStyle = PS_SOLID;
int nWidth = 1;
int err = 0;
if (!err)
{
UpdateData();
// ペンのスタイル
if (m_xvComboStyle == _T("SOLID")) nPenStyle = PS_SOLID;
if (m_xvComboStyle == _T("DASH")) nPenStyle = PS_DASH;
if (m_xvComboStyle == _T("DOT")) nPenStyle = PS_DOT;
if (m_xvComboStyle == _T("DASHDOT")) nPenStyle = PS_DASHDOT;
if (m_xvComboStyle == _T("DASHDOTDOT")) nPenStyle = PS_DASHDOTDOT;
if (m_xvComboStyle == _T("NULL")) nPenStyle = PS_NULL;
if (m_xvComboStyle == _T("INSIDEFRAME")) nPenStyle = PS_INSIDEFRAME;
// ペンの太さ
nWidth = m_xcSpinWidth.GetPos32();
}
// 新しいペンを作成
if (!err)
{
if (m_pen.GetSafeHandle())
if (!m_pen.DeleteObject()) err = 1;
}
if (!err) if (!m_pen.CreatePen(nPenStyle, nWidth, m_color)) err = 1;
if (!err) if (!cdc.SelectObject(&m_pen)) err = 1;
// 線を描画
if (!err)
{
cdc.FillSolidRect(10, 150, 300, 60, RGB(128, 128, 128));
cdc.MoveTo(30, 170);
cdc.LineTo(290, 190);
}
CDialog::OnPaint();
}
|
まず、現在のスタイル、太さ、色で新しいペンを作成します。新しいペンの作成は、CPen::CreatePen()関数でできます。
| BOOL CPen::CreatePen(int nPenStyle, int nWidth, COLORREF crColor); |
| 説明: |
新しいペンを作成 |
| 引数: |
nPenStyle:ペンのスタイル
nWidth:ペンの太さ
crColor:ペンの色 |
| 戻り値: |
正常終了した場合は0以外、または論理ペンのハンドル。それ以外の場合は0 |
ペンを作成したら、CDC::SelectObject()関数で、新しいペンを選択しておきます。描画する領域をクリアするために、線分を描画する前にCDC::FillSolidRect()関数で塗りつぶしておきます。
線分の描画は、CDC::MoveTo()関数と、CDC::LineTo()関数でできます。MoveTo()は現在位置の移動、LineTo()は現在位置から指定位置まで、現在のペンで線分を描画します。
では、ビルドして実行してみましょう。次のようにダイアログ上に線分が描画されているのがわかります。スタイルや太さ、色を変更すると、線のスタイル、太さ、色が変わります。また、DOT、DASHDOTなどの点線はペンの太さが1の時にしか有効にならないようです。

|