??? ActiveX控件是一個自包含代碼的組件,它有自己的永久狀態,并且ActiveX控件與包容器之間通過COM接口進行通信,所以通常ActiveX控件具有普遍的適應性,換句話說,如果ActiveX控件在一個包容器程序中可以運行,那么通常它也可以運行在另一個包容器程序中。由于ActiveX控件是一種可獨立發布的組件程序,又是一個永久對象,這些特性使得它非常適合于Internet環境。
從包容器IE而言。IE需要考慮一些與Internet環境有關的問題,如許可證檢查,自動下載、遠程數據獲取等。
另一方面從ActiveX控件本身來看,用于桌面環境的ActiveX控件,為了獲得更強的交互性能,通常它要實現各種ActiveX控件所要求的接口,所以組件規模通常很大。為了使程序代碼量盡可能地小,Microsoft Visual C++提供了ATL模板庫作為這類ActiveX控件的基本開發工具。
IE要求ActiveX控件必須支持自注冊,以便在用戶瀏覽包含ActiveX控件的WEB頁面時可以動態地注冊控件。所以作為ActiveX控件的DLL程序必須引出DllRegisterServer和DllUnregisterServer函數。
接口 | 功能與說明 |
IOleObject | 如果控件要與包容器程序的站點對象進行通信,則須實現此接口 |
IOleInPlaceObject IOleInPlaceActiveObject | 如果控件支持實地激活特性,則須實現此接口 |
IOleControl | 如果控件支持快捷鍵,或者訪問包容器的環境屬性,或者控件要求包容器處理事件,則須實現此接口。 |
IDataObject | 如果控件提供數據對象的特性,則實現此接口 |
IViewObject2 | 如果控件在非實地激活狀態下也需要顯示信息,則實現此接口 |
IDispatch | 如果控件有自定義的屬性和方法,則實現此接口 |
IConnectionPointContainer | 如果控件對象支持一個或多個出接口,則實現此接口。 |
IProvideClassInfo[2] | 如果控件對象要直接通過GetClassInfo成員函數提供對象類型信息,則實現此接口 |
ISpecifyPropertyPages | 如果控件對象支持屬性頁,則實現此接口 |
IPersistStream[Init] IPersisStorage 或其它永久接口 | 如果控件對象支持永久特性的,則至少實現一個永久接口 |
從理論上講,IE只要求被嵌入的對象(ActiveX控件以對象的形式被嵌入在頁面中)實現IUnKnown接口,但實際上為了實現一定的功能,并更好地與IE程序進行交互,ActiveX控件還必須實現其它一些接口。對應的接口與功能對應關系如下:
一般的包容器程序通常只負責ActiveX控件的創建、運行和釋放,但IE要做的事情更多一些。首先,當客戶機上不存在ActiveX控件組件程序時,它必須根據HTML頁面中指示的地點把組件程序下載過來,并注冊在客戶機上,然后再創建對象,此過程在后臺自動完成,不需要執行其它命令。其次,當IE把組件程序下載到本地之后,它在創建控件對象時可以進行許可證檢查,以保證系統安全性,用戶也可拒絕對象或執行初始化。
ActiveX控件包裝
通過CLSID指定ActiveX控件的類型,如果要在IE中正確顯示包含ActiveX控件的頁面,則必須事先在機器上注冊相應的ActiveX控件,否則相應的ActiveX就不能顯示。在Internet上使用時,頁面設計者不能期望瀏覽器用戶找到你指定的ActiveX控件并注冊到客戶機上,為了解次這個問題,我們可以用“codebase”屬性指定控件的代碼位置:
<OBJECT CLASSID=”CLSID:2885EE05-A26B-11d1-B49B-00c04F98EFE0”
??? ?ALIGN=”CENTER” WIDTH=200 HEIGHT=200 ID=”PolyCtl”> </OBJECT>
以上指定了Polygong控件程序“
http://webserver/Pollgon.dll”,當瀏覽器碰到這樣的描述時,它會把codebase指定的程序下載到本地(在系統目錄的“Downloaded Program Files”子目錄下),然后調用組件程序的自注冊入口函數注冊到當前系統中,以后的創建都在本地進行,不再涉及codebase屬性。
?
因為ActiveX控件的程序代碼需要在Internet上傳輸,所以使用壓縮技術傳輸程序代碼非常有意義。另一方面,如果ActiveX控件還調用到其它的DLL程序模塊,那么IE也必須把這些程序下載到本地來,為此,Microsoft采用了慣用的CAB壓縮方法,它把ActiveX控件程序以及相關的其它文件放到同一個CAB文件中,然后在codebase屬性中指定CAB文件的URL路徑。
?
IE對CAB文件的處理過程如下:
1.?IE在解析“OBJECT”標記時,它繼續查找codebase屬性。
2.?如果找到了codebase屬性,并且codebase指定了ActiveX控件的CAB文件,那么IE定位到CAB文件。
3.?IE把CAB文件中的有關文件解壓出來,并放到客戶機的臨時目錄(系統目錄的“Downloaded Program Files”子目錄下)中。
4.?IE注冊有關的文件。
5.?IE調用COM API函數創建ActiveX控件對象。
CAB文件包含了ActiveX控件注冊和運行時所需要的必要信息。通常一個CAB文件包含一個INF文件,INF文件是一個文本文件,它描述了CAB文件的所有細節信息。如以下的INF文件例子。
[version]
Signature=”$CHICAGE$”
AdvancedINF=2.0
[Add.Code]
MyCtrl.ocx = MyCtrl.ocx
Msvcrt.dll = msvcrt.dll
Mfc42.dll = mfc42.dll
Olepro32.dll = olepro32.dll
[MyCtrl.ocx]
File-win32-x86=thiscab
Clsid = {2885EE05-A26B-11d1-B49B-00c04F98EFE0}
FileVersion = 1,0,0,0
RegisterServer = yes
?
[msvcrt.dll]
FileVersion = 4,20,0,6164
Hook = mfc42installer
[mfc42.dll]
FileVersion=4,2,0,6256
Hook=mfc42installer
[olepro32.dll]
FileVersion = 4,2,0,6068
Hook = mfc42installer
[mfc42installer]
File-win32-x86=http://activex.microsoft.com/controls/vc/mfc42.cab
Run = %EXTRACT_DIR% \mfc42.exe
?
[Version]給出了INF文件的基本版本信息,“signature=”一行說明此INF文件可適用于32位
Windows操作系統; “AdvancedINF=”一行要求IE必須裝入2.0版以上的Advpack.dll模塊才能解析此INF文件。
[Add.Code]是INF文件的主體部分,它列出了所有ActiveX控件需要的文件以及每個文件所對應的部分名稱。MyCtrl控件是MFC開發的,所以它需要用到MFC的動態連接庫文件,所以,這一部分中列出了MyCtrl控件所必須的四個文件:MyCtrl.ocx、msvcrt.dll、mfc42.dll和olepro32.dll。
[MyCtrl.ocx]部分描述了MyCtrl控件組件程序MyCtrl.ocx的信息,包括此程序所在的CAB文件位置(thiscab指自身)以及MyCtrl控件的CLSID信息?!盕ileVersion=”指明了MyCtrl.ocx的版本;”RegisterServer=yes”說明此文件在使用之前要預先被注冊。
[msvcrt.dll] [mfc42.dll] [olepro32.dll]部分分別說明了相應的文件版本,并把進一步信息指向最后的[mfc42installer]部分。
[mfc42installer]部分中,“file-win32-x86=”指明了MFC42.CAB文件的URL路徑,”run=”指明了運行的命令
?
可用Cabarc.exe工具生成CAB文件,如:
Cabarc.exe N MyCtrl.cab MyCtrl.ocx MyCtrl.inf
?
用ATL產生的Activex控件所對應的INF文件如下:(可作為ATL開發的樣板)
[version]
??? Signature=”$CHICAGE$”
?? ?AdvancedINF = 2.0
[Add.Code]
??? Polygon.dll = polygon.dll
??? Atl.dll = atl.dll
[atl.dll]
??? File-win32-x86=thiscab
??? FileVersion = 3,00,0,8166
??? DestDir = 11
??? RegisterServer=yes
?
[Polygon.dll]
??? File-win32-x86=thiscab
??? Clsid = {2885EE05-A26B-11d1-B49B-00c04F98EFE0}
??? FileVersion=1,0,0,1
??? RegisterServer=yes
?
這里新出現的標記為“DestDir=”,它是指文件下載過來之后存放的目標目錄,“11”表示
Windows的系統目錄(“Windows\System” 或 “WInnt\System32”);“10”指windows目錄
(windows或winnt)。根據INF文件生成的CAB文件命令為:
Cabarc.exe N Polygon.cab ?atl.dll Polygon.dll Polygon.inf
?
CAB文件也支持數字簽名,我們在利用cabarc.exe工具生成CAB文件時可以用 –s命令行
參數預留數簽名空間,然后運行實用工具SIGNCODE,加入數字簽名即可。
?
許可證管理
??? 除了免費發行的ActiveX之外,大多數ActiveX控件都支持設計時刻和運行時刻的許可
證檢查。設計時刻許可證檢查可以保證程序員在創建就用系統或者WEB頁面時使用合法的
ActiveX控件;運行時刻許可證檢查可以保證用戶運行一個包含合法的控件的就用系統或者
顯示一個包含合法控件的Web頁面。
??? 由于許可證檢查是在ActiveX控件被創建時進行的,所以不管是設計時刻許可檢查還是
運行時刻許可檢查,實現的關鍵在于ActiveX控件的類廠對象。如果ActiveX控件支持許可
檢查,那么其類廠對象必須支持IClassFactory2接口。此接口是IClassFactory的擴展。
??? 許可證是一段文本信息,它可以存放在單獨的文件中,也可以存放在組件程序二進制代
碼中或者就用程序中。但作為ActiveX控件組件程序,它只需實現IClassFactory2接口的三
個成員函數,對于許可證的管理和用法取決于包容器程序。不同類型的包容器程序對許可證
的處理有所不同,并且設計時刻與運行時刻對許可證的處理也有所不同。
在創建包含ActiveX控件的應用程序時,包容器(如VB或其它開發工具)調用
IClassFactory2::GetLicInfo和RequestLicKey函數獲取許可證,然后嵌入到應用程序的二進制
代碼中。在運行應用程序時刻,作為包容器程序的應用程序在創建ActiveX控件時,調用
IClassFactory2::CreateInstanceLic函數創建控件對象,與設計時刻不同的是,它在bstrKey
參數中傳遞有效的許可證字符串(內嵌在程序中)而不是NULL。所以這樣的程序可以
在任何一機器上運行,而不用擔心許可問題
??? 對于IE這樣的包容器程序,它也調用IClassFactory2的成員函數進行許可檢查,但由于
ActiveX控件被包含在Web頁面上,任何瀏覽器都可以訪問到Web頁面,并且IE在創建控
件之前已經把程序代碼下載到本地,所以IE需要其它的方式把許可證隱藏起來,以避免許
可證被非法濫用。Microsoft為此引進了許可證包文件(license package file,文件名后綴為
LPK)。
??? 許可證文件格式共分四部分:
1.?LPK文件頭。包含信息“LPK License Package”。
2.?版權信息。對版權的解釋以及對非法拷貝的警告。
3.?LPK文件的版本和GUID。文本信息,也標識了真正許可證數據的開始。
4.?用UUENCODED(Base64)碼對許可證進行編碼。包含多個對象(CLSID)與相應的許可證(UNICODE字符串)。
IE包含一個許可證管理器組件,它負責解析LPK文件,并提取出每個CLSID的許可證。當
IE要顯示ActiveX控件時,它通過許可證管理器組件從LPK文件提取出許可證,然后調用IClassFactory2::CreateInstanceLic函數創建ActiveX控件對象,如果它指定的許可與ActiveX控件內部的許可證相匹配,那么ActiveX控件就會被創建并在頁面上顯示。
創建許可證包文件可以使用Microsoft提供的實用工具LPK_TOOL.EXE。為所指定的ActiveX控件生成相應的LPK文件。一旦生成了LPK文件,并可在WEB頁中使用,如:
<OBJECT CLASSID=”clsid: 2885EE05-A26B-11d1-B49B-00c04F98EFE0”>
<PARAM NAME=”LPKPATH” VALUE=”MyPage.lpk”>
</OBJECT>
LPK文件針對整個WEB頁面,而不是單個ActiveX控件,所以每個WEB頁面只能使用一個LPK文件。
?
WEB頁面中ActiveX控件的初始化
在“OBJECT”標記的“DATA”屬性中指定包含屬性數據文件的URL文件名。如果DATA屬性包含URL文件名,那么包容器就創建一個URL名字對象,并且調用ActiveX控件IPersistMoniker接口的Load成員函數執行初始化。ActiveX控件調用名字對象的IMoniker::BindToStorage函數以便獲取屬性數據并進行初始化。
如果ActiveX不支持IPersistMoniker接口,則IE會請求其它的永久接口,然后獲取屬性數據,必要時打包到流對象中,再調用永久接口的LOAD成員函數。于是ActiveX控件就可通過流對象得到屬性數據。
以下HTML說明在Web頁面中為ActiveX控件指定屬性數據的方法
<OBJECT CLASSID=” 2885EE05-A26B-11d1-B49B-00c04F98EFE0”
???????? ID=”MyCtrl”></OBJECT>
有時候ActiveX控件的屬性數據量很小,可以只用一些數值或字符串就把屬性表達出來。這種情況下,使用流方式的屬性表達式就沒有必要,可以在HTML中使用“
PARAM”關鍵字對ActiveX控件的屬性進行賦值。如:
<OBJECT CLASSID=” 2885EE05-A26B-11d1-B49B-00c04F98EFE0”
???????? <PARAM NAME = “Sides” VALUE = 5>
</OBJECT>
?
posted on 2007-03-08 17:26
SIMONE 閱讀(5954)
評論(2) 編輯 收藏 所屬分類:
C++