好象是繞口令一樣的標題。呵呵,看看下面的這個例子,我想大家就知道是 什麼意思了吧。
在腳本語言中,我們經常看到類似這樣的語句:obj.Document.Write(...), obj顯然是一個自動化的對象(IDispatch),它可以擁有方法和屬性。但 Document 到底是什麼那?如果說它是方法,那麼就無法解釋 Document.Write 了;如果說 他是屬性,那麼屬性怎麼還有Write方法那?答案是Document是一個LPDispatch 類型的屬性(具有自動化類型的屬性),當然,這樣的屬性擁有方法就不奇怪了 吧。
在我們自己寫的自動化組件中,當然你可以把所有的方法都用唯一的一個自 動化接口表現出來,但是這樣好嗎?所有的方法都處於一個層次上,沒有適當的 分類,顯然不是個優秀的組件。好了,下面看看我們如何實現分層次的自動化組 件吧。
MFC(CCmdTarget) 和 ATL(DUAL 雙接口)都可以實現組件自動化的接口。下面 分別來實現。(VC6編譯測試通過)
一、用MFC實現LPDispatch自動化接口屬性
產生一個支持自動化(Automation)的程序(例子程序中,使用的是DLL)
添加一個自動化類 CAAA ,派生於CCmdTarget。選擇Createable by type ID 。注意,只有選擇這項,才能被外部程序(VB)CreateObject或(VC) CreateDispatch等方法建立對象
添加另一個自動化類CBBB,派生於CCmdTarget。選擇Automation
在CAAA中,添加的成員對象,CBBB m_bbb
在IAAA中,添加名稱為BBB,類型為LPDispatch的屬性,使用Get/Set類型
完成BBB屬性的Get/Set代碼 LPDISPATCH CAAA::GetBBB()
{
return m_bbb.GetIDispatch(TRUE);
}
void CAAA::SetBBB(LPDISPATCH newValue)
{
SetNotSupported();
}
在IBBB中,添加方法(例子程序中,實現了一個數值加法)
修改CBBB的析構函數,從protected移動到public中
二、用ATL實現LPDispatch自動化接口屬性
產生一個ATL的組件程序框架(例子程序中,使用的是DLL)
添加一個IAAA的雙接口
手工添加另一個IBBB的雙接口
IDL文件修改如下:
... ...
[
object,
uuid(D17A119E-0FEC-4737-8EBD-4AA040393A36), //這裡是例子程序中的 IID,你需要自己產生
dual,
helpstring("IBBB Interface"),
pointer_default(unique)
]
interface IBBB : IDispatch
{
};
... ...
coclass AAA
{
[default] interface IAAA;
interface IBBB; //這是手工添加的第2個接口
};
頭文件,修改如下:
添加派生關系
class ATL_NO_VTABLE CAAA :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CAAA, &CLSID_AAA>,
public IDispatchImpl<IAAA, &IID_IAAA, &LIBID_ATLDISPLib>,
public IDispatchImpl<IBBB, &IID_IBBB, &LIBID_ATLDISPLib> //新增
添加並修改接口入口宏
BEGIN_COM_MAP(CAAA)
COM_INTERFACE_ENTRY(IAAA)
COM_INTERFACE_ENTRY(IBBB) //新增
//修改,使用ENTRY2方式,這樣VB才能知道默認使用哪個IDispatch接口
COM_INTERFACE_ENTRY2(IDispatch,IAAA)
END_COM_MAP()
在IAAA中,添加屬性BBB,類型為LPDispatch,只實現Get方法 STDMETHODIMP CAAA::get_BBB(LPDISPATCH *pVal)
{
QueryInterface(IID_IBBB,(LPVOID *)pVal);
return S_OK;
}
在IBBB中,添加方法(例子程序中,實現了一個數值加法)
HRESULT Add([in] long n1,[in] long n2, [out,retval] long *pnSum);
三、測試
下載代碼後,在Release目錄中有兩個DLL和兩個VBS的測試程序。用 Regsvr32.exe注冊兩個組件後,雙點VBS文件就可以執行了。
本文配套源碼