• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            旅途

            如果想飛得高,就該把地平線忘掉

            COM 組件設(shè)計(jì)與應(yīng)用(十七) ---持續(xù)性

            作者:楊老師

            下載源代碼

            一、前言

              我們寫程序,經(jīng)常需要實(shí)現(xiàn)這樣的需求:
            例一、程序運(yùn)行產(chǎn)生一個(gè)窗口,用戶關(guān)閉的時(shí)候需要記錄窗口的位置,以便下次運(yùn)行時(shí)保持位置不變;
            例二、由于程序運(yùn)行時(shí)間很長,今天執(zhí)行一部分,明天繼續(xù)執(zhí)行。那么在下次運(yùn)行前要恢復(fù)前次的狀態(tài);
            ... ... ... ...

            智慧的老師:以上這些需求,如何實(shí)現(xiàn)呢?
            懵懂的學(xué)生:這個(gè)簡單,只要在程序退出前提取必要的信息保存到文件中,下次運(yùn)行時(shí)再從文件中讀出來,設(shè)置一下就OK了。
            智慧的老師:恩,不錯(cuò),這位同學(xué)的思想值得表揚(yáng)。
            懵懂的學(xué)生:不好意思,這都要感謝老師的栽培,我對(duì)您的景仰如滔滔江水......
            智慧的老師:別臭P了,我話還沒有說完那......如果你需要提取和保存的信息很多,結(jié)構(gòu)很復(fù)雜......怎么辦?
            懵懂的學(xué)生:也好辦,我設(shè)計(jì)一個(gè)結(jié)構(gòu)來記錄這些信息。
            智慧的老師:恩......不錯(cuò)。但如果這些信息提供方是別人寫的模塊,并且隨著版本的不同還經(jīng)常變化,你怎么辦?
            懵懂的學(xué)生:... ...
            智慧的老師:解決這些問題的方法是---持續(xù)性。

            二、原理
              持續(xù)性,也叫永久性。組件方提供 IPersistXXX 接口,調(diào)用者(容器)提供存儲(chǔ)介質(zhì),比如文件啦、內(nèi)存啦、注冊(cè)表啦、流啦、文本啦......啦啦拉。需要保存的時(shí)候,調(diào)用者通過 IPersistXXX::Save() 接口函數(shù)讓組件去自己存儲(chǔ)屬性信息,而調(diào)用者根本不用關(guān)心存儲(chǔ)格式和存儲(chǔ)內(nèi)容;需要還原狀態(tài)的時(shí)候,調(diào)用者打開存儲(chǔ)介質(zhì),然后同樣調(diào)用 IPersistXXX::Load() 接口函數(shù)讓組件自己去讀取屬性信息并完成初始化的設(shè)置。
              目前,微軟定義了如下各種類型的持續(xù)性接口,足夠滿足你的需求了。我們只要在自己寫的組件中實(shí)現(xiàn)其中一個(gè)或幾個(gè)持續(xù)性接口,那么調(diào)用者就可以按照統(tǒng)一的方式和我們的組件協(xié)商完成屬性信息的保存和狀態(tài)還原了。
             
            持續(xù)性接口 簡要說明
            IPersist    所有持續(xù)性接口的根,下面的接口大多從它派生出來。這個(gè)接口很簡單,只有一個(gè)函數(shù) GetClassID()它返回組件的 CLSID 號(hào),以便調(diào)用者能保存這個(gè)號(hào)為將來 CoCreateInstance() 啟動(dòng)組件用。
               實(shí)現(xiàn)這個(gè)函數(shù)也很簡單,只要返回你組件中的 CLSID_XXX 即可,或者比較省事的方法是返回 GetObjectCLSID() 。
            IPersistStream

            派生自 IPersist,并增加了4個(gè)函數(shù),從流(IStream)中讀寫組件屬性信息。

            IsDirty() 組件內(nèi)部屬性是否發(fā)生了變化。為調(diào)用者是否需要保存信息提供依據(jù)
            Load() 從 IStream 中讀入信息,初始化組件屬性
            Save() 把屬性信息保存到 IStream 中
            GetSizeMax() 返回信息尺寸,以便調(diào)用者事先開辟空間
            IPersistStreamInit 派生自 IPersistStream,并再增加了一個(gè)函數(shù) InitNew() 用來完成一個(gè)默認(rèn)的組件屬性初始化。
            這個(gè)持續(xù)性接口是最常用的,本文示例中就實(shí)現(xiàn)了該接口。
            IPersistMemory 和 IPersistStreamInit 類似,但使用的是內(nèi)存塊,而不是大小可變化的 IStream 流。
            IPersistStorage 和 IPersistStream 類似,但保存屬性信息使用的是存儲(chǔ) IStorage,一個(gè) IStorage 中可以有多個(gè) IStream。
            IPersistFile 和 IPersistStream 類似,但存儲(chǔ)介質(zhì)為文件。
            IPersistPropertyBag    使用屬性包(屬性名、屬性值)的文本方式保存信息。在 IE 瀏覽器中,HTML 嵌入 ActiveX 控件通常使用這個(gè)方法。
               在 HTML 中插入控件,<param name="屬性名稱" value="值"> 這樣的形式你應(yīng)該見過吧?!
               在下一回的文章中,我們介紹這個(gè)接口。因?yàn)樵?ActiveX 中,它太常用了。
            IPersistPropertyBag2 擴(kuò)展了 IPersistPropertyBag 接口。提供了更豐富一些的屬性管理用函數(shù)。
            IPersistMoniker 用于命名(moniker)存儲(chǔ)和讀取狀態(tài)的持續(xù)性接口。
            IPersistHistory 運(yùn)行于 IE 上,想在用戶瀏覽 WEB 頁面時(shí)存儲(chǔ)和讀取狀態(tài)的持續(xù)性接口。

            三、持續(xù)性接口組件的實(shí)現(xiàn)
              示例程序分別在 vc6.0 和 vc.net 上實(shí)現(xiàn)了 IPersistStreamInit 接口的 COM 組件和調(diào)用舉例。組件完成的功能是計(jì)算素?cái)?shù),你第一次運(yùn)行的時(shí)候,會(huì)得到第一個(gè)素?cái)?shù)2,然后是3,5,7,11......下班時(shí)間到了,今天就運(yùn)行到這里。于是調(diào)用者開辟一個(gè)流來保存組件的屬性信息。明天繼續(xù)運(yùn)行的時(shí)候,從流中原換組件狀態(tài),開始了新的計(jì)算 13,17,19,23......
              這個(gè)示例應(yīng)用完全是假設(shè)性的,其實(shí)沒有什么實(shí)用價(jià)值,只是演示了 IPersistStreamInit 接口的實(shí)現(xiàn)方法。另外,關(guān)于建立流(IStream)的方法,請(qǐng)參閱COM 組件設(shè)計(jì)與應(yīng)用(一)》

            1、建立一個(gè) ATL 工程項(xiàng)目。
            2、增加 ATL 組件類,vc.net 使用者注意不要選擇“屬性化編程”方式,其它的設(shè)置全部使用默認(rèn)方法。當(dāng)然你愿意適當(dāng)?shù)馗淖冞x擇也無所謂。
            3、設(shè)計(jì)完成你的組件功能。
               示例程序中,實(shí)現(xiàn)了一個(gè)接口函數(shù) GetNext() 負(fù)責(zé)計(jì)算下一個(gè)素?cái)?shù)。
            4、添加IPersistStreamInit 接口。

            class ATL_NO_VTABLE Cxxx : 	public CComObjectRootEx<...> ,	public CComCoClass<...>,	......	public IPersistStreamInit	// 手工添加持續(xù)性接口{......BEGIN_COM_MAP(Cxxx)	......		// 手工添加接口映射表入口	COM_INTERFACE_ENTRY(IPersistStreamInit)		// 表示如果要取得 IPersistStream 指針,則返回 IPersistStreamInit 指針	COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStreamInit)		// 表示如果要取得 IPersist 指針,則返回 IPersistStremInit 指針	COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersistStreamInit)END_COM_MAP()
            5、完成 IPersistStreamInit 接口函數(shù)。
            手工在 h 頭文件中增加函數(shù)聲明:
            public:// IPersist	STDMETHOD(GetClassID)(/*[out]*/CLSID * pClassID);// IPersistStream	STDMETHOD(IsDirty)(void);	STDMETHOD(Load)(/*[in]*/IStream *pStm);	STDMETHOD(Save)(/*[in]*/IStream *pStm,/*[in]*/BOOL fClearDirty);	STDMETHOD(GetSizeMax)(/*[out]*/ULARGE_INTEGER *pcbSize);// IPersistStreamInit	STDMETHOD(InitNew)(void);
            手工在 cpp 文件中增加函數(shù)實(shí)現(xiàn):
            // IPersistSTDMETHODIMP Cxxx::GetClassID(/*[out]*/CLSID * pClassID){	*pClassID = GetObjectCLSID();	return S_OK;}// IPersistStreamSTDMETHODIMP Cxxx::IsDirty(void){	if( 數(shù)據(jù)已經(jīng)改變,需要保存 )	return S_OK;	else			return S_FALSE;}STDMETHODIMP Cxxx::Load(/*[in]*/IStream *pStm){	return pStm->Read( 讀到哪里, 讀多長字節(jié), NULL);}STDMETHODIMP Cxxx::Save(/*[in]*/IStream *pStm,/*[in]*/BOOL fClearDirty){	if( fClearDirty )	清除內(nèi)部表示數(shù)據(jù)變化的變量;	return pStm->Write( 需要保存的數(shù)據(jù)指針, 寫多長字節(jié), NULL );}STDMETHODIMP Cxxx::GetSizeMax(/*[out]*/ULARGE_INTEGER *pcbSize){	pcbSize->LowPart = 需要保存數(shù)據(jù)長度的低位;	pcbSize->HighPart = 需要保存數(shù)據(jù)長度的高位;// 一般都是0,難道你的數(shù)據(jù)長度都超過了 4G?	return S_OK;}// IPersistStreamInitSTDMETHODIMP Cxxx::InitNew(void){	內(nèi)部屬性數(shù)據(jù)默認(rèn)初始化;	設(shè)置或清除內(nèi)部表示數(shù)據(jù)變化的變量;	return S_OK;}
            四、小結(jié)
              下載示例程序后,結(jié)合本文仔細(xì)閱讀代碼,并試著運(yùn)行看看效果。如果你理解了,那么你能自己實(shí)現(xiàn) IPersistFile 接口嗎?你能自己實(shí)現(xiàn) IPersistStorage 接口嗎?你實(shí)現(xiàn)的持續(xù)性接口越多,別人使用你的組件就越方便,也就是說你的組件就能大賣特賣啦,祝你為中國軟件事業(yè)做貢獻(xiàn)的同時(shí)多多賺錢:-)下回我們用 IPersistPropertyBag 接口實(shí)現(xiàn)持續(xù)性屬性包功能,別忘了看呦......

            posted on 2007-07-30 15:59 旅途 閱讀(384) 評(píng)論(0)  編輯 收藏 引用 所屬分類: COM+/DCOM

            精品久久久久久久| 亚洲伊人久久精品影院| 国产精品久久久久久久| 青青青青久久精品国产h| 久久久久九国产精品| 久久午夜免费视频| 久久丫精品国产亚洲av不卡 | 无码人妻久久一区二区三区| 久久99精品国产自在现线小黄鸭 | 成人精品一区二区久久久| 久久综合色区| 精品久久久久中文字幕日本| 免费一级做a爰片久久毛片潮| 久久无码人妻一区二区三区午夜 | 久久综合九色综合精品| 人妻无码精品久久亚瑟影视 | 久久久久久亚洲Av无码精品专口| 久久精品国产免费一区| 亚洲乱码中文字幕久久孕妇黑人| 久久精品一区二区三区中文字幕| 国内精品久久久久影院日本| 亚洲国产高清精品线久久| 国产成人精品久久综合| 久久777国产线看观看精品| 久久久这里只有精品加勒比| 久久精品国产国产精品四凭| 狠狠色丁香婷综合久久| 伊人久久精品无码二区麻豆| 亚洲伊人久久成综合人影院 | 亚洲国产精品人久久| 久久综合久久美利坚合众国| 久久无码国产| 狠狠精品久久久无码中文字幕 | 久久91精品久久91综合| 无码超乳爆乳中文字幕久久| 精品久久久无码人妻中文字幕| 久久久噜噜噜久久中文字幕色伊伊| 色综合久久精品中文字幕首页| 国产成人无码久久久精品一| 久久精品人人槡人妻人人玩AV| 亚洲精品无码久久一线|