服務器應用程序
容器應用程序
ActiveX控件可以看成是一個極小的服務器應用程序
OCX是ActiveX控件的一種后綴名
典型的ActiveX控件,具有方法、屬性、事件這三種特性
一個文件可以包含多個ActiveX控件.
我們常用的word就是一個容器應用程序,例如,若在word文檔中可以嵌入或鏈接一個Excel表格對象,則這時的Excel就是服務器應用程序。 在雙擊word文檔中嵌入或鏈接的這個Excel表格對象后,將啟動Excel程序來完成對這個表格的編輯工作。Excel就是擁有這個表格對象的服務器應用程序,而word程序則是可以容納這個表格對象的容器應用程序。另外,我們也可以在word文檔中嵌入或鏈接一個Excel文檔對象,因此對word來說,它不僅僅只是一個容器應用程序,同時它也是一個服務器應用程序。
MFC ActiveX ControlWizard生成3個類
CClockApp
CClockCtrl 消息映射、調度映射、事件映射
CClockPropPage
調度映射是指DISPATCH_MAP
這個是把你的成員方法映射到Invoke,使得腳本語言也能夠使用你的接口。
事件映射是指EVENT_MAP
這個是自動生成一個連接點事件的方法(該方法是給你調用,由COM客戶來實現),并發布該事件,是COM客戶可以使用連接點訂閱你的事件以得到相關通知
兩個映射都可以用類向導生成
另外,讀者可以看到在該工程中還有兩項內容:_DClock和_DClockEvents,前面都有一個像平放著小勺一樣的圖標(),該圖標表示對應的項是接口,接口是控件與外部程序進行通信的協議。
可以把接口看作是函數的集合,外部程序通過這個接口所暴露出來的方法去訪問控件的屬性和方法。
實際上,可以把接口看作是一個抽象基類,在此接口中定義的所有函數都是純虛函數,這些函數的實現是在CClockCtrl類中完成的。MFC通過底層的封裝,讓CClockCtrl類繼承自接口:_DClock,所以通過該接口調用的函數實際上是調用CClockCtrl類中真正實現的函數。
ActiveX控件中的接口與計算機機硬件的接口是類似的,例如,在計算機硬件中,主板與顯卡間的通信是通過主板上的插槽完成的,這個插槽就是主板與顯卡進行通信的接口,一旦我們制定了這個接口,就可以任意地選擇一塊主板與一塊顯卡進行通信。因為該接口是標準的,所以選擇任一廠商生產的主板,任一廠商生產的顯示都是可以的,只要它們的接口遵從共同的標準。主板通過該接口所暴露出來的方法去調用顯卡的顯示功能,而顯卡需要實現該接口所暴露出來的方法。
顯卡就相當于這里的ActiveX控件,而主板就相當于與控件通信的外部容器。如果兩個通信實體要通過接口進行通信,那么肯定是其中的一個實體實現該接口所暴露出來的方法,而另一個實體通過接口調用這些方法。這里,就是ActiveX控件實現接口所暴露出來的方法,而容器調用這些方法。
這里,我們利用Build(F7)命令生成Clock控件程序,然后在該工程所在目錄的Debug目錄下,可以看到生成了一個Clock.ocx文件,這就是程序生成的ActiveX控件文件。在使用時,只需要將這個文件傳遞給使用方,經過注冊后就可以使用該控件了。
ActiveX控件不能獨立運行,它必須嵌入到一個容器中運行。
所有的ActiveX控件必須在注冊后才能使用
生成ActiveX控件時,VC++編譯器會調用regsvr32程序去注冊clock控件。將該控件的所有信息,包括其所在路徑,都寫入注冊表中。
invalidate函數,使窗口無效,這樣就可以使窗口重繪。
屬性
屬性是由ActiveX控件和控件所在的客戶端展示提供的。共有四種基本屬性:
1、Ambient屬性是由容器向控件提供的。為了適應需要,控件必須使用這些屬性。常用的ambient屬性有容器的背景顏色、默認字體以及前景色等。
2、extended屬性是由容器實現的,但看起來是由控件生成的。例如,容器中各種各樣控件的制表順序便屬于extended屬性。
3、stock屬性是由ActiveX控件開發工具實現的控件屬性。Stock屬性的例子有控件的字體、標題文本和前景色及背景色等。
4、custom屬性是由用戶實現的控件屬性。
事件
事件是用于向控件的容器發送通知信息的。例如當點擊鼠標或發生其他事件時,控件用事件通知容器。共有兩種基本類型的事件:
1、 stock事件是由ActiveX控件開發工具實現的,可以像調用fireError等函數那樣調用stock事件。
2、 custom事件是由用戶實現的,盡管在實現過程中MFC和ATL類庫以及Visual C++做了大量的工作。
方法
由ActiveX控件實現的方法類似于自動化中所述的自動化實現的方法。實際上,方法主要是使用IDispatch接口通過自動化來實現的。
用MFC構件的ActiveX控件總是通過IDispatch來提供它的方法,而用ATL構建的控件為了提供組件的方法,既可以使用雙工接口,也可以使用定制接口。
事件前面多了一個source,這表明事件是一個源接口,這表明控件將用這個源接口向容器來發送通知事件,這個接口中實現的代碼需要用戶在容器上編寫,而不是在控件內部。
控件上子定義屬性設置的長期有效性:
對于自定義屬性值,如果在VB程序中設置好了值后,關閉工程,當再次打開工程的時候,發現原先設置好的屬性值沒有被保存下來。
在CCtrl類中的DoPropExchange方法中提供了屬性值保存的長期有效性,在其中可以調用以PX打頭大方法讓用戶自定義的屬性值長期有效。調用哪種PX打頭的方法取決于自定義屬性所對應的內部成員變量的類型,這里以PX_SHORT舉例,第一個參數是DoPropExchange方法中參數指針,第二個參數是屬性的外部名稱,第三個是屬性所對應的內部成員變量名稱。第四個是屬性的默認填充值。
還有一個問題,對于自定義的屬性,發現如果在屬性頁中對屬性值進行了修改,但在容器的對應屬性框中該值沒有相應的改變,但系統屬性是可以的。在屬性通知方法OnIntervalChanged內調用BoundPropertyChanged方法即可,參數是屬性ID,可以在類視圖中雙擊屬性名稱即可看到(id(XXX),XXX即為屬性ID)。
檢測容器的環境屬性:
檢測控件是在容器的運行模式
還是在設計模式下可調用方法:AmbientUserMode。關于ActiveX的詳細學習可以參考MSDN中COleControl頁,點擊頁面下方的ActiveX鏈接。
VC調用ActiveX控件:
方法一:直接在對話框上右鍵選擇Insert ActiveX Control
方法二:菜單project->add to project->component and controls,選擇已經注冊的ActiveX控件。向導會自動添加一個關于控件的類,在該類中有ActiveX控件定義好的屬性和方法,它Create方法可以動態創建一個ActiveX控件,其操作過程很動態創建button很類似。至于給控件添加事件,可以在控件上右鍵選擇Event即可。