變更繪圖程式碼 (ATL 教學課程,第 4 部分)
根據預設,控件的繪圖程式代碼會顯示正方形和文字 PolyCtl。 在此步驟中,您將變更程式代碼以顯示更有趣的內容。 涉及下列工作:
修改頭檔
修改函式
OnDraw
新增方法來計算多邊形點
初始化填滿色彩
修改頭檔
首先,新增對數學函 sin
式和 cos
的支援,這會用來計算多邊形點,以及建立數位來儲存位置。
若要修改頭檔
將這一行
#include <math.h>
新增至 PolyCtl.h 頂端。 檔案頂端看起來應該像這樣:#include <math.h> #include "resource.h" // main symbols
實作
IProvideClassInfo
介面,藉由將下列程式代碼新增至 PolyCtl.h,為控件提供方法資訊。 在類別中CPolyCtl
,取代行:public CComControl<CPolyCtl>
取代為
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 方法
現在您應該修改 OnDraw
PolyCtl.h 中的 方法。 您將新增的程式代碼會建立新的畫筆和筆刷,以繪製多邊形,然後呼叫 Ellipse
和 Polygon
Win32 API 函式來執行實際的繪圖。
修改 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
新增至IPolyCtl
PolyCtl.h 中 類別的CPolyCtl
公用區段: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檔案已關閉,然後按兩下 [建置] 功能表上的 [建置多邊形]。 您可以從 [PolyCtl.htm] 頁面再次檢視控件,但這次使用 ActiveX 控制件測試容器。
使用 ActiveX 控制件測試容器
建置並啟動 ActiveX 控制件測試容器。 您可以在 GitHub 上找到 TSTCON 範例:ActiveX 控制件測試容器。
注意
針對涉及
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
的錯誤,請在項目中開啟 StdAfx.hTCProps
並取代:#ifndef WINVER #define WINVER 0x0400 #endif
取代為
#ifndef WINVER #define WINVER 0x0500 #define _WIN32_WINNT 0x0500 #endif
在 [測試容器] 的 [ 編輯] 功能表上,按兩下 [ 插入新控件]。
找出將會呼叫
PolyCtl class
的控件,然後按兩下 [ 確定]。 您會在圓形中看到綠色三角形。
請遵循下一個程式,嘗試變更側邊數目。 若要從測試容器內修改雙重介面上的屬性,請使用 Invoke 方法。
若要從測試容器內修改控件的屬性
在 [測試容器] 中,按兩下 [控制單上的[叫用方法]。
[ 叫用方法] 對話框隨即顯示。
從 [方法名稱] 下拉式清單框中選取 [側邊] 屬性的 PropPut 版本。
在 [參數值] 方塊中,
5
按兩下 [設定值],然後按兩下 [叫用]。
請注意,控件不會變更。 雖然您藉由設定 m_nSides
變數來變更內部的側邊數目,但這並沒有造成控件重新重繪。 如果您切換至另一個應用程式,然後切換回 測試容器,您會發現控件已重繪並具有正確的側邊數目。
若要更正此問題,請在設定側邊數目之後,將呼叫新增至 FireViewChange
中 IViewObjectExImpl
定義的函式。 如果控件在自己的視窗中執行, 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
時,您應該會立即看到控件變更。
在下一個步驟中,您將新增事件。