1.exe,ocx,dll的區別
分析:exe是一個可執行程式,而ocx看做是一個視窗上的控制項(控制項即ocx,如button),dll是將函數、變數、類封裝在一起的庫
ocx的形式如下:
圖中的各個都是ocx控制項(我是這樣認為的),只不過MFC內建了一些控制項,但是如果是自己寫的ocx控制項,程式運行時必須將產生的ocx控制項拷到可執行目錄下
2.ocx特點(根據普通的button可知)
(1)ocx是可視化視窗,一個ocx有一個ID,可以通過ID來建立一個對應的類,調用其中函數(如果看不到,那麼肯定隱藏了)
(2)可以響應單擊、雙擊等滑鼠事件
(3)含有對應的屬性
3.建立一個ocx程式(如何讓ocx含有上面這些屬性呢)
(1)利用VS2010建立一個MFC ActiveX Control工程,名為myocx
其中myocx.h中InitInstance是入口,.cpp中含有ocx註冊、反註冊的函數
myocxCtrl.h中CmyocxCtrl是ocx的可視化視窗類別,父類是COleControl,因為是視窗,所以可以響應OnCreate,Onsize等訊息,含有訊息映射,調度映射,事件映射
myocxPropPage.h是ocx的屬性,就像按鈕button類含有屬性一樣
myocx.idl是對外介面,據說CmyocxCtrl類是繼承它的,所有對外介面都在myocx.idl這裡聲明,在CmyocxCtrl類中實現
myocx.def,ocx是一種特殊的dll,所以同樣有def檔案,內容如下
; myocx.def : Declares the module parameters.EXPORTSDllCanUnloadNow PRIVATEDllGetClassObject PRIVATEDllRegisterServer PRIVATEDllUnregisterServer PRIVATE
其中的PRIVATE的意思是對ocx私人,即這些函數名不會加到產生的庫檔案中(編譯ocx發現除了產生ocx,還有一個lib檔案)
(2)訊息映射,調度映射,事件映射
>1含義
訊息映射:即響應作業系統的訊息
調度映射:可以在外部調用的介面函數,通俗的將就是一個控制項可以調用它內部的函數,如CButton btn;btn.函數名();
事件映射:單擊、雙擊等事件由ocx傳給它的容器進行響應,如按鈕的一些事件,觸發後可以在它的父視窗中進行響應處理
>2添加調度映射
在myocx的idl中對應的調度映射下添加:
[id(1)] void Hello();
在myocx.h中添加:
afx_msg void Hello();//添加調度枚舉類型enum { //調度ID,從1開始dispidHello = 1L, //事件ID,從1開始};
在myocx.cpp中添加:
void CmyocxCtrl::Hello(){AfxMessageBox(_T("Hello world"));}
編譯並產生ocx,預設編譯產生的ocx也註冊好了
建立一個基於對話方塊的MFC工程,名為useocx,在對話方塊視窗右擊插入ActiveX 控制項,快速輸入產生的ocx的前幾個字母找到ocx,添加進去
右鍵ocx,選擇添加變數,變數名設為m_myocx,設定好後,便會產生對應的ocx類
可以看到ocx類中已經自動含有:
void Hello(){InvokeHelper(0x1, DISPATCH_METHOD, VT_EMPTY, NULL, NULL);}
這個時候就可以利用m_myocx調用裡面的Hello函數了
附:也可以在下面這個位置右鍵選擇添加添加函數實現
>3添加事件映射
在下圖上右鍵
選擇添加事件,選擇Click,確認,效果是在idl檔案事件下面多出下面一行:
[id(DISPID_CLICK)] void Click(void);
在myocx.cpp中中間多出:
BEGIN_EVENT_MAP(CmyocxCtrl, COleControl)EVENT_STOCK_CLICK()END_EVENT_MAP()
效果是在useocx工程的資源對話方塊檔案中,右鍵添加的Ocx控制項,查看屬性,發現事件中
多出了Click屬性,此時可以添加函數,運行useocx工程時滑鼠點擊控制項就會觸發這個函數
如果添加自訂的事件映射,則在myocxi.idl中事件映射下添加:
[id(1)] void MyDrag(void);
在myocxCtrl.h中添加
enum {//調度映射ID dispidHelloClick = 1L,//事件映射IDeventidMyDrag = 1L, };protected:void MyDrag(void){ FireEvent(eventidMyDrag, EVENT_PARAM(VTS_NONE));}
同樣查看useocx工程資源對話方塊檔案控制項屬性:
多出MyDrag屬性,此時可以再外面寫響應函數,具體觸發則需要根據需要在ocx內部調用就可以觸發
這裡注意ocx事件觸發都是在ocx內部觸發,外部進行響應處理的,如button類,點擊或雙擊都是在按鈕本身觸發,最後由它的父視窗進行響應處理,自訂的事件也是要在內部進行觸發
注意:InvokeHelper和FireEvent這兩個函數中的表示傳入形參的參數含有多個時,通過空格進行隔開(一個函數形參可以有很多個,但傳回值只有一個)
總結:
1.ocx有三種映射,但idl中對外提供的只有調度映射和事件映射
2.(1)ocx的類與ocx是通過idl檔案中最後的類的ID建立聯絡的
idl中:
// Class information for CmyocxCtrl[uuid(EF2CFD6B-E121-47E3-BD63-5F5DD51DCCFF)]
在ocx類(class CMyocxctrl_use : public CWnd)中
CLSID const& GetClsid(){static CLSID const clsid= { 0xEF2CFD6B, 0xE121, 0x47E3, { 0xBD, 0x63, 0x5F, 0x5D, 0xD5, 0x1D, 0xCC, 0xFF } };return clsid;}
(2)調度映射是通過Idl中調度函數前的ID建立聯絡的
在idl中:
[id(1)] void Hello();
在在ocx類(class CMyocxctrl_use : public CWnd)中
void Hello(){InvokeHelper(0x1, DISPATCH_METHOD, VT_EMPTY, NULL, NULL);}
(3)事件映射是在內部進行觸發,也就是含有fireEvent的那個函數是在ocx內部調用作為觸發方式,響應在外面實現
3.ocx作為控制項在MFC中使用時,此時該控制項與它的容器是父視窗與子視窗關係,普通控制項與父視窗之間的函數調用方式它也同樣適用
4ocx屬性
與myocxPropPage.h中CmyocxPropPage類有關,對應的效果:
5.ocx調試
(1)在exe中進行調試
按照上面方法在useocx工程中添加好ocx後,在myocx工程中設定以下屬性:
就可以調試了
(2)在IE中調試
首先編寫一個html檔案,尾碼名為htm,添加如下內容:
HTML> <HEAD> <TITLE>Test ActiveX</TITLE> </HEAD> <OBJECT ID="TestMfcAtl Control" WIDTH=528 HEIGHT=545 classid="CLSID:EF2CFD6B-E121-47E3-BD63-5F5DD51DCCFF"> <PARAM NAME="_Version" VALUE="65536"> <PARAM NAME="_ExtentX" VALUE="12806"> <PARAM NAME="_ExtentY" VALUE="1747"> <PARAM NAME="_StockProps" VALUE="0"> </OBJECT> </HTML>
注意其中ID就是idl中類的ID,在myocx中設定如下屬性:
第一個是IE的路徑,第二個是IE地址欄中的資料,根據需要可填可不填,有的是IP地址,有的是htm,這樣就可以了
說明:有的IE不是單進程的,可以通過附加到進程進行調試,也可以將IE設定成單進程的
我這裡通過IE調試的時候打斷點,調試運行滑鼠不可用,也不知道什麼原因,暫未解決
6.ocx程式發布
OCX不能單獨運行,發布時必須拷到對應的可執行檔程式中,一起發布