描画コードの変更 (ATL チュートリアル、パート 4)
既定では、コントロールの描画コードによって、四角形とテキスト PolyCtl が表示されます。 この手順では、さらに興味深いものを表示するようにコードを変更します。 次のタスクが含まれます。
ヘッダー ファイルの変更
OnDraw
関数の変更多角形のポイントを計算するメソッドの追加
塗りつぶしの色の初期化
ヘッダー ファイルの変更
まず、多角形のポイントの計算に使用される数値演算関数 sin
と cos
のサポートを追加し、位置を格納するための配列を作成します。
ヘッダー ファイルを変更するには
PolyCtl.h の先頭に行
#include <math.h>
を追加します。 ファイルの先頭は次のようになります。#include <math.h> #include "resource.h" // main symbols
IProvideClassInfo
インターフェイスを実装し、次のコードを PolyCtl.h に追加することで、コントロールのメソッド情報を提供します。CPolyCtl
クラスで、次のように行を置き換えます。public CComControl<CPolyCtl>
with
public CComControl<CPolyCtl>, public IProvideClassInfo2Impl<&CLSID_PolyCtl, &DIID__IPolyCtlEvents, &LIBID_PolygonLib>
また、
BEGIN_COM_MAP(CPolyCtl)
には次の行を追加します。COM_INTERFACE_ENTRY(IProvideClassInfo) COM_INTERFACE_ENTRY(IProvideClassInfo2)
多角形のポイントが計算されると、それらは
POINT
型の配列に格納されます。そのため、PolyCtl.h の定義ステートメントshort m_nSides;
の後に配列を追加します。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 メソッドを追加するには
CalcPoints
の宣言を PolyCtl.h 内のCPolyCtl
クラスのIPolyCtl
パブリック セクションに追加します。void CalcPoints(const RECT& rc);
CPolyCtl
クラスのパブリック セクションの最後の部分は次のようになります。void FinalRelease() { } public: void CalcPoints(const RECT& rc);
CalcPoints
関数のこの実装を PolyCtl.cpp の最後に追加します。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 ファイルがまだ開いている場合は閉じたことを確認してから、[ビルド]メニューの [Build Polygon]\(多角形のビルド\) をクリックします。 PolyCtl.htm ページで再度コントロールを表示することもできますが、ここでは、ActiveX コントロール テスト コンテナーを使用します。
ActiveX コントロール テスト コンテナーを使用するには
ActiveX コントロール テスト コンテナーをビルドして開始します。 TSTCON サンプル: ActiveX コントロール テスト コンテナーは、GitHub にあります。
Note
ATL::CW2AEX
に関連するエラーが発生した場合、Script.Cpp の行TRACE( "XActiveScriptSite::GetItemInfo( %s )\n", pszNameT );
をTRACE( "XActiveScriptSite::GetItemInfo( %s )\n", pszNameT.m_psz );
に、行TRACE( "Source Text: %s\n", COLE2CT( bstrSourceLineText ) );
をTRACE( "Source Text: %s\n", bstrSourceLineText );
に置き換えます。
HMONITOR
に関連するエラーが発生した場合は、TCProps
プロジェクトの StdAfx.h を開いて、次のように置き換えます。#ifndef WINVER #define WINVER 0x0400 #endif
with
#ifndef WINVER #define WINVER 0x0500 #define _WIN32_WINNT 0x0500 #endif
テスト コンテナーの [編集] メニューで、[新しいコントロールを挿入] をクリックします。
PolyCtl class
という名前のコントロールを探し、[OK] をクリックします。 円の中に緑色の三角形が表示されます。
次の手順に従って、辺の数を変更します。 テスト コンテナー内でデュアル インターフェイスのプロパティを変更するには、[メソッドの呼び出し] を使用します。
テスト コンテナー内でコントロールのプロパティを変更するには
テスト コンテナーで、[コントロール] メニューの [メソッドの呼び出し] をクリックします。
[メソッドの呼び出し] ダイアログ ボックスが表示されます。
[メソッド名] ボックスの一覧から、[辺] プロパティの [PropPut] バージョンを選択します。
[パラメーター値] ボックスに
5
を入力し、[値の設定] をクリックし、[呼び出し] をクリックします。
コントロールは変更されないことに注意してください。 m_nSides
変数を設定することで、辺の数を内部で変更しましたが、これではコントロールは再描画されません。 別のアプリケーションに切り替えてからテスト コンテナーに戻ると、コントロールが再描画されて、正しい辺の数になっていることを確認できます。
この問題を修正するには、辺の数を設定した後で、IViewObjectExImpl
に定義された FireViewChange
関数の呼び出しを追加します。 コントロールがそれ自体のウィンドウで実行されている場合、FireViewChange
は InvalidateRect
メソッドを直接呼び出します。 コントロールがウィンドウなしで実行されている場合、InvalidateRect
メソッドはコンテナーのサイト インターフェイス上で呼び出されます。 これにより、コントロールが強制的に自動で再描画されます。
FireViewChange への呼び出しを追加するには
FireViewChange
への呼び出しをput_Sides
メソッドに追加して 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 コントロール テスト コンテナーでコントロールをリビルドして再試行します。 今回は、辺の数を変更して Invoke
をクリックすると、コントロールの変更がすぐに表示されます。
次の手順では、イベントを追加します。