首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

MFC 開發 ActiveX 控制項實戰:從專案建立到屬性方法事件完整實作

     編輯:關於C語言

專案建立:MFC ActiveX 控制項精靈逐步指南

Visual C++ 6.0 / Visual Studio 提供的 MFC ActiveX 控制項精靈,能自動生成包含 COleControlModule、COleControl 派生類、資源檔、註冊腳本的完整專案骨架。以下以建立包含三種控制項的範例專案為例:

  1. 選擇 MFC ActiveX Control 專案類型,命名專案(如 SamCtrl)。
  2. 在精靈第二步設定控制項數量與名稱:
  • CSam_windowCtrl:一般視窗控制項(繼承 CWnd,有 HWND)。
  • CSam_nowindowCtrl:無視窗控制項(輕量,無 HWND,繪圖由容器代管)。
  • CSam_editwindowCtrl:編輯視窗控制項(繼承 CEdit 或自訂編輯行為)。

進階選項可設定:是否支援授權、是否為不可見控制項、預設大小、是否支援非同步下載等。

核心類別結構解析

精靈為每個控制項生成三個核心類別:

  • CSam_windowCtrl (繼承 COleControl):控制項主體,處理繪圖、訊息、屬性/方法/事件分派。
  • CSam_windowCtrlPropPage (繼承 COlePropertyPage):屬性頁,提供設計時的視覺化屬性編輯介面。
  • CSam_windowCtrlFactory (繼承 COleObjectFactory):類別工廠,負責建立控制項實例、註冊/反註冊。

新增自訂方法:SetMaterial

透過 ClassWizard → Automation 頁籤 → Add Method:

  • 方法名:SetMaterial
  • 參數:LPCTSTR pszName, LPCTSTR pszBirth, LPCTSTR pszClass (皆為 [in])
  • 傳回型別:void

Wizard 會自動:

  1. 在 .odl (Object Description Language) 檔中加入 dispinterface 定義。
  2. 在 CSam_windowCtrl 類別宣告 void SetMaterial(LPCTSTR, LPCTSTR, LPCTSTR);。
  3. 在 .cpp 生成 DISP_FUNCTION 對應巨集與空白實作函式。

實作範例

// Sam_windowCtrl.cpp
void CSam_windowCtrl::SetMaterial(LPCTSTR pszName, LPCTSTR pszBirth, LPCTSTR pszClass)
{
    // 1. 參數檢查
    if (!pszName || !pszBirth || !pszClass) return;

    // 2. 更新成員變數 (需在 .h 中宣告 CString m_szName, m_szBirth, m_szClass;)
    m_szName = pszName;
    m_szBirth = pszBirth;
    m_szClass = pszClass;

    // 3. 觸發重繪
    InvalidateControl(); // 無視窗控制項用這個;有視窗控制項可用 Invalidate()
}

新增自訂屬性:TextColor (OLE_COLOR)

ClassWizard → Automation → Add Property:

  • 屬性名:TextColor
  • 型別:OLE_COLOR (32 位元色彩值,含調色盤索引)
  • 實作方式:Get/Set Methods (Wizard 產生 GetTextColor() / SetTextColor())

實作與色彩轉換

// .h
OLE_COLOR m_clrTextColor; // 內部儲存 OLE_COLOR
COLORREF m_clrTextColorRGB; // 轉換後的 RGB 值,供繪圖使用

// .cpp
OLE_COLOR CSam_windowCtrl::GetTextColor()
{
    return m_clrTextColor;
}

void CSam_windowCtrl::SetTextColor(OLE_COLOR clr)
{
    // 1. 更新內部值
    m_clrTextColor = clr;

    // 2. 將 OLE_COLOR 轉為 COLORREF (需容器提供調色盤)
    // 通常在 OnDraw 或需要繪圖時轉換,這裡僅標記需重繪
    // 實際轉換:TranslateColor(clr, hPal, &m_clrTextColorRGB);
    InvalidateControl();

    // 3. 通知容器屬性已變更 (觸發 PropertyChanged 事件)
    SetModifiedFlag();
    BoundPropertyChanged(dispidTextColor);
}

繪圖實作:OnDraw 核心邏輯

所有視覺輸出集中在 OnDraw(CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid):

void CSam_windowCtrl::OnDraw(CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
    // 1. 準備色彩 (若為 OLE_COLOR 需轉換)
    COLORREF crText = m_clrTextColorRGB; // 假設已在 SetTextColor 或 OnDraw 前轉換
    COLORREF crOld = pdc->SetTextColor(crText);
    int nOldMode = pdc->SetBkMode(TRANSPARENT);

    // 2. 繪製學生資料
    CString strInfo;
    strInfo.Format(_T("姓名: %s\n出生: %s\n班級: %s"), m_szName, m_szBirth, m_szClass);
    pdc->DrawText(strInfo, rcBounds, DT_LEFT | DT_TOP | DT_WORDBREAK);

    // 3. 還原 DC 狀態
    pdc->SetTextColor(crOld);
    pdc->SetBkMode(nOldMode);
}

無視窗控制項 (CSam_nowindowCtrl) 特殊處理

  • 不擁有 HWND,不接收 Windows 訊息 (WM_PAINT, WM_MOUSEMOVE 等)。
  • 容器負責在 OnDraw 中呼叫控制項繪圖,並轉發滑鼠/鍵盤事件透過 IOleInPlaceObjectWindowless 介面。
  • 優點:資源佔用極低,適合大量實例 (如表格儲存格內的小圖示)。
  • 缺點:無法直接使用 SetCapture、SetFocus、工具提示等視窗功能。

建置、測試與部署

  1. 建置 Release 版本,產生 SamCtrl.ocx。
  2. 使用 ActiveX Control Test Container (VC 工具) 測試屬性/方法/事件。
  3. 部署:將 .ocx 複製至目標機,以管理員權限執行 regsvr32 SamCtrl.ocx 註冊。
  4. 網頁嵌入:使用 <OBJECT classid="clsid:YOUR_CLSID" codebase="SamCtrl.cab#version=1,0,0,0"></OBJECT> (需打包 .cab 並簽章)。

常見問題排查

現象可能原因解決方向
屬性頁不顯示未在 DoDataExchange 綁定控制項檢查 DDX_Control/DDX_Text 等巨集
事件容器收不到未實作 FireEvent 或 EventMap 缺少 EVENT_CUSTOM用 ClassWizard 加入事件,自動生成 FireClick 等函式
色彩顯示異常OLE_COLOR 未正確轉換使用 TranslateColor 配合容器調色盤
授權失效未正確實作 VerifyUserLicense/GetLicenseKey檢查 .lic 檔案內容與 _szLicString 是否一致

總結

MFC 封裝了 ActiveX 控制項繁複的 COM 介面實作,透過 Wizard 與 ClassWizard,開發者可專注於商業邏輯:定義屬性/方法/事件 → 實作資料儲存與繪圖 → 處理視窗/無視窗差異。掌握 COleControl 虛函數 (OnDraw, OnEventAdvise, DoPropExchange 等) 的呼叫時機,是進階開發與除錯的關鍵。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved