手順 4: 描画コードの変更
更新 : 2007 年 11 月
既定では、コントロールの描画コードは、四角形と "ATL 8.0 : PolyCtl" というテキストを表示します。この手順では、コードを変更して他の形を表示します。以下のタスクがあります。
ヘッダー ファイルの変更
OnDraw 関数の変更
多角形の頂点を計算するメソッドの追加
塗りつぶす色の初期化
ヘッダー ファイルの変更
最初に、多角形の頂点を計算する sin や cos などの数値演算関数のサポートを追加し、頂点の位置を格納する配列を作成します。
ヘッダー ファイルを変更するには
PolyCtl.h の先頭に #include <math.h> という行を追加します。
#include <math.h> #include "resource.h" // main symbols
計算された多角形の頂点は POINT 型の配列に格納されるため、PolyCtl.h のクラス定義の最後に POINT 型の配列を追加します。
POINT m_arrPoint[100];
OnDraw メソッドの変更
ここで PolyCtl.h の OnDraw メソッドを変更してください。追加するコードは、多角形を描画する新しいペンとブラシを作成し、Win32 API の Ellipse 関数と Polygon 関数を呼び出して実際の描画を実行します。
OnDraw 関数を変更するには
PolyCtl.h の OnDraw メソッドを次のコードで置き換えます。
HRESULT CPolyCtl::OnDraw(ATL_DRAWINFO& di) { RECT& rc = *(RECT*)di.prcBounds; HDC hdc = di.hdcDraw; COLORREF colFore; HBRUSH hOldBrush, hBrush; HPEN hOldPen, hPen; // Translate m_colFore into a COLORREF type OleTranslateColor(m_clrFillColor, NULL, &colFore); // Create and select the colors to draw the circle hPen = (HPEN)GetStockObject(BLACK_PEN); hOldPen = (HPEN)SelectObject(hdc, hPen); hBrush = (HBRUSH)GetStockObject(WHITE_BRUSH); hOldBrush = (HBRUSH)SelectObject(hdc, hBrush); Ellipse(hdc, rc.left, rc.top, rc.right, rc.bottom); // Create and select the brush that will be used to fill the polygon hBrush = CreateSolidBrush(colFore); SelectObject(hdc, hBrush); CalcPoints(rc); Polygon(hdc, &m_arrPoint[0], m_nSides); // Select back the old pen and brush and delete the brush we created SelectObject(hdc, hOldPen); SelectObject(hdc, hOldBrush); DeleteObject(hBrush); return S_OK; }
多角形の頂点を計算するメソッドの追加
多角形の辺を構成する頂点の座標を計算する、CalcPoints というメソッドを追加します。この計算は、関数に渡す RECT 変数に基づいて行われます。
CalcPoints メソッドを追加するには
PolyCtl.h の CPolyCtl クラスの IPolyCtl パブリック セクションに、CalcPoints という宣言を追加します。
void CalcPoints(const RECT& rc);
CPolyCtl クラスのパブリック セクションの最後の部分は、次のようになります。
void FinalRelease() { } public: STDMETHOD(get_Sides)(short* pVal); STDMETHOD(put_Sides)(short newVal); void CalcPoints(const RECT& rc);
PolyCtl.cpp の最後に CalcPoints 関数の次の実装を追加します。
void CPolyCtl::CalcPoints(const RECT& rc) { const double pi = 3.14159265358979; POINT ptCenter; double dblRadiusx = (rc.right - rc.left) / 2; double dblRadiusy = (rc.bottom - rc.top) / 2; double dblAngle = 3 * pi / 2; // Start at the top double dblDiff = 2 * pi / m_nSides; // Angle each side will make ptCenter.x = (rc.left + rc.right) / 2; ptCenter.y = (rc.top + rc.bottom) / 2; // Calculate the points for each side for (int i = 0; i < m_nSides; i++) { m_arrPoint[i].x = (long)(dblRadiusx * cos(dblAngle) + ptCenter.x + 0.5); m_arrPoint[i].y = (long)(dblRadiusy * sin(dblAngle) + ptCenter.y + 0.5); dblAngle += dblDiff; } }
塗りつぶす色の初期化
既定の色で m_clrFillColor を初期化します。
塗りつぶす色を初期化するには
既定の色を緑にするために、PolyCtl.h の CPolyCtl コンストラクタに次の行を追加します。
m_clrFillColor = RGB(0, 0xFF, 0);
コンストラクタは、次のようになります。
CPolyCtl()
{
m_nSides = 3;
m_clrFillColor = RGB(0, 0xFF, 0);
}
コントロールのビルドと動作確認
コントロールを再度ビルドします。PolyCtl.htm ファイルがまだ開いている場合は閉じ、[ビルド] メニューの [Polygon のビルド] をクリックします。コントロールを再度 PolyCtl.htm ページで表示することもできますが、ここでは ActiveX コントロール テスト コンテナを使用します。
ActiveX コントロール テスト コンテナを使用するには
ActiveX コントロール テスト コンテナをビルドして起動します。詳細については、「TSTCON サンプル : ActiveX コントロール テスト コンテナ」を参照してください。
テスト コンテナの [編集] メニューの [新しいコントロールを挿入] をクリックします。
作成した PolyCtl Class コントロールを指定し、[OK] をクリックします。円の中に緑の三角形が表示されます。
次の手順で辺の数を変更してみます。テスト コンテナのデュアル インターフェイスでプロパティを変更するには、[メソッドの呼び出し] を使用します。
テスト コンテナでコントロールのプロパティを変更するには
テスト コンテナの [コントロール] メニューの [メソッドの呼び出し] をクリックします。
[メソッドの呼び出し] ダイアログ ボックスが表示されます。
[メソッド名] ボックスで Sides プロパティの PropPut の方を選択します。
[パラメータ値] ボックスに「5」と入力し、[設定] をクリックしてから [呼び出し] をクリックします。
コントロールは変更されません。m_nSides 変数を設定して内部的に辺の数を変更したにもかかわらず、コントロールの再描画が行われていません。ここで、ほかのアプリケーションに切り替えてからテスト コンテナに戻ると、コントロールの再描画が行われて、正しい辺の数になります。
この問題を解決するには、辺の数を設定した後で、IViewObjectExImpl で定義されている FireViewChange 関数呼び出しを追加します。ウィンドウ内でコントロールを実行している場合は、FireViewChange が InvalidateRect メソッドを直接呼び出します。コントロールをウィンドウなしで実行している場合は、コンテナのサイト インターフェイスで InvalidateRect メソッドが呼び出されます。これにより、コントロールが自動的に再描画されます。
FireViewChange の呼び出しを追加するには
put_Sides メソッドに対する FireViewChange 呼び出しを追加して、PolyCtl.cpp を更新します。追加すると、put_Sides メソッドは次のようになります。
STDMETHODIMP CPolyCtl::put_Sides(short newVal) { if (2 < newVal && newVal < 101) { m_nSides = newVal; FireViewChange(); return S_OK; } else { return Error(_T("Shape must have between 3 and 100 sides")); } }
FireViewChange を追加した後で再度ビルドを行い、ActiveX コントロール テスト コンテナでコントロールの動作を確認します。今回は、辺の数を変更してから [呼び出し] をクリックすると、コントロールがすぐに変化します。
次の手順でイベントを追加します。