COM組件設計與應用(十八)——屬性包
作者:楊老師
下載源代碼
一、前言
書(shū)接上回,本回著(zhù)落在介紹屬性包 IPersistPropertyBag 接口的實(shí)現方法和調用方式。屬性包,是以“名稱(chēng) - 值”的方式提供組件持續性的支持,而“名稱(chēng) - 值”恰恰又適合于用文本方式來(lái)表現。下面的片段是在 HTML 中插入 Microsoft MonthView Control ActiveX 控件后的樣式:
<object classid="clsid:232E456A-87C3-11D1-8BE3-0000F8754DA1" id="MonthView1"><param name="_ExtentX" value="9393"><param name="_ExtentY" value="4974"><param name="_Version" value="393216"><param name="ForeColor" value="0"><param name="MaxSelCount" value="7"><param name="MonthColumns" value="1"><param name="CurrentDate" value="38632"><param name="MaxDate" value="2958465"><param name="MinDate" value="-53688"></object>以文本方式保存組件屬性,比較直觀(guān)、容易修改,上面 HTML 示例中的 <param name="屬性名" value="值"> 就很清晰。下面開(kāi)始介紹如何在組件中實(shí)現 IPersistPropertyBag 接口。








STDMETHODIMP Cxxx::get_str(BSTR* pVal){*pVal = m_str.Copy();return S_OK;}STDMETHODIMP Cxxx::put_str(BSTR newVal){m_str = newVal;return S_OK;}STDMETHODIMP Cxxx::get_integer(LONG* pVal){*pVal = m_integer;return S_OK;}STDMETHODIMP Cxxx::put_integer(LONG newVal){m_integer = newVal;return S_OK;}沒(méi)有什么復雜的,就是實(shí)現 str、integer 兩個(gè)屬性值的設置和讀取功能。class ATL_NO_VTABLE Cxxx :public CComObjectRootEx<...>,public CComCoClass<...>,public IDispatchImpl<...>,public IPersistPropertyBagImpl<Cxxx> // 手工添加派生類(lèi){... ... ...BEGIN_COM_MAP(Cxxx)... ... ...COM_INTERFACE_ENTRY(IPersistPropertyBag) // 手工添加接口表END_COM_MAP()... ... ... // 手工添加屬性映射表,這是 IPersistXXXImpl 所必須的。// 將來(lái)你在寫(xiě) ActiveX 的時(shí)候,ATL 向導會(huì )幫我們添加屬性映射表BEGIN_PROP_MAP(Cxxx)// 參數:"屬性名稱(chēng)", 接口屬性序號(見(jiàn)IDL文件), 屬性頁(yè)對話(huà)窗PROP_ENTRY("str", 1, CLSID_NULL)PROP_ENTRY("integer", 2, CLSID_NULL)END_PROP_MAP()... ... ...public:... ... ...// 這個(gè)成員變量,是 IPersistXXXImpl 所必須的bool m_bRequiresSave; // 表示屬性數據是否已經(jīng)改變而需要保存}; 我們只要手工添加以上內容,而不用自己寫(xiě)任何 IPersistPropertyBag 接口的函數,多簡(jiǎn)單呀!天空出彩霞呀,地上開(kāi)紅花呀......會(huì )唱這只歌的同學(xué)請舉手,每個(gè)人獎勵 vckbase 的專(zhuān)家分 500 !
STDMETHODIMP CPropertyBag::QueryInterface(const struct _GUID &iid,void ** ppv){*ppv = this;return S_OK;}ULONG __stdcall CPropertyBag::AddRef(void){ return 1; } // 做個(gè)假的就可以,因為反正這個(gè)對象在程序結束前是不會(huì )退出的ULONG __stdcall CPropertyBag::Release(void){ return 0; } // 做個(gè)假的就可以,因為反正這個(gè)對象在程序結束前是不會(huì )退出的STDMETHODIMP CPropertyBag::Read(LPCOLESTR pszPropName,VARIANT *pVar,IErrorLog *pErrorLog){// 根據 pszPropName 指定的屬性名稱(chēng),你要提供該屬性的值。// 而值的數據類(lèi)型已經(jīng)在 pVal->vt 中指定了。if( 如果能提供指定的數據 ) return S_OK;else return E_FAIL;}STDMETHODIMP CPropertyBag::Write(LPCOLESTR pszPropName,VARIANT *pVar){// 根據 psaPropName 指定的屬性名稱(chēng)和 pVar 提供的值// 你保存到文本中去吧。return S_OK;} 以上是調用者(容器)程序的關(guān)鍵部分,其它的管理和協(xié)調部分,讀者去閱讀示例程序代碼。編譯注冊組件,并運行調用者示例程序,顯示如下:
聯(lián)系客服