共用方式為


變更繪圖程式碼 (ATL 教學課程,第 4 部分)

根據預設,控制項的繪圖程式碼會顯示正方形和文字 PolyCtl 。 在此步驟中,您將變更程式碼以顯示更有趣的內容。 涉及下列工作:

  • 修改標頭檔

  • 修改函式 OnDraw

  • 新增方法來計算多邊形點

  • 初始化填滿色彩

修改標頭檔

首先,新增對數學函 sin 式和 cos 的支援,這會用來計算多邊形點,以及建立陣列來儲存位置。

若要修改標頭檔

  1. 將這一行 #include <math.h> 新增至 PolyCtl.h 頂端。 檔案頂端看起來應該像這樣:

    #include <math.h>
    #include "resource.h"       // main symbols
    
  2. 實作 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)
    
  3. 計算多邊形點之後,它們會儲存在 類型的 POINT 陣列中,因此請在 PolyCtl.h 中的定義語句 short m_nSides; 後面新增陣列:

    POINT m_arrPoint[100];
    

修改 OnDraw 方法

現在您應該修改 OnDraw PolyCtl.h 中的 方法。 您將新增的程式碼會建立新的畫筆和筆刷,以繪製多邊形,然後呼叫 EllipsePolygon WIN32 API 函式來執行實際的繪圖。

修改 OnDraw 函式

  1. 以下列程式碼取代 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 方法

  1. 將 的宣告 CalcPoints 新增至 IPolyCtl PolyCtl.h 中 類別的 CPolyCtl 公用區段:

    void CalcPoints(const RECT& rc);
    

    類別之公用區段 CPolyCtl 的最後一個部分看起來會像這樣:

       void FinalRelease()
       {
       }
    public:
       void CalcPoints(const RECT& rc);
    
  2. 將此函 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

初始化填滿色彩

  1. 將這一行新增至 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 控制項測試容器

  1. 建置並啟動 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.h TCProps 並取代:

    #ifndef WINVER
    #define WINVER 0x0400
    #endif
    

    取代為

    #ifndef WINVER
    #define WINVER 0x0500
    #define _WIN32_WINNT 0x0500
    #endif
    
  2. [測試容器 ] 的 [ 編輯] 功能表上,按一下 [ 插入新控制項 ]。

  3. 找出將會呼叫 PolyCtl class 的控制項,然後按一下 [ 確定 ]。 您會在圓形中看到綠色三角形。

請遵循下一個程式,嘗試變更側邊數目。 若要從測試容器內 修改雙重介面上的屬性,請使用 Invoke 方法

若要從測試容器內修改控制項的 屬性

  1. [測試容器 ] 中,按一下 [控制項 ] 功能表上的 [ 叫用 方法]。

    [ 叫用方法] 對話方塊隨即顯示。

  2. [ 方法名稱 ] 下拉式清單方塊中選取 [側邊 ] 屬性的 PropPut 版本。

  3. 在 [參數值] 方塊中, 5 按一下 [ 設定值 ],然後按一下 [ 叫用 ]。

請注意,控制項不會變更。 雖然您藉由設定 m_nSides 變數來變更內部的側邊數目,但這並沒有造成控制項重新重繪。 如果您切換至另一個應用程式,然後切換回 測試容器 ,您會發現控制項已重繪並具有正確的側邊數目。

若要更正此問題,請在設定側邊數目之後,將 呼叫新增至 FireViewChangeIViewObjectExImpl 定義的函式。 如果控制項在自己的視窗中執行, FireViewChange 則會直接呼叫 InvalidateRect 方法。 如果控制項執行無視窗,則會 InvalidateRect 在容器的月臺介面上呼叫 方法。 這會強制控制項重新重繪本身。

若要新增對 FireViewChange 的呼叫

  1. 將 呼叫新增至 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 時,您應該會立即看到控制項變更。

在下一個步驟中,您將新增事件。

回到步驟 3 | 開啟至步驟 5

另請參閱

教學課程
使用測試容器測試屬性和事件