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 / ctlview.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-05  |  22.5 KB  |  733 lines

  1. //=--------------------------------------------------------------------------=
  2. // CtlView.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 the IViewObjectEx interface, which is a moderately
  13. // non-trivial bunch of code.
  14. //
  15. #include "IPServer.H"
  16.  
  17. #include "CtrlObj.H"
  18. #include "Globals.H"
  19. #include "Util.H"
  20.  
  21. // for ASSERT and FAIL
  22. //
  23. SZTHISFILE
  24.  
  25. // local functions we're going to find useful
  26. //
  27. HDC _CreateOleDC(DVTARGETDEVICE *ptd);
  28.  
  29. //=--------------------------------------------------------------------------=
  30. // COleControl::Draw    [IViewObject2]
  31. //=--------------------------------------------------------------------------=
  32. // Draws a representation of an object onto the specified device context. 
  33. //
  34. // Parameters:
  35. //    DWORD                - [in] draw aspect
  36. //    LONG                 - [in] part of object to draw [not relevant]
  37. //    void *               - NULL
  38. //    DVTARGETDEVICE *     - [in] specifies the target device
  39. //    HDC                  - [in] information context for target device
  40. //    HDC                  - [in] target device context
  41. //    LPCRECTL             - [in] rectangle in which the object is drawn
  42. //    LPCRECTL             - [in] window extent and origin for metafiles
  43. //    BOOL (*)(DWORD)      - [in] callback for continuing or cancelling drawing
  44. //    DWORD                - [in] parameter to pass to callback.
  45. //
  46. // Output:
  47. //    HRESULT
  48. //
  49. // Notes:
  50. //    - we support the following OCX 96 extensions
  51. //        a. flicker free drawing [multi-pass drawing]
  52. //        b. pvAspect != NULL for optimized DC handling
  53. //        c. prcBounds == NULL for windowless inplace active objects
  54. //
  55. STDMETHODIMP COleControl::Draw
  56. (
  57.     DWORD            dwDrawAspect,
  58.     LONG             lIndex,
  59.     void            *pvAspect,
  60.     DVTARGETDEVICE  *ptd,
  61.     HDC              hicTargetDevice,
  62.     HDC              hdcDraw,
  63.     LPCRECTL         prcBounds,
  64.     LPCRECTL         prcWBounds,
  65.     BOOL (__stdcall *pfnContinue)(DWORD dwContinue),
  66.     DWORD            dwContinue
  67. )
  68. {
  69.     HRESULT hr;
  70.     RECTL rc;
  71.     POINT pVp, pW;
  72.     BOOL  fOptimize = FALSE;
  73.     int iMode;
  74.     BYTE fMetafile = FALSE;
  75.     BYTE fDeleteDC = FALSE;
  76.  
  77.     // support the aspects required for multi-pass drawing
  78.     //
  79.     switch (dwDrawAspect) {
  80.         case DVASPECT_CONTENT:
  81.         case DVASPECT_OPAQUE:
  82.         case DVASPECT_TRANSPARENT:
  83.             break;
  84.         default:
  85.             return DV_E_DVASPECT;
  86.     }
  87.  
  88.     // first, have to do a little bit to support printing.
  89.     //
  90.     if (GetDeviceCaps(hdcDraw, TECHNOLOGY) == DT_METAFILE) {
  91.  
  92.         // We are dealing with a metafile.
  93.         //
  94.         fMetafile = TRUE;
  95.  
  96.         // If attributes DC is NULL, create one, based on ptd.
  97.         //
  98.         if (!hicTargetDevice) {
  99.  
  100.             // Does _CreateOleDC have to return an hDC
  101.             // or can it be flagged to return an hIC 
  102.             // for this particular case?
  103.             //
  104.             hicTargetDevice = _CreateOleDC(ptd);
  105.             fDeleteDC = TRUE;
  106.         }
  107.     }
  108.  
  109.     // check to see if we have any flags passed in the pvAspect parameter.
  110.     //
  111.     if (pvAspect && ((DVASPECTINFO *)pvAspect)->cb == sizeof(DVASPECTINFO))
  112.         fOptimize = (((DVASPECTINFO *)pvAspect)->dwFlags & DVASPECTINFOFLAG_CANOPTIMIZE) ? TRUE : FALSE;
  113.  
  114.     // if we are windowless, then we just pass this on to the end control code.
  115.     //
  116.     if (m_fInPlaceActive) {
  117.  
  118.         // give them a rectangle with which to draw
  119.         //
  120.         //ASSERT(!m_fInPlaceActive || !prcBounds, "Inplace active and somebody passed in prcBounds!!!");
  121.         if (prcBounds)
  122.         memcpy(&rc, prcBounds, sizeof(rc));
  123.     else
  124.         memcpy(&rc, &m_rcLocation, sizeof(rc));
  125.     } else {
  126.  
  127.         // first -- convert the DC back to MM_TEXT mapping mode so that the
  128.         // window proc and OnDraw can share the same painting code.  save
  129.         // some information on it, so we can restore it later [without using
  130.         // a SaveDC/RestoreDC]
  131.         //
  132.         rc = *prcBounds;
  133.  
  134.         // Don't do anything to hdcDraw if it's a metafile.
  135.         // The control's Draw method must make the appropriate
  136.         // accomodations for drawing to a metafile
  137.         //
  138.         if (!fMetafile) {
  139.             LPtoDP(hdcDraw, (POINT *)&rc, 2);
  140.             SetViewportOrgEx(hdcDraw, 0, 0, &pVp);
  141.             SetWindowOrgEx(hdcDraw, 0, 0, &pW);
  142.             iMode = SetMapMode(hdcDraw, MM_TEXT);
  143.         }
  144.     }
  145.  
  146.     // prcWBounds is NULL and not used if we are not dealing with a metafile.
  147.     // For metafiles, we pass on rc as *prcBounds, we should also include
  148.     // prcWBounds
  149.     //
  150.     hr = OnDraw(dwDrawAspect, hdcDraw, &rc, prcWBounds, hicTargetDevice, fOptimize);
  151.  
  152.     // clean up the DC when we're done with it, if appropriate.
  153.     //
  154.     if (!m_fInPlaceActive) {
  155.         SetViewportOrgEx(hdcDraw, pVp.x, pVp.y, NULL);
  156.         SetWindowOrgEx(hdcDraw, pW.x, pW.y, NULL);
  157.         SetMapMode(hdcDraw, iMode);
  158.     }
  159.  
  160.     // if we created a dc, blow it away now
  161.     //
  162.     if (fDeleteDC) DeleteDC(hicTargetDevice);
  163.     return hr;
  164. }
  165.  
  166. //=--------------------------------------------------------------------------=
  167. // COleControl::DoSuperClassPaint
  168. //=--------------------------------------------------------------------------=
  169. // design time painting of a subclassed control.
  170. //
  171. // Parameters:
  172. //    HDC                - [in]  dc to work with
  173. //    LPCRECTL           - [in]  rectangle to paint to.  should be in pixels
  174. //
  175. // Output:
  176. //    HRESULT
  177. //
  178. // Notes:
  179. //
  180. HRESULT COleControl::DoSuperClassPaint
  181. (
  182.     HDC      hdc,
  183.     LPCRECTL prcBounds
  184. )
  185. {
  186.     HWND hwnd;
  187.     RECT rcClient;
  188.     int  iMapMode;
  189.     POINT ptWOrg, ptVOrg;
  190.     SIZE  sWOrg, sVOrg;
  191.  
  192.     // make sure we have a window.
  193.     //
  194.     hwnd = CreateInPlaceWindow(0,0, FALSE);
  195.     if (!hwnd)
  196.         return E_FAIL;
  197.  
  198.     GetClientRect(hwnd, &rcClient);
  199.  
  200.     // set up the DC for painting.  this code largely taken from the MFC CDK
  201.     // DoSuperClassPaint() fn.  doesn't always get things like command
  202.     // buttons quite right ...
  203.     //
  204.     // NOTE: there is a windows 95 problem in which the font instance manager
  205.     // will leak a bunch of bytes in the global GDI pool whenever you 
  206.     // change your extents and have an active font.  this code gets around
  207.     // this for on-screen cases, but not for printing [which shouldn't be
  208.     // too serious, because you're not often changing your control size and
  209.     // printing rapidly in succession]
  210.     //
  211.     if ((rcClient.right - rcClient.left != prcBounds->right - prcBounds->left)
  212.         && (rcClient.bottom - rcClient.top != prcBounds->bottom - prcBounds->top)) {
  213.  
  214.         iMapMode = SetMapMode(hdc, MM_ANISOTROPIC);
  215.         SetWindowExtEx(hdc, rcClient.right, rcClient.bottom, &sWOrg);
  216.         SetViewportExtEx(hdc, prcBounds->right - prcBounds->left, prcBounds->bottom - prcBounds->top, &sVOrg);
  217.     }
  218.  
  219.     SetWindowOrgEx(hdc, 0, 0, &ptWOrg);
  220.     SetViewportOrgEx(hdc, prcBounds->left, prcBounds->top, &ptVOrg);
  221.  
  222. #if STRICT
  223.     CallWindowProc((WNDPROC)SUBCLASSWNDPROCOFCONTROL(m_ObjectType), hwnd, (g_fSysWin95Shell) ? WM_PRINT : WM_PAINT, (WPARAM)hdc, (LPARAM)(g_fSysWin95Shell ? PRF_CHILDREN | PRF_CLIENT : 0));
  224. #else
  225.     CallWindowProc((FARPROC)SUBCLASSWNDPROCOFCONTROL(m_ObjectType), hwnd, (g_fSysWin95Shell) ? WM_PRINT : WM_PAINT, (WPARAM)hdc, (LPARAM)(g_fSysWin95Shell ? PRF_CHILDREN | PRF_CLIENT : 0));
  226. #endif // STRICT
  227.  
  228.     return S_OK;
  229. }
  230.  
  231.  
  232. //=--------------------------------------------------------------------------=
  233. // COleControl::GetColorSet    [IViewObject2]
  234. //=--------------------------------------------------------------------------=
  235. // Returns the logical palette that the control will use for drawing in its
  236. // IViewObject::Draw method with the corresponding parameters.
  237. //
  238. // Parameters:
  239. //    DWORD                - [in]  how the object is to be represented
  240. //    LONG                 - [in]  part of the object to draw [not relevant]
  241. //    void *               - NULL
  242. //    DVTARGETDEVICE *     - [in]  specifies the target device
  243. //    HDC                  - [in]  information context for the target device
  244. //    LOGPALETTE **        - [out] where to put palette
  245. //
  246. // Output:
  247. //    S_OK                 - Control has a palette, and returned it through the out param.
  248. //    S_FALSE              - Control does not currently have a palette.
  249. //    E_NOTIMPL            - Control will never have a palette so optimize handling of this control.
  250. //
  251. // Notes:
  252. //
  253. STDMETHODIMP COleControl::GetColorSet
  254. (
  255.     DWORD            dwDrawAspect,
  256.     LONG             lindex,
  257.     void            *IgnoreMe,
  258.     DVTARGETDEVICE  *ptd,
  259.     HDC              hicTargetDevice,
  260.     LOGPALETTE     **ppColorSet
  261. )
  262. {
  263.     if (dwDrawAspect != DVASPECT_CONTENT)
  264.         return DV_E_DVASPECT;
  265.  
  266.     *ppColorSet = NULL;
  267.     return (OnGetPalette(hicTargetDevice, ppColorSet)) ? ((*ppColorSet) ? S_OK : S_FALSE) : E_NOTIMPL;
  268. }
  269.  
  270. //=--------------------------------------------------------------------------=
  271. // COleControl::Freeze    [IViewObject2]
  272. //=--------------------------------------------------------------------------=
  273. // Freezes a certain aspect of the object's presentation so that it does not
  274. // change until the IViewObject::Unfreeze method is called.
  275. //
  276. // Parameters:
  277. //    DWORD            - [in] aspect
  278. //    LONG             - [in] part of object to draw
  279. //    void *           - NULL
  280. //    DWORD *          - [out] for Unfreeze
  281. //
  282. // Output:
  283. //    HRESULT
  284. //
  285. // Notes:
  286. //
  287. STDMETHODIMP COleControl::Freeze
  288. (
  289.     DWORD   dwDrawAspect,
  290.     LONG    lIndex,
  291.     void   *IgnoreMe,
  292.     DWORD  *pdwFreeze
  293. )
  294. {
  295.     return E_NOTIMPL;
  296. }
  297.  
  298. //=--------------------------------------------------------------------------=
  299. // COleControl::Unfreeze    [IVewObject2]
  300. //=--------------------------------------------------------------------------=
  301. // Releases a previously frozen drawing. The most common use of this method
  302. // is for banded printing.
  303. //
  304. // Parameters:
  305. //    DWORD        - [in] cookie from freeze
  306. //
  307. // Output:
  308. //    HRESULT
  309. //
  310. // Notes:
  311. //
  312. STDMETHODIMP COleControl::Unfreeze
  313. (
  314.     DWORD dwFreeze
  315. )
  316. {
  317.     return E_NOTIMPL;
  318. }
  319.  
  320. //=--------------------------------------------------------------------------=
  321. // COleControl::SetAdvise    [IViewObject2]
  322. //=--------------------------------------------------------------------------=
  323. // Sets up a connection between the control and an advise sink so that the
  324. // advise sink can be notified about changes in the control's view.
  325. //
  326. // Parameters:
  327. //    DWORD            - [in] aspect
  328. //    DWORD            - [in] info about the sink
  329. //    IAdviseSink *    - [in] the sink
  330. //
  331. // Output:
  332. //    HRESULT
  333. //
  334. // Notes:
  335. //
  336. STDMETHODIMP COleControl::SetAdvise
  337. (
  338.     DWORD        dwAspects,
  339.     DWORD        dwAdviseFlags,
  340.     IAdviseSink *pAdviseSink
  341. )
  342. {
  343.     // if it's not a content aspect, we don't support it.
  344.     //
  345.     if (!(dwAspects & DVASPECT_CONTENT)) {
  346.         return DV_E_DVASPECT;
  347.     }
  348.  
  349.     // set up some flags  [we gotta stash for GetAdvise ...]
  350.     //
  351.     m_fViewAdvisePrimeFirst = (dwAdviseFlags & ADVF_PRIMEFIRST) ? TRUE : FALSE;
  352.     m_fViewAdviseOnlyOnce = (dwAdviseFlags & ADVF_ONLYONCE) ? TRUE : FALSE;
  353.  
  354.     RELEASE_OBJECT(m_pViewAdviseSink);
  355.     m_pViewAdviseSink = pAdviseSink;
  356.     ADDREF_OBJECT(m_pViewAdviseSink);
  357.  
  358.     // prime them if they want it [we need to store this so they can get flags later]
  359.     //
  360.     if (m_fViewAdvisePrimeFirst)
  361.         ViewChanged();
  362.  
  363.     return S_OK;
  364. }
  365.  
  366. //=--------------------------------------------------------------------------=
  367. // COleControl::GetAdvise    [IViewObject2]
  368. //=--------------------------------------------------------------------------=
  369. // Retrieves the existing advisory connection on the control if there is one.
  370. // This method simply returns the parameters used in the most recent call to
  371. // the IViewObject::SetAdvise method.
  372. //
  373. // Parameters:
  374. //    DWORD *            - [out]  aspects
  375. //    DWORD *            - [out]  advise flags
  376. //    IAdviseSink **     - [out]  the sink
  377. //
  378. // Output:
  379. //    HRESULT
  380. //
  381. // Notes;
  382. //
  383. STDMETHODIMP COleControl::GetAdvise
  384. (
  385.     DWORD        *pdwAspects,
  386.     DWORD        *pdwAdviseFlags,
  387.     IAdviseSink **ppAdviseSink
  388. )
  389. {
  390.     // if they want it, give it to them
  391.     //
  392.     if (pdwAspects)
  393.         *pdwAspects = DVASPECT_CONTENT;
  394.  
  395.     if (pdwAdviseFlags) {
  396.         *pdwAdviseFlags = 0;
  397.         if (m_fViewAdviseOnlyOnce) *pdwAdviseFlags |= ADVF_ONLYONCE;
  398.         if (m_fViewAdvisePrimeFirst) *pdwAdviseFlags |= ADVF_PRIMEFIRST;
  399.     }
  400.  
  401.     if (ppAdviseSink) {
  402.         *ppAdviseSink = m_pViewAdviseSink;
  403.         ADDREF_OBJECT(*ppAdviseSink);
  404.     }
  405.  
  406.     return S_OK;
  407. }
  408.  
  409. //=--------------------------------------------------------------------------=
  410. // COleControl::GetExtent    [IViewObject2]
  411. //=--------------------------------------------------------------------------=
  412. // Returns the size that the control will be drawn on the
  413. // specified target device.
  414. //
  415. // Parameters:
  416. //    DWORD            - [in] draw aspect
  417. //    LONG             - [in] part of object to draw
  418. //    DVTARGETDEVICE * - [in] information about target device
  419. //    LPSIZEL          - [out] where to put the size
  420. //
  421. // Output:
  422. //    HRESULT
  423. //
  424. // Notes:
  425. //
  426. STDMETHODIMP COleControl::GetExtent
  427. (
  428.     DWORD           dwDrawAspect,
  429.     LONG            lindex,
  430.     DVTARGETDEVICE *ptd,
  431.     LPSIZEL         psizel
  432. )
  433. {
  434.     // we already have an implementation of this [from IOleObject]
  435.     //
  436.     return GetExtent(dwDrawAspect, psizel);
  437. }
  438.  
  439.  
  440. //=--------------------------------------------------------------------------=
  441. // COleControl::OnGetPalette    [overridable]
  442. //=--------------------------------------------------------------------------=
  443. // called when the host wants palette information.  ideally, people should use
  444. // this sparingly and carefully.
  445. //
  446. // Parameters:
  447. //    HDC            - [in]  HIC for the target device
  448. //    LOGPALETTE **  - [out] where to put the palette
  449. //
  450. // Output:
  451. //    BOOL           - TRUE means we processed it, false means nope.
  452. //
  453. // Notes:
  454. //
  455. BOOL COleControl::OnGetPalette
  456. (
  457.     HDC          hicTargetDevice,
  458.     LOGPALETTE **ppColorSet
  459. )
  460. {
  461.     return FALSE;
  462. }
  463.  
  464.  
  465. //=--------------------------------------------------------------------------=
  466. // COleControl::GetRect    [IViewObjectEx]
  467. //=--------------------------------------------------------------------------=
  468. // returns a rectnagle describing a given drawing aspect
  469. //
  470. // Parameters:
  471. //    DWORD             - [in]  aspect
  472. //    LPRECTL           - [out] region rectangle
  473. //
  474. // Output:
  475. //    HRESULT
  476. //
  477. // Notes:
  478. //
  479. STDMETHODIMP COleControl::GetRect
  480. (
  481.     DWORD    dvAspect,
  482.     LPRECTL  prcRect
  483. )
  484. {
  485.     RECTL rc;
  486.     BOOL  f;
  487.  
  488.     // call the user routine and let them return the size
  489.     //
  490.     f = OnGetRect(dvAspect, &rc);
  491.     if (!f) return DV_E_DVASPECT;
  492.  
  493.     // transform these dudes.
  494.     //
  495.     PixelToHiMetric((LPSIZEL)&rc, (LPSIZEL)prcRect);
  496.     PixelToHiMetric((LPSIZEL)(LPBYTE)&rc + sizeof(SIZEL), (LPSIZEL)((LPBYTE)prcRect + sizeof(SIZEL)));
  497.  
  498.     return S_OK;
  499. }
  500.  
  501. //=--------------------------------------------------------------------------=
  502. // COleControl::GetViewStatus    [IViewObjectEx]
  503. //=--------------------------------------------------------------------------=
  504. // returns information about the opactiy of the object and what drawing
  505. // aspects are supported
  506. //
  507. // Parameters:
  508. //    DWORD *            - [out] the status
  509. //
  510. /// Output:
  511. //    HRESULT
  512. //
  513. // Notes:
  514. //
  515. STDMETHODIMP COleControl::GetViewStatus
  516. (
  517.     DWORD *pdwStatus
  518. )
  519. {
  520.     // depending on the flag in the CONTROLOBJECTINFO structure, indicate our
  521.     // transparency vs opacity.
  522.     // OVERRIDE:  controls that wish to support multi-pass drawing should
  523.     // override this routine and return, in addition to the flags indication
  524.     // opacity, flags indicating what sort of drawing aspects they support.
  525.     //
  526.     *pdwStatus = FCONTROLISOPAQUE(m_ObjectType) ? VIEWSTATUS_OPAQUE : 0;
  527.     return S_OK;
  528. }
  529.  
  530. //=--------------------------------------------------------------------------=
  531. // COleControl::QueryHitPoint    [IViewObjectEx]
  532. //=--------------------------------------------------------------------------=
  533. // indicates whether a point is within a given aspect of an object.
  534. //
  535. // Parameters:
  536. //    DWORD                - [in]  aspect
  537. //    LPCRECT              - [in]  Bounds rectangle
  538. //    POINT                - [in]  hit location client coordinates
  539. //    LONG                 - [in]  what the container considers close
  540. //    DWORD *              - [out] info about the hit
  541. //
  542. // Output:
  543. //    HRESULT
  544. //
  545. // Notes:
  546. //
  547. STDMETHODIMP COleControl::QueryHitPoint
  548. (
  549.     DWORD    dvAspect,
  550.     LPCRECT  prcBounds,
  551.     POINT    ptLocation,
  552.     LONG     lCloseHint,
  553.     DWORD   *pdwHitResult
  554. )
  555. {
  556.     // OVERRIDE: override me if you want to provide additional [non-opaque]
  557.     // functionality
  558.     //
  559.     if (dvAspect != DVASPECT_CONTENT)
  560.         return DV_E_DVASPECT;
  561.  
  562.     *pdwHitResult = PtInRect(prcBounds, ptLocation) ? HITRESULT_HIT : HITRESULT_OUTSIDE;
  563.     return S_OK;
  564. }
  565.  
  566. //=--------------------------------------------------------------------------=
  567. // COleControl::QueryHitRect    [IViewObjectEx]
  568. //=--------------------------------------------------------------------------=
  569. // indicates wheter any point in a rectangle is within a given drawing aspect
  570. // of an object.
  571. //
  572. // Parameters:
  573. //    DWORD            - [in]  aspect
  574. //    LPCRECT          - [in]  bounds
  575. //    LPCRECT          - [in]  location
  576. //    LONG             - [in]  what host considers close
  577. //    DWORD *          - [out] hit result
  578. //
  579. // Output:
  580. //    HRESULT
  581. //
  582. // Notes:
  583. //
  584. STDMETHODIMP COleControl::QueryHitRect
  585. (
  586.     DWORD     dvAspect,
  587.     LPCRECT   prcBounds,
  588.     LPCRECT   prcLocation,
  589.     LONG      lCloseHint,
  590.     DWORD    *pdwHitResult
  591. )
  592. {
  593.     RECT rc;
  594.  
  595.     // OVERRIDE: override this for additional behaviour
  596.     //
  597.     if (dvAspect != DVASPECT_CONTENT)
  598.         return DV_E_DVASPECT;
  599.  
  600.     *pdwHitResult = IntersectRect(&rc, prcBounds, prcLocation) ? HITRESULT_HIT : HITRESULT_OUTSIDE;
  601.     return S_OK;
  602. }
  603.  
  604. //=--------------------------------------------------------------------------=
  605. // COleControl::GetNaturalExtent    [IViewObjectEx]
  606. //=--------------------------------------------------------------------------=
  607. // supports two types of control sizing, content and integral.
  608. //
  609. // Parameters:
  610. //    DWORD            - [in]  aspect
  611. //    LONG             - [in]  index
  612. //    DVTARGETDEVICE * - [in]  target device information
  613. //    HDC              - [in]  HIC
  614. //    DVEXTENTINFO *   - [in]  sizing data
  615. //    LPSIZEL          - [out] sizing data retunred by control
  616. //
  617. // Output:
  618. //    HRESULT
  619. //
  620. // Notes:
  621. //
  622. STDMETHODIMP COleControl::GetNaturalExtent
  623. (
  624.     DWORD           dvAspect,
  625.     LONG            lIndex,
  626.     DVTARGETDEVICE *ptd,
  627.     HDC             hicTargetDevice,
  628.     DVEXTENTINFO   *pExtentInfo,
  629.     LPSIZEL         pSizel
  630. )
  631. {
  632.     return E_NOTIMPL;
  633. }
  634.  
  635. //=--------------------------------------------------------------------------=
  636. // COleControl::OnGetRect    [overridable
  637. //=--------------------------------------------------------------------------=
  638. // returns our rectangle
  639. //
  640. // Parameters:
  641. //    DWORD              - [in]  aspect they want the rect for
  642. //    RECTL *            - [out] the rectangle that matches this aspect
  643. //
  644. // Output:
  645. //    BOOL               - false means we don't like the aspect
  646. //
  647. // Notes:
  648. //
  649. BOOL COleControl::OnGetRect
  650. (
  651.     DWORD   dvAspect,
  652.     RECTL  *pRect
  653. )
  654. {
  655.     // by default, we only support content drawing.
  656.     //
  657.     if (dvAspect != DVASPECT_CONTENT)
  658.         return FALSE;
  659.  
  660.     // just give them our bounding rectangle
  661.     //
  662.     *((LPRECT)pRect) = m_rcLocation;
  663.     return TRUE;
  664. }
  665.  
  666. //=--------------------------------------------------------------------------=
  667. // _CreateOleDC
  668. //=--------------------------------------------------------------------------=
  669. // creates an HDC given a DVTARGETDEVICE structure.
  670. //
  671. // Parameters:
  672. //    DVTARGETDEVICE *              - [in] duh.
  673. //
  674. // Output:
  675. //    HDC
  676. //
  677. // Notes:
  678. //
  679. HDC _CreateOleDC
  680. (
  681.     DVTARGETDEVICE *ptd
  682. )
  683. {
  684.     LPDEVMODEW   pDevModeW;
  685.     DEVMODEA     DevModeA, *pDevModeA;
  686.     LPOLESTR     lpwszDriverName;
  687.     LPOLESTR     lpwszDeviceName;
  688.     LPOLESTR     lpwszPortName;
  689.     HDC          hdc;
  690.  
  691.     // return screen DC for NULL target device
  692.     //
  693.     if (!ptd)
  694.         return CreateDC("DISPLAY", NULL, NULL, NULL);
  695.  
  696.     if (ptd->tdExtDevmodeOffset == 0)
  697.         pDevModeW = NULL;
  698.     else
  699.         pDevModeW = (LPDEVMODEW)((LPSTR)ptd + ptd->tdExtDevmodeOffset);
  700.  
  701.     lpwszDriverName = (LPOLESTR)((BYTE*)ptd + ptd->tdDriverNameOffset);
  702.     lpwszDeviceName = (LPOLESTR)((BYTE*)ptd + ptd->tdDeviceNameOffset);
  703.     lpwszPortName   = (LPOLESTR)((BYTE*)ptd + ptd->tdPortNameOffset);
  704.  
  705.     MAKE_ANSIPTR_FROMWIDE(pszDriverName, lpwszDriverName);
  706.     MAKE_ANSIPTR_FROMWIDE(pszDeviceName, lpwszDeviceName);
  707.     MAKE_ANSIPTR_FROMWIDE(pszPortName,   lpwszPortName);
  708.  
  709.     // wow, this sucks.
  710.     //
  711.     if (pDevModeW) {
  712.         WideCharToMultiByte(CP_ACP, 0, pDevModeW->dmDeviceName, -1, (LPSTR)DevModeA.dmDeviceName, CCHDEVICENAME, NULL, NULL);
  713.     memcpy(&DevModeA.dmSpecVersion, &pDevModeW->dmSpecVersion,
  714.         offsetof(DEVMODEA, dmFormName) - offsetof(DEVMODEA, dmSpecVersion));
  715.         WideCharToMultiByte(CP_ACP, 0, pDevModeW->dmFormName, -1, (LPSTR)DevModeA.dmFormName, CCHFORMNAME, NULL, NULL);
  716.     memcpy(&DevModeA.dmLogPixels, &pDevModeW->dmLogPixels, sizeof(DEVMODEA) - offsetof(DEVMODEA, dmLogPixels));
  717.         if (pDevModeW->dmDriverExtra) {
  718.             pDevModeA = (DEVMODEA *)HeapAlloc(g_hHeap, 0, sizeof(DEVMODEA) + pDevModeW->dmDriverExtra);
  719.             if (!pDevModeA) return NULL;
  720.             memcpy(pDevModeA, &DevModeA, sizeof(DEVMODEA));
  721.             memcpy(pDevModeA + 1, pDevModeW + 1, pDevModeW->dmDriverExtra);
  722.         } else
  723.             pDevModeA = &DevModeA;
  724.  
  725.     DevModeA.dmSize = sizeof(DEVMODEA);
  726.     } else
  727.         pDevModeA = NULL;
  728.  
  729.     hdc = CreateDC(pszDriverName, pszDeviceName, pszPortName, pDevModeA);
  730.     if (pDevModeA != &DevModeA) HeapFree(g_hHeap, 0, pDevModeA);
  731.     return hdc;
  732. }
  733.