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 / webimage / wimgctl.cpp < prev    next >
C/C++ Source or Header  |  1997-10-09  |  21KB  |  852 lines

  1. //=--------------------------------------------------------------------------=
  2. // WImgCtl.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. //
  13. //
  14. #include "IPServer.H"
  15.  
  16. #include "Guids.H"
  17. #include "LocalObj.H"
  18. #include "Util.H"
  19. #include "Globals.H"
  20. #include "Resource.H"
  21. #include "Wimgctl.H"
  22.  
  23. // for ASSERT and FAIL
  24. //
  25. SZTHISFILE
  26.  
  27. WCHAR wszImage [] = L"Image";
  28.  
  29.  
  30.  
  31.  
  32. //=--------------------------------------------------------------------------=
  33. // all the events in this control
  34. //
  35. // TODO: add events here ...
  36. //
  37.  
  38. //=--------------------------------------------------------------------------=
  39. // array describing all of our property pages.  these clsids are typically
  40. // in guids.h
  41. //
  42. // TODO: add any additional property page guids here ...
  43. //
  44. const GUID *rgWebImagePropPages [] = {
  45.     &CLSID_WebImageGeneralPage
  46. };
  47.  
  48. //=--------------------------------------------------------------------------=
  49. // Custum Verb information
  50. //
  51. // TODO: add any custom verbs here in an array, using the VERBINFO structure.
  52. //       then mark the controld def'n in WebImageCtl.H with
  53. //       this verb array
  54. //
  55.  
  56.  
  57. //=--------------------------------------------------------------------------=
  58. // CWebImageControl::Create
  59. //=--------------------------------------------------------------------------=
  60. // global static function that creates an instance of the control an returns
  61. // an IUnknown pointer for it.
  62. //
  63. // Parameters:
  64. //    IUnknown *        - [in] controlling unknown for aggregation
  65. //
  66. // Output:
  67. //    IUnknown *        - new object.
  68. //
  69. // Notes:
  70. //
  71. IUnknown *CWebImageControl::Create
  72. (
  73.     IUnknown *pUnkOuter
  74. )
  75. {
  76.     // make sure we return the private unknown so that we support aggegation
  77.     // correctly!
  78.     //
  79.     CWebImageControl *pNew = new CWebImageControl(pUnkOuter);
  80.     return pNew->PrivateUnknown();
  81. }
  82.  
  83. //=--------------------------------------------------------------------------=
  84. // CWebImageControl::CWebImageControl
  85. //=--------------------------------------------------------------------------=
  86. // "Being born is like being kidnapped.  And then sold into slavery."
  87. //    - andy warhol (1928 - 87)
  88. //
  89. // Parameters:
  90. //    IUnknown *        - [in]
  91. //
  92. // Notes:
  93. //
  94. #pragma warning(disable:4355)  // using 'this' in constructor
  95. CWebImageControl::CWebImageControl
  96. (
  97.     IUnknown *pUnkOuter
  98. )
  99. : CInternetControl(pUnkOuter, OBJECT_TYPE_CTLWEBIMAGE, (IDispatch *)this)
  100. {
  101.     m_bmpPath = 0;
  102.     m_dib = 0;
  103.     m_dibFile = 0;
  104.     m_state    = bdsNoBitsYet;
  105.  
  106. }
  107. #pragma warning(default:4355)  // using 'this' in constructor
  108.  
  109. //=--------------------------------------------------------------------------=
  110. // CWebImageControl::~CWebImageControl
  111. //=--------------------------------------------------------------------------=
  112. // "We all labour against our own cure, for death is the cure of all diseases"
  113. //    - Sir Thomas Browne (1605 - 82)
  114. //
  115. // Notes:
  116. //
  117. CWebImageControl::~CWebImageControl ()
  118. {
  119.     if(m_bmpPath)
  120.         delete [] m_bmpPath;
  121.     if( m_dibFile )
  122.         delete m_dibFile;
  123.     if( m_dib )
  124.         delete m_dib;
  125. }
  126.  
  127. //=--------------------------------------------------------------------------=
  128. // CWebImageControl:RegisterClassData
  129. //=--------------------------------------------------------------------------=
  130. // register the window class information for your control here.
  131. // this information will automatically get cleaned up for you on DLL shutdown.
  132. //
  133. // Output:
  134. //    BOOL            - FALSE means fatal error.
  135. //
  136. // Notes:
  137. //
  138. BOOL CWebImageControl::RegisterClassData()
  139. {
  140.     WNDCLASS wndclass;
  141.  
  142.     // TODO: register any additional information you find interesting here.
  143.     //       this method is only called once for each type of control
  144.     //
  145.     memset(&wndclass, 0, sizeof(WNDCLASS));
  146.     wndclass.style          = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS | CS_OWNDC;
  147.     wndclass.lpfnWndProc    = COleControl::ControlWindowProc;
  148.     wndclass.hInstance      = g_hInstance;
  149.     wndclass.hCursor        = LoadCursor(NULL, IDC_ARROW);
  150.     wndclass.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);
  151.     wndclass.lpszClassName  = WNDCLASSNAMEOFCONTROL(OBJECT_TYPE_CTLWEBIMAGE);
  152.  
  153.     return RegisterClass(&wndclass);
  154. }
  155.  
  156. //=--------------------------------------------------------------------------=
  157. // CWebImageControl::BeforeCreateWindow
  158. //=--------------------------------------------------------------------------=
  159. // called just before the window is created.  Great place to set up the
  160. // window title, etc, so that they're passed in to the call to CreateWindowEx.
  161. // speeds things up slightly.
  162. //
  163. // Notes:
  164. //
  165. void CWebImageControl::BeforeCreateWindow()
  166. {
  167. }
  168.  
  169. BOOL CWebImageControl::AfterCreateWindow()
  170. {
  171.     m_dc = ::GetDC(m_hwnd);
  172.     HPALETTE hpal = ::CreateHalftonePalette(m_dc);
  173.     ::SelectPalette(m_dc, hpal, FALSE);
  174.  
  175.         UpdateImage();
  176.         return TRUE;
  177. }
  178.  
  179. //=--------------------------------------------------------------------------=
  180. // CWebImageControl::InternalQueryInterface
  181. //=--------------------------------------------------------------------------=
  182. // qi for things only we support.
  183. //
  184. // Parameters:
  185. // Parameters:
  186. //    REFIID        - [in]  interface they want
  187. //    void **       - [out] where they want to put the resulting object ptr.
  188. //
  189. // Output:
  190. //    HRESULT       - S_OK, E_NOINTERFACE
  191. //
  192. // Notes:
  193. //
  194. HRESULT CWebImageControl::InternalQueryInterface
  195. (
  196.     REFIID  riid,
  197.     void  **ppvObjOut
  198. )
  199. {
  200.     IUnknown *pUnk;
  201.  
  202.     *ppvObjOut = NULL;
  203.  
  204.     // TODO: if you want to support any additional interrfaces, then you should
  205.     // indicate that here.  never forget to call COleControl's version in the
  206.     // case where you don't support the given interface.
  207.     //
  208.     if (DO_GUIDS_MATCH(riid, IID_IWebImage)) {
  209.         pUnk = (IUnknown *)(IWebImage *)this;
  210.     } else{
  211.         return COleControl::InternalQueryInterface(riid, ppvObjOut);
  212.     }
  213.  
  214.     pUnk->AddRef();
  215.     *ppvObjOut = (void *)pUnk;
  216.     return S_OK;
  217. }
  218.  
  219. //=--------------------------------------------------------------------------=
  220. // CWebImageControl::LoadTextState
  221. //=--------------------------------------------------------------------------=
  222. // load in our text state for this control.
  223. //
  224. // Parameters:
  225. //    IPropertyBag *        - [in] property bag to read from
  226. //    IErrorLog *           - [in] errorlog object to use with proeprty bag
  227. //
  228. // Output:
  229. //    HRESULT
  230. //
  231. // Notes:
  232. //    - NOTE: if you have a binary object, then you should pass an unknown
  233. //      pointer to the property bag, and it will QI it for IPersistStream, and
  234. //      get said object to do a Load()
  235. //
  236. STDMETHODIMP CWebImageControl::LoadTextState
  237. (
  238.     IPropertyBag *pPropertyBag,
  239.     IErrorLog    *pErrorLog
  240. )
  241. {
  242.     VARIANT v;
  243.  
  244.     VariantInit(&v);
  245.  
  246.     v.vt = VT_BSTR;
  247.     v.bstrVal = NULL;
  248.  
  249.     HRESULT hr = S_OK;
  250.     // try to load in the property.  if we can't get it, then leave
  251.     // things at their default.
  252.     //
  253.     pPropertyBag->Read(::wszImage, &v, pErrorLog);
  254.     if (v.bstrVal) {
  255.         MAKE_ANSIPTR_FROMWIDE(psz, v.bstrVal);
  256.         hr = SetBmpPath(psz);
  257.         VariantClear(&v);
  258.     }
  259.  
  260.     return hr;
  261. }
  262.  
  263. //=--------------------------------------------------------------------------=
  264. // CWebImageControl::LoadBinaryState
  265. //=--------------------------------------------------------------------------=
  266. // loads in our binary state using streams.
  267. //
  268. // Parameters:
  269. //    IStream *            - [in] stream to write to.
  270. //
  271. // Output:
  272. //    HRESULT
  273. //
  274. // Notes:
  275. //
  276. const DWORD STREAMHDR_MAGIC = 12345678L;
  277.  
  278. STDMETHODIMP CWebImageControl::LoadBinaryState
  279. (
  280.     IStream *pStream
  281. )
  282. {
  283.     DWORD        sh;
  284.     HRESULT        hr;
  285.  
  286.     // first read in the streamhdr, and make sure we like what we're getting
  287.     //
  288.     hr = pStream->Read(&sh, sizeof(sh), NULL);
  289.     RETURN_ON_FAILURE(hr);
  290.  
  291.     // sanity check
  292.     //
  293.     if (sh != STREAMHDR_MAGIC )
  294.         return E_UNEXPECTED;
  295.  
  296.     return(SetBmpPath(pStream));
  297. }
  298.  
  299. //=--------------------------------------------------------------------------=
  300. // CWebImageControl::SaveTextState
  301. //=--------------------------------------------------------------------------=
  302. // saves out the text state for this control using a property bag.
  303. //
  304. // Parameters:
  305. //    IPropertyBag *        - [in] the property bag with which to work.
  306. //    BOOL                  - [in] if TRUE, then write out ALL properties, even
  307. //                            if they're their the default value ...
  308. //
  309. // Output:
  310. //    HRESULT
  311. //
  312. // Notes:
  313. //
  314. STDMETHODIMP CWebImageControl::SaveTextState
  315. (
  316.     IPropertyBag *pPropertyBag,
  317.     BOOL          fWriteDefaults
  318. )
  319. {
  320.     HRESULT hr;
  321.     VARIANT v;
  322.  
  323.     v.vt = VT_BSTR;
  324.     v.bstrVal = BSTRFROMANSI(m_bmpPath);
  325.     RETURN_ON_NULLALLOC(v.bstrVal);
  326.  
  327.     // this control currently only persists out the caption property
  328.     //
  329.     hr = pPropertyBag->Write(::wszImage, &v);
  330.     VariantClear(&v);
  331.     return hr;}
  332.  
  333. //=--------------------------------------------------------------------------=
  334. // CWebImageControl::SaveBinaryState
  335. //=--------------------------------------------------------------------------=
  336. // save out the binary state for this control, using the given IStream object.
  337. //
  338. // Parameters:
  339. //    IStream  *             - [in] save to which you should save.
  340. //
  341. // Output:
  342. //    HRESULT
  343. //
  344. // Notes:
  345. //    - it is important that you seek to the end of where you saved your
  346. //      properties when you're done with the IStream.
  347. //
  348. STDMETHODIMP CWebImageControl::SaveBinaryState
  349. (
  350.     IStream *pStream
  351. )
  352. {
  353.     DWORD sh = STREAMHDR_MAGIC;
  354.     HRESULT hr;
  355.  
  356.     // write out the stream hdr.
  357.     //
  358.     hr = pStream->Write(&sh, sizeof(sh), NULL);
  359.     RETURN_ON_FAILURE(hr);
  360.  
  361.     // write out he control state information
  362.     //
  363.  
  364.     DWORD dw = m_bmpPath ? lstrlen(m_bmpPath) : 0;
  365.  
  366.     hr = pStream->Write(&dw,sizeof(dw),0);
  367.     RETURN_ON_FAILURE(hr);
  368.  
  369.     if( dw )
  370.         hr = pStream->Write(m_bmpPath,dw+1,0);
  371.  
  372.     return hr;
  373. }
  374.  
  375.  
  376. //=--------------------------------------------------------------------------=
  377. // CWebImageControl::OnDraw
  378. //=--------------------------------------------------------------------------=
  379. // "I don't very much enjoy looking at paintings in general.  i know too
  380. //  much about them.  i take them apart."
  381. //    - georgia o'keeffe (1887-1986)
  382. //
  383. // Parameters:
  384. //    DWORD              - [in]  drawing aspect
  385. //    HDC                - [in]  HDC to draw to
  386. //    LPCRECTL           - [in]  rect we're drawing to
  387. //    LPCRECTL           - [in]  window extent and origin for meta-files
  388. //    HDC                - [in]  HIC for target device
  389. //    BOOL               - [in]  can we optimize dc handling?
  390. //
  391. // Output:
  392. //    HRESULT
  393. //
  394. // Notes:
  395. //
  396. HRESULT CWebImageControl::OnDraw
  397. (
  398.     DWORD    dvAspect,
  399.     HDC      hdcDraw,
  400.     LPCRECTL prcBounds,
  401.     LPCRECTL prcWBounds,
  402.     HDC      hicTargetDevice,
  403.     BOOL     fOptimize
  404. )
  405. {
  406.     if(m_dib) 
  407.     {
  408.         if (prcWBounds != NULL) //printing
  409.         {
  410.             SetMapMode(hdcDraw,MM_TEXT);
  411.             HBITMAP hBitmap;
  412.                 //printing DIB
  413.             hBitmap = (HBITMAP) HANDLE(*m_dib);
  414.             DIBSECTION ds;
  415.             GetObject(hBitmap,sizeof(DIBSECTION),(LPSTR)&ds);
  416.             StretchDIBits(hdcDraw,prcBounds->left,prcBounds->top,prcBounds->right - prcBounds->left,
  417.                 prcBounds->bottom - prcBounds->top,0,0,
  418.                 ds.dsBm.bmWidth, ds.dsBm.bmHeight,
  419.                 ds.dsBm.bmBits, 
  420.                 (BITMAPINFO *)(*m_dibFile), 
  421.                 DIB_RGB_COLORS,
  422.                 SRCCOPY);
  423.             return S_OK;
  424.         }
  425.  
  426.         if( hdcDraw != m_dc )
  427.         {
  428.             HPALETTE hpal = ::CreateHalftonePalette(hdcDraw);
  429.             ::SelectPalette(hdcDraw, hpal, FALSE);
  430.         }
  431.  
  432.         ::RealizePalette(hdcDraw);
  433.  
  434.         m_dib->PaintTo(hdcDraw,prcBounds->left,prcBounds->top);
  435.  
  436.     }
  437.     return S_OK;
  438. }
  439.  
  440. //=--------------------------------------------------------------------------=
  441. // CWebImageControl::OnProgress
  442. //=--------------------------------------------------------------------------=
  443. //
  444. // Parameters:
  445. //    DISPID    propId        - [in]  Same dispId that was passed into SetupDownload
  446. //    ULONG        progress    - [in]  Size downlaoded so far
  447. //    ULONG     themax        - [in]  Overall size of object being downloaded
  448. //    ULONG        statusFlag    - [in]  Flags according 
  449. //    LPCWSTR   statusStr    - [in]    Readable version of status
  450. //
  451. // Notes:
  452. //
  453. HRESULT CWebImageControl::OnProgress
  454. (
  455.     DISPID    propId, 
  456.     ULONG    progress, 
  457.     ULONG    themax, 
  458.     ULONG    statusFlag,
  459.     LPCWSTR    statusString
  460. )
  461. {
  462.     // TODO: put custom progress UI notification code here. The default action
  463.     //    (shown below) is to fire an OnProgress event to the host
  464.  
  465.     return(FireProgress(themax ? (progress * 100)/themax : 0));
  466. }
  467.  
  468.  
  469. //=--------------------------------------------------------------------------=
  470. // CWebImageControl::WindowProc
  471. //=--------------------------------------------------------------------------=
  472. // window procedure for this control.  nothing terribly exciting.
  473. //
  474. // Parameters:
  475. //     see win32sdk on window procs.
  476. //
  477. // Notes:
  478. //
  479. LRESULT CWebImageControl::WindowProc
  480. (
  481.     UINT   msg,
  482.     WPARAM wParam,
  483.     LPARAM lParam
  484. )
  485. {
  486.     // TODO: handle any messages here, like in a normal window
  487.     // proc.  note that for special keys, you'll want to override and
  488.     // implement OnSpecialKey.
  489.     //
  490.     return OcxDefWindowProc(msg, wParam, lParam);
  491. }
  492.  
  493. //=--------------------------------------------------------------------------=
  494. // CWebImageControl::AboutBox
  495. //=--------------------------------------------------------------------------=
  496. // prints up an about box.  fweeeee.
  497. //
  498. // Notes:
  499. //
  500. void CWebImageControl::AboutBox
  501. (
  502.     void
  503. )
  504. {
  505.     // TODO: Ideally, one would use DialogBox, and some sort of Dialog Box here if
  506.     // they wanted a slightly more interesting About Box ...  you should
  507.     // still call ModalDialog first, however.
  508.     //
  509.     ModalDialog(TRUE);
  510.     MessageBox(NULL, "This is My Control", "About WebImage", MB_OK | MB_TASKMODAL);
  511.     ModalDialog(FALSE);
  512. }
  513.  
  514. STDMETHODIMP  CWebImageControl::get_Image(BSTR * path)
  515. {
  516.     CHECK_POINTER(path);
  517.  
  518.     // Actually we need to be accepting (happily IMoniker objects)
  519.  
  520. //    path->vt = VT_BSTR;
  521.         
  522.     BSTR * pbstrPath = path; //&path->bstrVal;
  523.     
  524.     *pbstrPath = (m_bmpPath && *m_bmpPath) ? BSTRFROMANSI(m_bmpPath) : SysAllocString(L"");
  525.  
  526.     return (*pbstrPath) ? S_OK : E_OUTOFMEMORY;
  527. }
  528.  
  529. STDMETHODIMP  CWebImageControl::put_Image(BSTR path)
  530. {
  531.     // NOTE: We should reference and IMoniker*!!
  532.  
  533. //    if( path.vt != VT_BSTR )
  534. //        return(E_UNEXPECTED);
  535.  
  536.     BSTR & bstrPath = path; //.bstrVal;
  537.     // get an ANSI pointer, so we can stuff it in our local buffer for captions!
  538.     //
  539.  
  540.     MAKE_ANSIPTR_FROMWIDE(pszPath, bstrPath);
  541.  
  542.     HRESULT hr = SetBmpPath(pszPath);
  543.  
  544.     // update anybody who cares about property changes and mark ourselves
  545.     // as dirty
  546.     //
  547.     PropertyChanged(DISPID_BMPPATH);
  548.     m_fDirty = TRUE;
  549.  
  550.     return hr;
  551. }
  552.  
  553. STDMETHODIMP  CWebImageControl::Scramble()
  554. {
  555.     HRESULT hr;
  556.  
  557.         if (m_dib)
  558.     {
  559.         unsigned char * p = m_dib->Base();
  560.         DWORD            dw = m_dib->ImageSize();
  561.  
  562.         for( DWORD i = 0; i < dw; i+=3,p+=3 )
  563.             *p ^= 0x55;
  564.  
  565.         InvalidateControl(0);
  566.  
  567.         hr = S_OK;
  568.     }
  569.     else
  570.     {
  571.         hr = E_FAIL; // E_PENDING;
  572.     }
  573.  
  574.  
  575.     return(hr);
  576. }
  577.  
  578. HRESULT CWebImageControl::SetBmpPath(const char *psz)
  579. {
  580.     // if it hasn't changed, don't waste any time.
  581.     //
  582.     if (psz && m_bmpPath )
  583.     {
  584.         CHECK_POINTER(psz);
  585.         if( !lstrcmp(m_bmpPath, psz) )
  586.             return S_OK;
  587.     }
  588.  
  589.     if( m_bmpPath )
  590.         delete [] m_bmpPath;
  591.  
  592.     if(!psz)
  593.     {
  594.         m_bmpPath = 0;
  595.         return(S_OK);
  596.     }
  597.  
  598.     CHECK_POINTER(psz);
  599.  
  600.     if( !*psz )
  601.     {
  602.         m_bmpPath = 0;
  603.         return(S_OK);
  604.     }
  605.  
  606.     DWORD dw = lstrlen(psz);
  607.  
  608.     m_bmpPath = new char[dw + 1];
  609.  
  610.     if( !m_bmpPath )
  611.     {
  612.         FAIL("No memory");
  613.         return(E_OUTOFMEMORY);
  614.     }
  615.  
  616.     lstrcpy(m_bmpPath, psz);
  617.  
  618.         UpdateImage();
  619.  
  620.     return(S_OK);
  621. }
  622.  
  623. HRESULT CWebImageControl::SetBmpPath(IStream * strm)
  624. {
  625.     CHECK_POINTER(strm);
  626.  
  627.     char * tmp = 0;
  628.  
  629.     if( m_bmpPath )
  630.         delete [] m_bmpPath;
  631.  
  632.     DWORD    dw;
  633.     HRESULT hr = strm->Read(&dw,sizeof(dw),0);
  634.  
  635.     if( SUCCEEDED(hr) )
  636.     {
  637.         if( !dw )
  638.         {
  639.             hr = S_OK;
  640.         }
  641.         else
  642.         {
  643.             tmp = new char[dw+1];
  644.  
  645.             if( !tmp )
  646.             {
  647.                 FAIL("No memory");
  648.                 hr = E_OUTOFMEMORY;
  649.             }
  650.             else
  651.             {
  652.                 hr = strm->Read(tmp,dw+1,0);
  653.             }
  654.         }
  655.     }
  656.  
  657.     // if it hasn't changed, don't waste any time.
  658.     //
  659.     if ((!tmp && !m_bmpPath) || !lstrcmp(m_bmpPath, tmp))
  660.         return S_OK;
  661.  
  662.     if( m_bmpPath )
  663.         delete [] m_bmpPath;
  664.  
  665.     m_bmpPath = tmp;
  666.  
  667.         UpdateImage();
  668.  
  669.     return(hr);
  670. }
  671.  
  672. HRESULT CWebImageControl::UpdateImage()
  673. {
  674.     if( !m_hwnd )
  675.         return(S_OK);
  676.  
  677.     if( !m_bmpPath )
  678.         return(S_OK);
  679.  
  680.     return( SetupDownload(OLESTRFROMANSI(m_bmpPath),DISPID_BMPPATH) );
  681. }
  682.  
  683.  
  684. //=--------------------------------------------------------------------------=
  685. // CWebImageControl::OnData
  686. //=--------------------------------------------------------------------------=
  687. //
  688. // Parameters:
  689. //    DISPID    propId        - [in]  Same dispId that was passed into SetupDownload
  690. //    DWORD        grfBSCF        - [in]  Notification flags ("URL Moniker" specification)
  691. //    IStream *    strm        - [in]  Stream to read data from
  692. //    DWORD        dwSize        - [in]  Overall size available so far
  693. //
  694. //
  695. //    Notes:    This is the class that is monitering and interpreting the bits that
  696. //    are being downloaded. The methods in class inherited from IBindStatusCallback
  697. //    are only called during 'DispatchMessage' calls from the main applications loop.
  698. //    This impelmentation maintains a state machine for the bits as they arrive:
  699. //
  700. //        Initial state:            No bits have been seen yet
  701. //
  702. //              Have BITMAPFILEHEADER   We now have this structure. At this point there is
  703. //                                enough information to calculate the following values:
  704. //                                    - The file is actually a Windows BMP file
  705. //                                    - The size of the entire image
  706. //                                    - This size of the BITMAPINFO structure
  707. //
  708. //        Have BITMAPINFO            We now have enough information to call 
  709. //                                CreateDibSection! That function will return a 
  710. //                                a buffer it allocated.
  711. //
  712. //        Getting BITS            At this point the bits are arriving and all we 
  713. //                                have to do is strm->Read the bits directly into
  714. //                                buffer returned from the step above and notify
  715. //                                our view sink that we need refreshing.
  716. //
  717. //        BITS are done            (nothing to do!?)
  718. //
  719. HRESULT CWebImageControl::OnData
  720. (
  721.     DISPID        propId,
  722.     DWORD        grfBSCF,
  723.     IStream *    strm,
  724.     DWORD        dwSize
  725. )
  726. {
  727.     HRESULT        hr        = NOERROR;
  728.  
  729.     switch(m_state)
  730.     {
  731.         case bdsNoBitsYet:
  732.             {
  733.                 if( dwSize >= sizeof(BITMAPFILEHEADER) )
  734.                 {
  735.                     CHECK_POINTER(strm);
  736.                     strm->AddRef();
  737.  
  738.                     if( m_dibFile )
  739.                         delete m_dibFile;
  740.  
  741.                     m_dibFile = new CDibFile;
  742.  
  743.                     if( !m_dibFile )
  744.                     {
  745.                         hr = E_OUTOFMEMORY;
  746.                         break;
  747.                     }
  748.  
  749.                     hr = m_dibFile->GetFileHeader(strm);
  750.  
  751.                     if( FAILED(hr) )
  752.                         break;
  753.  
  754.                     m_state = bdsGotFileHeader;
  755.  
  756.                     // now FALL THRU!
  757.                 }
  758.                 else
  759.                 {
  760.                     break;
  761.                 }
  762.             }
  763.         
  764.         case bdsGotFileHeader:
  765.             {
  766.                 if( dwSize >= (m_dibFile->HeaderSize() + sizeof(BITMAPFILEHEADER)) )
  767.                 {
  768.                     if( m_dibFile )
  769.                         hr = m_dibFile->GetInfoHeader(strm);
  770.                     else
  771.                         hr = E_OUTOFMEMORY;
  772.  
  773.                     if( FAILED(hr) )
  774.                         break;
  775.  
  776.                     if( m_dib )
  777.                         delete m_dib;
  778.  
  779.                     m_dib = new CDibSection;
  780.  
  781.                     if( !m_dib )
  782.                     {
  783.                         hr = E_OUTOFMEMORY;
  784.                         break;
  785.                     }
  786.  
  787.                     m_dib->Setup(m_dc);
  788.  
  789.                     hr = m_dib->Create(*m_dibFile);
  790.  
  791.                     if( FAILED(hr) )
  792.                         break;
  793.  
  794.                     m_dib->ImageSize( m_dibFile->CalcImageSize() );
  795.                     m_state = bdsGotBitmapInfo;
  796.  
  797.                     // FALL THRU!
  798.  
  799.                 }
  800.                 else
  801.                 {
  802.                     break;
  803.                 }
  804.             }
  805.         
  806.         case bdsGotBitmapInfo:
  807.             {
  808.                 SIZEL    sz;
  809.                 m_dib->GetSize(sz);
  810.                 SetControlSize(&sz);
  811.  
  812.                 // we need m_dibFile for printing
  813.                 //delete m_dibFile;
  814.                 //m_dibFile = 0;
  815.  
  816.                 m_state = bdsGettingBits;
  817.  
  818.                 // FALL THRU
  819.             }
  820.  
  821.         case bdsGettingBits:
  822.             {
  823.                 if( dwSize > 0 )
  824.                 {
  825.                     hr = m_dib->ReadFrom( strm, dwSize );
  826.  
  827.                     if( FAILED(hr) )
  828.                         break;
  829.  
  830.                     ::RealizePalette(m_dc);
  831.  
  832.                     m_dib->PaintTo(m_dc);
  833.                 }
  834.  
  835.                 if( grfBSCF & BSCF_LASTDATANOTIFICATION )
  836.                     m_state = bdsBitsAreDone;
  837.                 else
  838.                     break;
  839.             }
  840.         
  841.         case bdsBitsAreDone:
  842.             {
  843.                 m_state = bdsNoBitsYet;
  844.                 strm->Release();
  845.                 break;
  846.             }
  847.         
  848.     }
  849.  
  850.     return(hr);
  851. }
  852.