IPersistStorage接口详解

50 篇文章 0 订阅
23 篇文章 0 订阅

     允许一个ActiveX控件嵌入到容器中,这项技术已经很长时间了。OLE文档标准(当时称为复合文档,Compound Documents)1991年创建,其中包含了OLE的主要内容。实际上OLEObject Linking and Embedding(对象链接与嵌入)的首字母缩写。在ActiveX控件出现以后,OLE文档标准也得到了增强,它允许文档服务器向外公开programmatic功能。

       现在,如果你所开发的控件需要提供一个可视化界面,并需要通过鼠标点击或类似的方式与用户实现交互,则它必须支持基本的OLE文档接口:IOleObjectIOleInPlaceObjectIOleInPlaceActiveObjectIDataObject以及IViewObject2

 

接口

说明

IOleObject

IOleObject提供了OLE文档构架的基本内容。通过该接口,容器和组件相互协商被嵌入对象的大小

IOleInPlaceObject

一个控件必须实现IOleInPlaceObject来支持在容器中实现在位激活和失效。该接口还提供了一个方法,用于通知控件,他的大小已经改变或已经在容器中删除

IOleInPlace

ActiveObject

一个控件必须实现IOleInPlaceActiveObject,以便对在控件中使用和转换加速键提供支持。IOleInPlaceActiveObject的大部分方法对于ActiveX控件是不需要的

IOleControl

IOleControl是为支持ActiveX控件而加入的一个新的接口。它所提供的方法使得与控件容器的交互得到了加强。IOleControl的主要功能是允许控件和容器在处理键盘输入时能够很好的协调工作

IDataObject

控件实现该接口主要用于为容器提供图形绘制功能。IDataObject还提供了一个属性,用于对它的属性持续性进行设置

IViewObject2

当一个控件提供一个可视的外观时需要提供IViewObject2。该接口为容器提供各种方法,允许容器通过这些方法请求控件在容器的客户区重绘控件本身

IPersistFile

IPersistFile接口比较简单,客户程序调用Load函数使永久对象装载状态数据,执行初始化操作,永久对象可以使文件保持打开状态。在Save函数中,如果参数lpszFileNameNULL,那么永久对象把状态数据写到文件中,同时清除修改标记并关闭文件;如果lpszFileName不为NULL,那么根据参数fRemember的不同值,或者执行Save As操作,或者执行Save Copy As,前者情况下也要清除修改标记并关闭文件。客户程序调用SaveCompleted函数,通知永久对象保存操作已经完成,对象可以再打开文件。GetCurFile函数返回永久对象所使用的文件名字

IPersistStorage

IPersistStorage接口并不复杂,它不仅可实现在事物方式下用存储对象保存永久状态数据,而且也支持零内存保存特性。客户程序通过SaveCompleted函数通知永久对象,它已经完成了所有的保存操作,根据参数的值,客户控制永久对象进入相应的状态。客户程序利用HandsOffStorage函数指示永久对象释放存储对象的所有接口指针,包括所有的子对象,以后由客户程序完全控制存储对象

 

 

来个例子吧,仅仅是实现了一个IPersistStorage接口:

1、我打算从d://test.bmp得到bmp的数据,然后StgCreateStorageEx,通过IPersistStorageSave函数保存到Zeng.stg(createStream了一个流ZengStream)
2、通过读取d://a.stg然后在Load函数中OpenStreamZengStream,从里面得到刚才保存的数据,再写到本地文件1.bmp 

 
  1. // CImpIPersist.cpp : 定义控制台应用程序的入口点。  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include "windows.h"  
  6. #include "fstream"  
  7. #include "iostream"  
  8. using namespace std;  
  9. #include <initguid.h>  
  10. #include "assert.h"  
  11.   
  12. DEFINE_GUID(CLSID_CImpIPersistStorage, 0x00021108, 0, 0, 0xB0,0,0,0,0,0,0,0x47);  
  13.   
  14. class ImpIPersistStorage : public IPersistStorage  
  15. {  
  16. protected:  
  17.     ULONG                   refence_count_;  
  18.     LPSTORAGE               pIStorage_;  
  19.     LPSTREAM                pIStream_;  
  20.   
  21. public:  
  22.     ImpIPersistStorage();  
  23.     ~ImpIPersistStorage();  
  24.   
  25.     STDMETHODIMP QueryInterface(/* [in] */ REFIID riid,  
  26.         /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject);  
  27.     STDMETHODIMP_(ULONG) AddRef(void);  
  28.     STDMETHODIMP_(ULONG) Release(void);  
  29.   
  30.     STDMETHODIMP GetClassID(LPCLSID);  
  31.   
  32.     STDMETHODIMP IsDirty(void);  
  33.     STDMETHODIMP InitNew(LPSTORAGE);  
  34.     STDMETHODIMP Load(LPSTORAGE);  
  35.     STDMETHODIMP Save(LPSTORAGE, BOOL);  
  36.     STDMETHODIMP SaveCompleted(LPSTORAGE);  
  37.     STDMETHODIMP HandsOffStorage(void);  
  38. };  
  39.   
  40. ImpIPersistStorage::ImpIPersistStorage()  
  41. {  
  42.     refence_count_  = 0;  
  43.     pIStorage_      = NULL;  
  44.     pIStream_       = NULL;  
  45. }  
  46.   
  47. ImpIPersistStorage::~ImpIPersistStorage()  
  48. {  
  49.     if (0 == refence_count_)  
  50.     {  
  51.     //  delete this;  
  52.     }  
  53. }  
  54.   
  55. //  
  56. // IUnknown  
  57. //  
  58. STDMETHODIMP ImpIPersistStorage::QueryInterface(/* [in] */ REFIID riid,  
  59.                                                  /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject)  
  60. {  
  61.     *ppvObject = NULL;  
  62.   
  63.     if (IsEqualIID(riid, IID_IUnknown))  
  64.         *ppvObject=(LPVOID)this;  
  65.   
  66.     if (IsEqualIID(riid, IID_IPersist)  
  67.         || IsEqualIID(riid, IID_IPersistStorage))  
  68.         *ppvObject=(LPVOID)this;  
  69.   
  70.     //AddRef any interface we'll return.  
  71.     if (NULL!=*ppvObject)  
  72.     {  
  73.         ((LPUNKNOWN)*ppvObject)->AddRef();  
  74.         return NOERROR;  
  75.     }  
  76.   
  77.     return ResultFromScode(E_NOINTERFACE);  
  78. }  
  79.   
  80. STDMETHODIMP_(ULONG) ImpIPersistStorage::AddRef(void)  
  81. {  
  82.     ++refence_count_;  
  83.   
  84.     return (ULONG)refence_count_;  
  85. }  
  86.   
  87. STDMETHODIMP_(ULONG) ImpIPersistStorage::Release(void)  
  88. {  
  89.     --refence_count_;  
  90.     if (0 == refence_count_)  
  91.     {  
  92.         delete this;  
  93.         return 0;  
  94.     }  
  95.     return (ULONG)refence_count_;  
  96. }  
  97.   
  98.   
  99. //  
  100. // IPersistStorage  
  101. //  
  102. STDMETHODIMP ImpIPersistStorage::GetClassID(LPCLSID pClsID)  
  103. {  
  104.     *pClsID = CLSID_CImpIPersistStorage;  
  105.     return NOERROR;  
  106. }  
  107.   
  108. STDMETHODIMP ImpIPersistStorage::IsDirty(void)  
  109. {  
  110.     return ResultFromScode(S_OK);  
  111. }  
  112.   
  113. STDMETHODIMP ImpIPersistStorage::InitNew(LPSTORAGE pIStorage)  
  114. {  
  115.     if (NULL != pIStorage_)  
  116.     {  
  117.         return ResultFromScode(E_UNEXPECTED);  
  118.     }  
  119.       
  120.     HRESULT hr = pIStorage->CreateStream(    L"ZengStream",   
  121.                                             STGM_DIRECT | STGM_CREATE | STGM_WRITE   
  122.                                             | STGM_SHARE_EXCLUSIVE, 0, 0, &pIStream_);  
  123.   
  124.     if (FAILED(hr))  
  125.     {  
  126.         return hr;  
  127.     }  
  128.   
  129.     WriteClassStg(pIStorage, CLSID_CImpIPersistStorage);  
  130.     WriteFmtUserTypeStg(pIStorage, 0, 0);  
  131.   
  132.     pIStorage->AddRef();  
  133.     pIStorage_ = pIStorage;  
  134.   
  135.     return NOERROR;  
  136. }  
  137.   
  138. STDMETHODIMP ImpIPersistStorage::Load(LPSTORAGE pIStorage)  
  139. {  
  140.     HRESULT         hr;  
  141.     ULONG           cb = -1;  
  142.     ULONG           fileLength = 0;  
  143.     LPSTREAM        pIStream;  
  144.     ofstream        fout("d://1.bmp", ios::binary);  
  145.   
  146.     if ( NULL != pIStorage_ )  
  147.         return ResultFromScode(E_UNEXPECTED);  
  148.   
  149.     if ( NULL == pIStorage )  
  150.         return ResultFromScode( STG_E_INVALIDPOINTER );  
  151.   
  152.     hr = pIStorage->OpenStream( L"ZengStream", 0, STGM_DIRECT  
  153.                                 | STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pIStream );  
  154.   
  155.     if ( FAILED(hr) )  
  156.         return ResultFromScode( STG_E_READFAULT );  
  157.   
  158.     // begin read the file length info from IStream  
  159.     hr = pIStream->Read( (LPVOID)&fileLength, sizeof(ULONG), &cb );  
  160.   
  161.     LARGE_INTEGER lInt;  
  162.     lInt.QuadPart = sizeof(ULONG);  
  163.     pIStream->Seek( lInt,STREAM_SEEK_SET, 0 );  
  164.   
  165.     if ( FAILED(hr) || ( sizeof(ULONG) != cb ) )  
  166.     {  
  167.         pIStream->Release();  
  168.         return ResultFromScode( STG_E_READFAULT );   
  169.     }  
  170.   
  171.     cout << "read the file length is :" << fileLength << endl;  
  172.   
  173.     void *readFileData = new char[ fileLength ];  
  174.   
  175.     hr = pIStream->Read( readFileData, fileLength, &cb );  
  176.     if ( FAILED(hr) || ( fileLength != cb ) )  
  177.     {  
  178.         pIStream->Release();  
  179.         return ResultFromScode( STG_E_READFAULT );   
  180.     }  
  181.   
  182.     //已经读取到了bmp的数据  
  183.     fout.write( (char *)readFileData, fileLength );  
  184.   
  185.     pIStream_  = pIStream;  
  186.   
  187.     pIStorage->AddRef();  
  188.     pIStorage_ = pIStorage;  
  189.   
  190.     fout.close();  
  191.   
  192.     return NOERROR;  
  193. }  
  194.   
  195. STDMETHODIMP ImpIPersistStorage::Save( LPSTORAGE pIStorage, BOOL fSameAsLoad )  
  196. {  
  197.     HRESULT     hr;  
  198.     LPSTREAM    pIStream;  
  199.     ULONG       totalWriteBytes = 0;  
  200.   
  201.   
  202.     if (NULL==pIStorage)  
  203.         return ResultFromScode(STG_E_INVALIDPOINTER);  
  204.   
  205.     // fSameAsLoad is true, mean create a new stream  
  206.     if ( fSameAsLoad )  
  207.     {  
  208.         LARGE_INTEGER   li;  
  209.         pIStream = pIStream_;  
  210.   
  211.         LISet32( li, 0 );  
  212.         pIStream->Seek( li, STREAM_SEEK_SET, NULL );  
  213.   
  214.         pIStream->AddRef();  
  215.     }  
  216.     else  
  217.     {  
  218. //      hr = pIStorage->CreateStream(    L"zengraoli", STGM_DIRECT  
  219. //          | STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pIStream );  
  220.         hr = pIStorage->CreateStream(                        // 建立流  
  221.                                         L"ZengStream",      // 流名称  
  222.                                         STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE,  
  223.                                         0,0,  
  224.                                         &pIStream );        // 取得流接口指针  
  225.   
  226.         if (FAILED(hr))  
  227.         {  
  228.             return hr;  
  229.         }  
  230.   
  231.         WriteFmtUserTypeStg( pIStorage, 0, 0 );  
  232.     }  
  233.   
  234.     if ( NULL == pIStream )  
  235.     {  
  236.         return ResultFromScode( STG_E_WRITEFAULT );  
  237.     }  
  238.   
  239.     // read bitmap from local file  
  240.     ifstream fin("d://test.bmp", ios::binary);  
  241.     if (NULL == fin)  
  242.     {  
  243.         printf("the file is open fail...");  
  244.         return 0;  
  245.     }  
  246.     fin.seekg(0, ios::end);  
  247.     ULONG fileLength = fin.tellg();  
  248.     fin.seekg(0, 0);  
  249.     int writeLength = fileLength + sizeof(ULONG);  
  250.     void *fileData = new char[writeLength + 1];  
  251.     *((ULONG*)fileData) = fileLength;   // write the bitmap date length to fileDate  
  252.   
  253.     while (!fin.eof())  
  254.     {  
  255.         fin.read((char *)fileData + sizeof(ULONG), fileLength);  
  256.     }  
  257.   
  258.     // write fileData to pIStream  
  259.     hr = pIStream->Write(fileData, writeLength, &totalWriteBytes);  
  260.     pIStream->Release();  
  261.     if (FAILED(hr) || totalWriteBytes != writeLength)  
  262.     {  
  263.         return ResultFromScode(STG_E_WRITEFAULT);  
  264.     }  
  265.   
  266.     return NOERROR;  
  267. }  
  268.   
  269. STDMETHODIMP ImpIPersistStorage::SaveCompleted(LPSTORAGE pIStorage)  
  270. {  
  271.     HRESULT hr;  
  272.     LPSTREAM pIStream;  
  273.   
  274.     if (NULL != pIStorage)  
  275.     {  
  276.         hr = pIStorage->OpenStream( L"ZengStream", 0, STGM_DIRECT  
  277.                 | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pIStream );  
  278.         if (FAILED(hr))  
  279.         {  
  280.             return hr;  
  281.         }  
  282.         if (NULL != pIStream_)  
  283.         {  
  284.             pIStream_->Release();  
  285.         }  
  286.         pIStream_ = pIStream;  
  287.         if (NULL != pIStorage_)  
  288.         {  
  289.             pIStorage_->Release();  
  290.         }  
  291.         pIStorage_ = pIStorage;  
  292.         pIStorage_->AddRef();  
  293.     }  
  294.   
  295.     return NOERROR;  
  296. }  
  297.   
  298. STDMETHODIMP ImpIPersistStorage::HandsOffStorage(void)  
  299. {  
  300.     //Release held pointers  
  301.     if (NULL != pIStream_)  
  302.     {  
  303.         pIStream_->Release();  
  304.         pIStream_ = NULL;  
  305.     }  
  306.     if (NULL != pIStorage_)  
  307.     {  
  308.         pIStorage_->Release();  
  309.         pIStorage_ = NULL;  
  310.     }  
  311.   
  312.     return NOERROR;  
  313. }  
  314.   
  315. int _tmain(int argc, _TCHAR* argv[])  
  316. {  
  317.     ImpIPersistStorage test;  
  318.       
  319.     HRESULT hr;  
  320.     IStorage *pStg = NULL;  // 根存储指针  
  321.     IStorage *pSub = NULL;  // 子存储接口指针  
  322.     IStream  *pStm = NULL;  // 流接口指针  
  323.     ::CoInitialize(NULL);   // COM 初始化  
  324. //  
  325. // test the Save method  
  326. //  
  327. //  hr = ::StgCreateStorageEx(  L"d://Zeng.stg",   
  328. //                              STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, STGFMT_STORAGE,  
  329. //                              0, NULL, NULL, IID_IStorage, (void **)&pStg );  
  330. //   
  331. //  hr = pStg->CreateStorage(                        // 建立子存储  
  332. //                              L"ZengStorage",     // 子存储名称  
  333. //                              STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE,  
  334. //                              0,0,  
  335. //                              &pSub );            // 取得子存储接口指针  
  336. //   
  337. //  assert( SUCCEEDED(hr) );  
  338. //   
  339. //  test.InitNew(pSub);  
  340. //  test.Save(pSub, false);  
  341. //  test.SaveCompleted(pStg);  
  342. //  
  343.   
  344.   
  345. //  
  346. // test the Load method  
  347. //  
  348.     hr = ::StgOpenStorage(  L"d://Zeng.stg", NULL,  
  349.                             STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE | STGFMT_STORAGE,  
  350.                             0, 0, &pStg);  
  351.     assert( SUCCEEDED(hr) );  
  352.   
  353.     hr = pStg->OpenStorage( L"ZengStorage", 0, STGM_READ | STGM_SHARE_EXCLUSIVE | STGFMT_STORAGE,  
  354.                         0, 0, &pSub );  
  355.   
  356. //  hr = pSub->OpenStream(   L"ZengStream", 0,  
  357. //                           STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pStm);  
  358.     assert( SUCCEEDED(hr) );  
  359.   
  360.     test.Load(pSub);  
  361. //  
  362.       
  363.     if( pStm )  pStm->Release(); // 释放流指针  
  364.     if( pSub )  pSub->Release(); // 释放子存储指针  
  365.     if( pStg )  pStg->Release(); // 释放根存储指针  
  366.   
  367.     ::CoUninitialize();             // COM 释放  
  368.   
  369.     return 0;  
  370. }  

 

测试完之后,在我的D盘出现1.bmp和Zeng

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
摘要 StorageTools是OLE 2.0结构化存储技术的关键。 组件列表 StorageTools包含了Windows NT, Windows 2000/XP, Windows 95 & 98平台下的注册数据库控件。此外,还包含了一个简单的资源编译器(提供源代码),以便您采用VB,其他16位或32位COM/ActiveX以及.NET创建您自己使用的.RES文件。 技术特性 StorageTools支持结构化存储的主要特性: ·可以虚拟存储任何数据类型,无须复杂和额外的数据库。 ·使用自持续VB6 类,序列化.NET对象和IIS/ASP .NET应用程序的理想选择。 ·完全支持标准版和定制版文档属性。 ·利用与Microsoft自己的应用程序相同的文件存储系统。 2.5版本的新特性 ·文件属性控件 – 用于读写属于Microsoft Office的文件属性,其他结构化存储文件以及位于Windows 2000NTFS格式下的文件的文件属性。 ·注册控件 – 类似于目前的注册控件,基于DLL的ATL。 ·在StorageTools中支持IPersistStorageIpersistStreamInit接口,补充了现有对IPersistStreamInit的支持。 3.0版本的新特性 支持 .NET ·StorageTools 3.0包括了对.NET的支持,从.NET 程序集访问OLE 结构化存储。 应用场景 适用于各类Windows环境下的结构化数据存储工具 运用优势 开发环境 Microsoft Visual Studio 6.0/.NET Microsoft Visual Basic 3.0/4.0/5.0/6.0/.NET Microsoft Visual C++ /4.0/5.0/6.0/.NET Microsoft Visual C# .NET .NET Common Language Runtime V1.0 支持平台 Win 98/NT/2000/ME/XP 标准报价 2,750 元人民币 * 以上报价仅供参考,具体以厂商正式报价为准。 电话 021-58549800 Email: [email protected] http://www.grapecity.com/china

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值