VS2010下開發ActiveX 控制元件
這幾天看了關於COM技術的資料並看了孫鑫老師關於ActiveX控制元件的教程,自己就動手實踐了一下。教程中用的是VC6.0實現的,我用的是vs2010,在實踐的過程中也遇到了一些問題,最終都解決了。在這裡將學習過程分享一下。
ActiveX控制元件的底層實現是基於COM技術的。任何一個控制元件都有自身的屬性、方法、事件。那麼我們自己在開發ActiceX空間的時候,也可以為其新增屬性、方法、事件,這些屬性、方法、事件不僅包括標準的屬性、方法、事件也包括自定義的屬性、方法、事件。我們先在VS中建立MFC ActiveX Control的應用程式。然後我們就可以開發自己的ActiveX控制元件了。
一、註冊控制元件
開發的控制元件或者系統安裝的控制元件可以在任何程式開發環境是使用,使用之前必須先進行註冊,向登錄檔寫入資訊,否則開發環境是無法知道系統中的控制元件的。我們自己開發的控制元件在編譯過程中會自動呼叫regsvr32應用程式為我們的控制元件進行註冊。在我們的開發環境中用於註冊的操作時通過DllRegisterServer()函式實現的,響應的反註冊函式為DllUnregisterServer(),當然我們也可以手動的註冊、反註冊我們的ActiveX控制元件,方法是在執行程序中輸入regsvr32 E:\studio\Clock\Debug\Clock.ocx
反註冊regsvr32 /u E:\studio\Clock\Debug\Clock.ocx
一個ActiveX控制元件不能單獨執行,必須在某個容器中執行,我們在開發過程中可用vs自帶的測試容器進行測試。但是在安裝vs2010時這個測試容器應用程式並沒有安裝,我們可以在vs的安裝目錄下的Sample資料夾下找到一個VC2010Samples.zip的壓縮檔案。在這個路徑下有一個測試程式VC2010Samples\C++\MFC\ole\TstCon,經過編譯後就會有一個測試用的可執行檔案,我們可以在這個容器中測試我們開發的ActiveX控制元件。
二、為控制元件新增屬性
(1)為控制元件新增標準屬性
這個示例程式是編寫一個顯示當前系統時間的控制元件,我們可以為該控制元件新增標準的改變背景和前景顏色的屬性。在
CBrushbrush(TranslateColor(GetBackColor()));
pdc->FillRect(rcBounds,&brush);
pdc->SetBkMode(TRANSPARENT);
pdc->SetTextColor(TranslateColor(GetForeColor()));
(2)為控制元件新增自定義屬性
我們不僅能為控制元件新增標準屬性,也可以為其新增自定義屬性,該示例控制元件的功能是顯示系統當前時間,每隔一秒重新整理一次,我們可以讓使用者自定義重新整理時間。該例項中我們為其新增外部屬性名InterVal的屬性,新增完成後,系統自動為我們新增一個OnIntervalChanged()的成員函式,當該屬性發生變化時,就會呼叫該函式來處理使用者的屬性設定。示例程式碼如下:
if (m_Interval<0||m_Interval>6000)
{
m_Interval=1000;
}
else
{
m_Interval=m_Interval/1000*1000;
KillTimer(1);
SetTimer(1,m_Interval,NULL);
BoundPropertyChanged(0x1);
}
(3)為控制元件新增屬性表單
每一個控制元件自身都有一個屬性表單供使用者改變該控制元件的屬性,我們建立的工程自動為其新增一個屬性頁,我們可以為其新增多個屬性頁。
首先為其新增改變背景和前景顏色的屬性頁。我們可以在Ctrl的原始檔新增如下加粗顯示的程式碼:
BEGIN_PROPPAGEIDS(CClockCtrl, 2)
PROPPAGEID(CClockPropPage::guid)
PROPPAGEID(CLSID_CColorPropPage)
END_PROPPAGEIDS(CClockCtrl)
在這個巨集之間,我們可以新增標準屬性的屬性頁程式碼。這樣就可以生成一個改變顏色的屬性頁了。
我們可以在系統自動生成的空的屬性頁上新增編輯框,讓使用者輸入重新整理時間。我們可以為該編輯框關聯成員變數和屬性名,讓該編輯框控制元件和開發的控制元件的時間相關聯。在VC6.0中,可以很方便的使用Class Wizard同時關聯成員變數和屬性。但是在vs中只能通過嚮導關聯成員變數,必須手動關聯屬性。我們可以在PropPage類的DoDataExchange()中新增控制元件與屬性的關聯。示例如下:
DDP_Text(pDX, IDC_EDIT1, m_updateInterval,_T("Interval"));
三、為控制元件新增方法
為控制元件新增方法跟新增屬性的過程一樣,新增後在介面中有方法的定義,在Ctrl類中有方法的實現。
四、為控制元件新增事件
控制元件通過介面傳送事件通知,容器實現介面中的方法。
(1)為控制元件新增標準事件
在VC6.0中可以通過Class Wizard為控制元件新增事件,或者在事件介面上右鍵單擊新增事件,但是在vs中以上方法好像不能新增,不過可以在Ctrl類上單擊右鍵可以為控制元件新增事件。我們可以很方便的為控制元件新增標準事件。
(2)為控制元件新增自定義事件
可以通過同樣的方法為事件新增自定義事件。在Ctrl類的原始檔中可以完成自定義事件的實現,當某一事件發生時,可以呼叫該函式通過FireEvent()函式向容器傳送事件通知。在OnDraw()函式中新增響應時間。
五、屬性的永續性
我們開發的控制元件在具體的使用過程中,可以改變其屬性值,但是當我們關閉程式,再一次開啟應用程式時,會發現我們新增的標準屬性仍然保持我們以前設定的屬性值,而新增的自定義屬性不能保持我們上次設定的屬性值,這在實際應用中是很不方便的。所以我們要設法保持屬性的永續性。我們可以在Ctrl類的DoPropExchange()函式中新增如下程式碼實現:
PX_Short(pPX,_T("Interval"),m_Interval,1000);
六、通知容器屬性發生變化
當我們在實際應用過程中,我們在控制元件自身的屬性表單中改變屬性,但是我們會發現屬性表單中屬性值的變化不會反映到開發環境的屬性上,這樣會給使用者造成誤解。我們可以讓其同步。我們可以在OnIntervalChanged()函式中通過BoundPropertyChanged(0x1)函式使指定的屬性通知容器也發生改變。
七、改變控制元件的環境屬性
我們可以讓控制元件在設計狀態下不執行,而在執行時才執行。但是控制元件自身不會感知自己處於何種狀態,而容器知道自身處於何種狀態。我們可以通過控制元件的環境屬性通知控制元件此時處於何種狀態,然後做出相應的操作。AmbientUserMode( )函式可以感知容器處於何種狀態。具體實現程式碼如下:
if(AmbientUserMode())
InvalidateControl();
執行結果: