共用方式為


MFC ActiveX 控件:子類別化 Windows 控制件

本文說明將通用 Windows 控制件子類別化以建立 ActiveX 控件的程式。 將現有的 Windows 控件子類別化是開發 ActiveX 控件的快速方法。 新的控件將具備子類別化 Windows 控制元件的功能,例如繪圖和回應滑鼠點擊。 MFC ActiveX 控件範例 BUTTON 是子類別化 Windows 控件的範例。

這很重要

ActiveX 是不應該用於新開發的舊版技術。 如需取代 ActiveX 的新式技術詳細資訊,請參閱 ActiveX 控件

若要將 Windows 控件子類別化,請完成下列工作:

覆寫 IsSubclassedControl 函數和 PreCreateWindow 設定

若要覆寫 PreCreateWindowIsSubclassedControl,請將下列程式代碼行新增至 protected 控件類別宣告的 區段:

virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
BOOL IsSubclassedControl();

在控件實作檔案中 (.CPP),新增下列幾行程式代碼來實作兩個覆寫的函式:

// CMyAxSubCtrl::PreCreateWindow - Modify parameters for CreateWindowEx

BOOL CMyAxSubCtrl::PreCreateWindow(CREATESTRUCT& cs)
{
   cs.lpszClass = _T("BUTTON");
   return COleControl::PreCreateWindow(cs);
}

// CMyAxSubCtrl::IsSubclassedControl - This is a subclassed control

BOOL CMyAxSubCtrl::IsSubclassedControl()
{
   return TRUE;
}

請注意,在此範例中,Windows 按鈕控件是在 中 PreCreateWindow指定。 不過,任何標準 Windows 控制件都可以子類別化。 如需標準 Windows 控件的詳細資訊,請參閱 控件

在子類別化 Windows 控制件時,您可能想要指定特定視窗樣式 (WS_) 或擴充視窗樣式 (WS_EX_) 旗標,以用於建立控件的視窗。 您可以在 PreCreateWindow 成員函式中設定這些參數的值,透過修改 cs.stylecs.dwExStyle 結構欄位。 應該使用 OR 作業修改這些欄位,以保留 類別 COleControl所設定的預設旗標。 例如,如果控制項是 BUTTON 控件的子類別,而且您希望控制項顯示為複選框,請在 return 語句之前,將以下程式碼行插入到 CSampleCtrl::PreCreateWindow 的實作中:

cs.style |= BS_CHECKBOX;

此作業會新增BS_CHECKBOX樣式旗標,同時讓類別 COleControl 的預設樣式旗標 (WS_CHILD) 保持不變。

修改 OnDraw 成員函式

如果您想要讓子類別化控件保持與對應 Windows 控件相同的外觀, OnDraw 控件的成員函式應該只包含對成員函式的呼叫 DoSuperclassPaint ,如下列範例所示:

void CMyAxSubCtrl::OnDraw(CDC* pdc, const CRect& rcBounds, const CRect& /*rcInvalid*/)
{
   if (!pdc)
      return;

   DoSuperclassPaint(pdc, rcBounds);
}

DoSuperclassPaintCOleControl實作的成員函式會使用 Windows 控件的視窗程式,在周框內於指定的裝置內容中繪製控件。 如此一來,即使控件不在作用中也可見。

備註

成員 DoSuperclassPaint 函式只適用於允許將裝置內容當做WM_PAINT訊息 的 wParam 傳遞的控件類型。 這包括一些標準 Windows 控制件,例如 SCROLLBAR 和 BUTTON,以及所有通用控制項。 對於不支援此行為的控制件,您必須提供自己的程式碼,才能正確顯示非使用中的控制件。

處理反射的視窗訊息

Windows 控制件通常會將特定視窗訊息傳送至其父視窗。 其中一些訊息,例如WM_COMMAND,會向使用者提供動作的通知。 其他,例如WM_CTLCOLOR,則用來從父視窗取得資訊。 ActiveX 控制件通常以其他方式與父窗口通訊。 通知會藉由引發事件(傳送事件通知)來傳達,而控制容器的相關信息則是藉由存取容器的環境屬性來取得。 由於這些通訊技術存在,因此 ActiveX 控制件容器不會處理控制項所傳送的任何視窗訊息。

若要防止容器接收子類化的 Windows 控制項所傳送的視窗訊息, COleControl 建立額外的視窗作為控制項的父系。 這個稱為「反映器」的額外視窗只會針對將 Windows 控件子類別化的 ActiveX 控制件建立,而且其大小和位置與控件視窗相同。 反映器視窗會攔截特定視窗訊息,並將其傳回控件。 控件在其視窗程式中,接著可以採取適用於 ActiveX 控件的動作來處理這些反映的訊息(例如引發事件)。 如需攔截的視窗訊息清單及其對應的反映訊息,請參閱 反映的視窗訊息標識碼

ActiveX 控制項容器可能被設計成可本身進行訊息反射,從而不需要 COleControl 建立反射器視窗,並且透過減少對子類化 Windows 控制項的運行時額外負擔來優化性能。 COleControl 偵測容器是否支援這項功能,方法是檢查值為 TRUE 的 MessageReflect 環境屬性。

若要處理反映的視窗訊息,請將條目新增至控件訊息對應,並實作處理函式。 由於反映的訊息不是 Windows 所定義之標準訊息集的一部分,因此類別檢視不支援新增這類訊息處理程式。 不過,手動新增處理程式並不難。

若要手動新增反映視窗訊息的訊息處理程式,請執行下列動作:

  • 在控制類別的 .H 檔案中,宣告一個處理函式。 函式應該有 LRESULT 的傳回型別和兩個參數,分別具有 WPARAMLPARAM 類型。 例如:

    class CMyAxSubCtrl : public COleControl
    {
    
    protected:
       LRESULT OnOcmCommand(WPARAM wParam, LPARAM lParam);
    };
    
  • 在控制類別的 CPP 檔案中,將 ON_MESSAGE 項目新增至訊息映射。 這個項目的參數應該是訊息標識碼和處理程式函式的名稱。 例如:

    BEGIN_MESSAGE_MAP(CMyAxSubCtrl, COleControl)
       ON_MESSAGE(OCM_COMMAND, &CMyAxSubCtrl::OnOcmCommand)
    END_MESSAGE_MAP()
    
  • 此外,在 CPP 檔案中,實作 OnOcmCommand 成員函式來處理反映的訊息。 wParamlParam 參數與原始視窗訊息的參數相同。

如需如何處理反映訊息的範例,請參閱 MFC ActiveX 控件範例 BUTTON。 它示範了一個 OnOcmCommand 處理程式,偵測 BN_CLICKED 通知代碼,並藉由觸發(發送)Click 事件來回應。

另請參閱

MFC ActiveX 控制件