home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / activexcontrol / basectl / framewrk / ctlpsst.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-05  |  16.4 KB  |  652 lines

  1. //=--------------------------------------------------------------------------=
  2. // CtlPsst.Cpp
  3. //=--------------------------------------------------------------------------=
  4. // Copyright 1995-1997 Microsoft Corporation.  All Rights Reserved.
  5. //
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
  7. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
  8. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
  9. // PARTICULAR PURPOSE.
  10. //=--------------------------------------------------------------------------=
  11. //
  12. // implementation of persistence interfaces for COleControl.
  13. //
  14. #include "IPServer.H"
  15. #include "CtrlObj.H"
  16.  
  17. #include "CtlHelp.H"
  18. #include "Util.H"
  19.  
  20. // this is the name of the stream we'll save our ole controls to.
  21. //
  22. const WCHAR wszCtlSaveStream [] = L"CONTROLSAVESTREAM";
  23.  
  24. // for ASSERT and FAIL
  25. //
  26. SZTHISFILE
  27.  
  28. //=--------------------------------------------------------------------------=
  29. // to help with out stream save implementation ...
  30. //
  31. #define STREAMHDR_SIGNATURE 0x12344321  // Signature to identify our format (avoid crashes!)
  32. #define IPROP_END 0xFF                  // Marker at end of property list
  33. #define MAXAUTOBUF 3800                 // Best if < 1 page.
  34.  
  35. typedef struct tagSTREAMHDR {
  36.  
  37.     DWORD  dwSignature;     // Signature.
  38.     size_t cbWritten;       // Number of bytes written
  39.  
  40. } STREAMHDR;
  41.  
  42. //=--------------------------------------------------------------------------=
  43. // COleControl persistence interfaces
  44. //=--------------------------------------------------------------------------=
  45.  
  46.  
  47. //=--------------------------------------------------------------------------=
  48. // COleControl::Load    [IPersistPropertyBag]
  49. //=--------------------------------------------------------------------------=
  50. // IPersistPropertyBag.  we've got a property bag, so let's load our properties
  51. // from it.
  52. //
  53. // Parameters:
  54. //    IPropertyBag *      - [in] pbag from which to read props.
  55. //    IErrorLog *         - [in] error log to write to
  56. //
  57. // Output:
  58. //    HRESULT
  59. //
  60. // Notes:
  61. //
  62. STDMETHODIMP COleControl::Load
  63. (
  64.     IPropertyBag *pPropertyBag,
  65.     IErrorLog    *pErrorLog
  66. )
  67. {
  68.     HRESULT hr;
  69.  
  70.     // load in our standard state first.  nothing serious here ... currently,
  71.     // we've just got two properties, for cx and cy.
  72.     //
  73.     hr = LoadStandardState(pPropertyBag, pErrorLog);
  74.     RETURN_ON_FAILURE(hr);
  75.  
  76.     // now call the user text load function, and get them to load in whatever
  77.     // they're interested in.
  78.     //
  79.     hr = LoadTextState(pPropertyBag, pErrorLog);
  80.  
  81.     return hr;
  82. }
  83.  
  84. //=--------------------------------------------------------------------------=
  85. // COleControl::Save    [IPersistPropertyBag]
  86. //=--------------------------------------------------------------------------=
  87. // given a property bag, save out all the relevant state information.
  88. //
  89. // Parameters:
  90. //    IPropertyBag *        - [in] property to write to
  91. //    BOOL                  - [in] do we clear the dirty bit?
  92. //    BOOL                  - [in] do we write out default values anyhoo?
  93. //
  94. // Output:
  95. //    HRESULT
  96. //
  97. // Notes:
  98. //
  99. STDMETHODIMP COleControl::Save
  100. (
  101.     IPropertyBag *pPropertyBag,
  102.     BOOL          fClearDirty,
  103.     BOOL          fWriteDefault
  104. )
  105. {
  106.     HRESULT hr;
  107.  
  108.     // save out standard state information
  109.     //
  110.     hr = SaveStandardState(pPropertyBag);
  111.     RETURN_ON_FAILURE(hr);
  112.  
  113.     // now call the user function and get them to save out
  114.     // all of their properties.
  115.     //
  116.     hr = SaveTextState(pPropertyBag, fWriteDefault);
  117.     RETURN_ON_FAILURE(hr);
  118.  
  119.     // now clear the dirty flag and send out notification that we're
  120.     // done.
  121.     //
  122.     if (fClearDirty)
  123.         m_fDirty = FALSE;
  124.  
  125.     if (m_pOleAdviseHolder)
  126.         m_pOleAdviseHolder->SendOnSave();
  127.  
  128.     return S_OK;
  129. }
  130.  
  131. //=--------------------------------------------------------------------------=
  132. // COleControl::GetClassID    [IPersistStreamInit]
  133. //=--------------------------------------------------------------------------=
  134. // returns the classid of this mamma
  135. //
  136. // Parameters:
  137. //    CLSID *         - [out] where to put the clsid
  138. //
  139. // Output:
  140. //    HRESULT
  141. //
  142. // Notes:
  143. //
  144. STDMETHODIMP COleControl::GetClassID
  145. (
  146.     CLSID *pclsid
  147. )
  148. {
  149.     CHECK_POINTER(pclsid);
  150.  
  151.     // copy the thing over
  152.     //
  153.     *pclsid = CLSIDOFOBJECT(m_ObjectType);
  154.     return S_OK;
  155. }
  156.  
  157.  
  158. //=--------------------------------------------------------------------------=
  159. // COleControl::IsDirty    [IPersistStreamInit]
  160. //=--------------------------------------------------------------------------=
  161. // asks if we're dirty or not.  duh.
  162. //
  163. // Output:
  164. //    HRESULT        - S_OK: dirty, S_FALSE: not dirty
  165. //
  166. // Notes:
  167. //
  168. STDMETHODIMP COleControl::IsDirty
  169. (
  170.     void
  171. )
  172. {
  173.     return (m_fDirty) ? S_OK : S_FALSE;
  174. }
  175.  
  176. //=--------------------------------------------------------------------------=
  177. // COleControl::InitNew    [IPersistStreamInit]
  178. //=--------------------------------------------------------------------------=
  179. // causes the control to intialize itself with a new bunch of state information
  180. //
  181. // Output:
  182. //    HRESULT
  183. //
  184. // Notes:
  185. //
  186. STDMETHODIMP COleControl::InitNew
  187. (
  188.     void
  189. )
  190. {
  191.     BOOL f;
  192.  
  193.     // call the overridable function to do this work
  194.     //
  195.     f = InitializeNewState();
  196.     return (f) ? S_OK : E_FAIL;
  197. }
  198.  
  199. //=--------------------------------------------------------------------------=
  200. // COleControl::GetSizeMax    [IPersistStreamInit]
  201. //=--------------------------------------------------------------------------=
  202. //
  203. // Parameters:
  204. //    ULARGE_INTEGER *    - [out]
  205. //
  206. // Output:
  207. //    HRESULT
  208. //
  209. // Notes:
  210. //
  211. STDMETHODIMP COleControl::GetSizeMax
  212. (
  213.     ULARGE_INTEGER *pulMaxSize
  214. )
  215. {
  216.     return E_NOTIMPL;
  217. }
  218.  
  219. //=--------------------------------------------------------------------------=
  220. // COleControl::Load    [IPersistStreamInit]
  221. //=--------------------------------------------------------------------------=
  222. // load from an IStream
  223. //
  224. // Parameters:
  225. //    IStream *    - [in] stream from which to load
  226. //
  227. // Output:
  228. //    HRESULT
  229. //
  230. // Notes:
  231. //
  232. STDMETHODIMP COleControl::Load
  233. (
  234.     IStream *pStream
  235. )
  236. {
  237.     HRESULT hr;
  238.  
  239.     // first thing to do is read in standard properties the user don't
  240.     // persist themselves.
  241.     //
  242.     hr = LoadStandardState(pStream);
  243.     RETURN_ON_FAILURE(hr);
  244.  
  245.     // load in the user properties.  this method is one they -have- to implement
  246.     // themselves.
  247.     //
  248.     hr = LoadBinaryState(pStream);
  249.     
  250.     return hr;
  251. }
  252.  
  253. //=--------------------------------------------------------------------------=
  254. // COleControl::Save    [IPersistStreamInit]
  255. //=--------------------------------------------------------------------------=
  256. // saves out our state using streams
  257. //
  258. // Parameters:
  259. //    IStream *        - [in]
  260. //    BOOL             - [in] clear dirty bit?
  261. //
  262. // Output:
  263. //    HRESULT
  264. //
  265. // Notes:
  266. //
  267. STDMETHODIMP COleControl::Save
  268. (
  269.     IStream *pStream,
  270.     BOOL     fClearDirty
  271. )
  272. {
  273.     HRESULT hr;
  274.  
  275.     // use our helper routine that we share with the IStorage persistence
  276.     // code.
  277.     //
  278.     hr = m_SaveToStream(pStream);
  279.     RETURN_ON_FAILURE(hr);
  280.  
  281.     // clear out dirty flag [if appropriate] and notify that we're done
  282.     // with save.
  283.     //
  284.     if (fClearDirty)
  285.         m_fDirty = FALSE;
  286.     if (m_pOleAdviseHolder)
  287.         m_pOleAdviseHolder->SendOnSave();
  288.  
  289.     return S_OK;
  290. }
  291.  
  292. //=--------------------------------------------------------------------------=
  293. // COleControl::InitNew    [IPersistStorage]
  294. //=--------------------------------------------------------------------------=
  295. // ipersiststorage version of this.  fweee
  296. //
  297. // Parameters:
  298. //    IStorage *    - [in] we don't use this
  299. //
  300. // Output:
  301. //    HRESULT
  302. //
  303. // Notes:
  304. //
  305. STDMETHODIMP COleControl::InitNew
  306. (
  307.     IStorage *pStorage
  308. )
  309. {
  310.     // we already have an implementation of this [for IPersistStreamInit]
  311.     //
  312.     return InitNew();
  313. }
  314.  
  315. //=--------------------------------------------------------------------------=
  316. // COleControl::Load    [IPersistStorage]
  317. //=--------------------------------------------------------------------------=
  318. // Ipersiststorage version of this
  319. //
  320. // Parameters:
  321. //    IStorage *    - [in] DUH.
  322. //
  323. // Output:
  324. //    HRESULT
  325. //
  326. // Notes:
  327. //
  328. STDMETHODIMP COleControl::Load(IStorage *pStorage)
  329. {
  330.     IStream *pStream;
  331.     HRESULT  hr;
  332.  
  333.     // we're going to use IPersistStream::Load from the CONTENTS stream.
  334.     //
  335.     hr = pStorage->OpenStream(wszCtlSaveStream, 0, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pStream);
  336.     RETURN_ON_FAILURE(hr);
  337.  
  338.     // IPersistStreamInit::Load
  339.     //
  340.     hr = Load(pStream);
  341.     pStream->Release();
  342.     return hr;
  343. }
  344.  
  345. //=--------------------------------------------------------------------------=
  346. // COleControl::Save    [IPersistStorage]
  347. //=--------------------------------------------------------------------------=
  348. // save into the contents stream of the given storage object.
  349. //
  350. // Parameters:
  351. //    IStorage *        - [in] 10 points if you figure it out
  352. //    BOOL              - [in] is the storage the same as the load storage?
  353. //
  354. // Output:
  355. //    HRESULT
  356. //
  357. // Notes:
  358. //
  359. STDMETHODIMP COleControl::Save
  360. (
  361.     IStorage *pStorage,
  362.     BOOL      fSameAsLoad
  363. )
  364. {
  365.     IStream *pStream;
  366.     HRESULT  hr;
  367.  
  368.     // we're just going to save out to the CONTENTES stream.
  369.     //
  370.     hr = pStorage->CreateStream(wszCtlSaveStream, STGM_WRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE,
  371.                                 0, 0, &pStream);
  372.     RETURN_ON_FAILURE(hr);
  373.  
  374.     // use our helper routine.
  375.     //
  376.     hr = m_SaveToStream(pStream);
  377.     m_fSaveSucceeded = (FAILED(hr)) ? FALSE : TRUE;
  378.     pStream->Release();
  379.     return hr;
  380. }
  381.  
  382. //=--------------------------------------------------------------------------=
  383. // COleControl::SaveCompleted    [IPersistStorage]
  384. //=--------------------------------------------------------------------------=
  385. // lets us clear out our flags.
  386. //
  387. // Parameters:
  388. //    IStorage *    - ignored
  389. //
  390. // Output:
  391. //    HRESULT
  392. //
  393. // Notes:
  394. //
  395. STDMETHODIMP COleControl::SaveCompleted
  396. (
  397.     IStorage *pStorageNew
  398. )
  399. {
  400.     // if our save succeeded, then we can do our post save work.
  401.     //
  402.     if (m_fSaveSucceeded) {
  403.         m_fDirty = FALSE;
  404.         if (m_pOleAdviseHolder)
  405.             m_pOleAdviseHolder->SendOnSave();
  406.     }
  407.  
  408.     return S_OK;
  409. }
  410.  
  411. //=--------------------------------------------------------------------------=
  412. // COleControl::HandsOffStorage    [IPersistStorage]
  413. //=--------------------------------------------------------------------------=
  414. // not interesting
  415. //
  416. // Output:
  417. //    S_OK
  418. //
  419. // Notes:
  420. //
  421. STDMETHODIMP COleControl::HandsOffStorage
  422. (
  423.     void
  424. )
  425. {
  426.     // we don't ever hold on to  a storage pointer, so this is remarkably
  427.     // uninteresting to us.
  428.     //
  429.     return S_OK;
  430. }
  431.  
  432. //=--------------------------------------------------------------------------=
  433. // COleControl::m_SaveToStream    [helper: IPersistStreamInit/IPersistStorage]
  434. //=--------------------------------------------------------------------------=
  435. // save ourselves to a stream
  436. //
  437. // Parameters:
  438. //    IStream *        - figure it out
  439. //
  440. // Output:
  441. //    HRESULT
  442. //
  443. // Notes:
  444. //
  445. HRESULT COleControl::m_SaveToStream
  446. (
  447.     IStream *pStream
  448. )
  449. {
  450.     HRESULT hr;
  451.  
  452.     // save out standard state information that the user has no control
  453.     // over
  454.     //
  455.     hr = SaveStandardState(pStream);
  456.     RETURN_ON_FAILURE(hr);
  457.  
  458.     // save out user-specific satte information.  they MUST implement this
  459.     // function
  460.     //
  461.     hr = SaveBinaryState(pStream);
  462.  
  463.     return hr;
  464. }
  465.  
  466. //=--------------------------------------------------------------------------=
  467. // COleControl::LoadStandardState    [ helper ]
  468. //=--------------------------------------------------------------------------=
  469. // reads in standard properties that all controls are going to have, using
  470. // text persistence APIs.  there is another version for streams.
  471. //
  472. // Parameters:
  473. //    IPropertyBag *    - [in]
  474. //    IErrorLog *       - [in]
  475. //
  476. // Output:
  477. //    HRESULT
  478. //
  479. // Notes:
  480. //
  481. HRESULT COleControl::LoadStandardState
  482. (
  483.     IPropertyBag *pPropertyBag,
  484.     IErrorLog    *pErrorLog
  485. )
  486. {
  487.     VARIANT v;
  488.     HRESULT hr;
  489.     SIZEL   slHiMetric = { 100, 50 };
  490.  
  491.     // currently, our only standard properties are related to size.
  492.     // if we can't find them, then we'll just use some defaults.
  493.     //
  494.     v.vt = VT_I4;
  495.     v.lVal = 0;
  496.     hr = pPropertyBag->Read(L"_ExtentX", &v, pErrorLog);
  497.     if (SUCCEEDED(hr)) slHiMetric.cx = v.lVal;
  498.  
  499.     v.lVal = 0;
  500.     hr = pPropertyBag->Read(L"_ExtentY", &v, pErrorLog);
  501.     if (SUCCEEDED(hr)) slHiMetric.cy = v.lVal;
  502.  
  503.     HiMetricToPixel(&slHiMetric, &m_Size);
  504.     return S_OK;
  505. }
  506.  
  507. //=--------------------------------------------------------------------------=
  508. // COleControl::LoadStandardState    [ helper ]
  509. //=--------------------------------------------------------------------------=
  510. // reads in standard properties that all controls are going to have, using
  511. // stream persistence APIs.  there is another version for text.
  512. //
  513. // Parameters:
  514. //    IStream *         - [in] 
  515. //
  516. // Output:
  517. //    HRESULT
  518. //
  519. // Notes:
  520. //
  521. HRESULT COleControl::LoadStandardState
  522. (
  523.     IStream *pStream
  524. )
  525. {
  526.     STREAMHDR stmhdr;
  527.     HRESULT hr;
  528.     SIZEL   slHiMetric;
  529.  
  530.     // look for our header structure, so we can verify stream validity.
  531.     //
  532.     hr = pStream->Read(&stmhdr, sizeof(STREAMHDR), NULL);
  533.     RETURN_ON_FAILURE(hr);
  534.  
  535.     if (stmhdr.dwSignature != STREAMHDR_SIGNATURE)
  536.         return E_UNEXPECTED;
  537.  
  538.     // currently, the only standard state we're writing out is
  539.     // a SIZEL structure describing the control's size.
  540.     //
  541.     if (stmhdr.cbWritten != sizeof(m_Size))
  542.         return E_UNEXPECTED;
  543.  
  544.     // we like the stream.  let's go load in our two properties.
  545.     //
  546.     hr = pStream->Read(&slHiMetric, sizeof(slHiMetric), NULL);
  547.     RETURN_ON_FAILURE(hr);
  548.  
  549.     HiMetricToPixel(&slHiMetric, &m_Size);
  550.     return S_OK;
  551. }
  552.  
  553. //=--------------------------------------------------------------------------=
  554. // COleControl::SaveStandardState    [ helper ]
  555. //=--------------------------------------------------------------------------=
  556. // saves out standard properties that we're managing for a control using text
  557. // persistence APIs.  there is another version for stream persistence.
  558. //
  559. // Parameters:
  560. //    IPropertyBag *        - [in]
  561. //
  562. // Output:
  563. //    HRESULT
  564. //
  565. // Notes:
  566. //
  567. HRESULT COleControl::SaveStandardState
  568. (
  569.     IPropertyBag *pPropertyBag
  570. )
  571. {
  572.     HRESULT hr;
  573.     VARIANT v;
  574.     SIZEL   slHiMetric;
  575.  
  576.     // currently, the only standard proprerties we persist are Size related
  577.     //
  578.     PixelToHiMetric(&m_Size, &slHiMetric);
  579.  
  580.     v.vt = VT_I4;
  581.     v.lVal = slHiMetric.cx;
  582.  
  583.     hr = pPropertyBag->Write(L"_ExtentX", &v);
  584.     RETURN_ON_FAILURE(hr);
  585.  
  586.     v.lVal = slHiMetric.cy;
  587.  
  588.     hr = pPropertyBag->Write(L"_ExtentY", &v);
  589.  
  590.     return hr;
  591. }
  592.  
  593. //=--------------------------------------------------------------------------=
  594. // COleControl::SaveStandardState    [ helper ]
  595. //=--------------------------------------------------------------------------=
  596. // saves out standard properties that we're managing for a control using stream
  597. // persistence APIs.  there is another version for text persistence.
  598. //
  599. // Parameters:
  600. //    IStream *            - [in]
  601. //
  602. // Output:
  603. //    HRESULT
  604. //
  605. // Notes:
  606. //
  607. HRESULT COleControl::SaveStandardState
  608. (
  609.     IStream *pStream
  610. )
  611. {
  612.     STREAMHDR streamhdr = { STREAMHDR_SIGNATURE, sizeof(SIZEL) };
  613.     HRESULT hr;
  614.     SIZEL   slHiMetric;
  615.  
  616.  
  617.     // first thing to do is write out our stream hdr structure.
  618.     //
  619.     hr = pStream->Write(&streamhdr, sizeof(STREAMHDR), NULL);
  620.     RETURN_ON_FAILURE(hr);
  621.  
  622.     // the only properties we're currently persisting here are the size
  623.     // properties for this control.  make sure we do that in HiMetric
  624.     //
  625.     PixelToHiMetric(&m_Size, &slHiMetric);
  626.  
  627.     hr = pStream->Write(&slHiMetric, sizeof(slHiMetric), NULL);
  628.     return hr;
  629. }
  630.  
  631. //=--------------------------------------------------------------------------=
  632. // COleControl::InitializeNewState    [overridable]
  633. //=--------------------------------------------------------------------------=
  634. // the user can override this to initialize variables
  635. //
  636. // Output:
  637. //    BOOL        - FALSE means couldn't do it.
  638. //
  639. // Notes:
  640. //
  641. BOOL COleControl::InitializeNewState
  642. (
  643.     void
  644. )
  645. {
  646.     // we find this largely uninteresting
  647.     //
  648.     return TRUE;
  649. }
  650.  
  651.  
  652.