home *** CD-ROM | disk | FTP | other *** search
/ PC Plus SuperCD (UK) 2000 May / PCP163A.iso / Runimage / Cbuilder4 / Include / Atl / ATLCTL.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1999-01-26  |  30.4 KB  |  1,183 lines

  1. // This is a part of the Active Template Library.
  2. // Copyright (C) 1996-1997 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Active Template Library Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Active Template Library product.
  10.  
  11. #ifndef ATL_NO_NAMESPACE
  12. namespace ATL
  13. {
  14. #endif
  15.  
  16. /////////////////////////////////////////////////////////////////////////////
  17. // CComDispatchDriver support
  18.  
  19. HRESULT CComDispatchDriver::GetProperty(IDispatch* pDisp, DISPID dwDispID,
  20.     VARIANT* pVar)
  21. {
  22.     ATLTRACE(_T("CPropertyHelper::GetProperty\n"));
  23.     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
  24.     return pDisp->Invoke(dwDispID, IID_NULL,
  25.             LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
  26.             &dispparamsNoArgs, pVar, NULL, NULL);
  27. }
  28.  
  29. HRESULT CComDispatchDriver::PutProperty(IDispatch* pDisp, DISPID dwDispID,
  30.     VARIANT* pVar)
  31. {
  32.     ATLTRACE(_T("CPropertyHelper::PutProperty\n"));
  33.     DISPPARAMS dispparams = {NULL, NULL, 1, 1};
  34.     dispparams.rgvarg = pVar;
  35.     DISPID dispidPut = DISPID_PROPERTYPUT;
  36.     dispparams.rgdispidNamedArgs = &dispidPut;
  37.  
  38.     if (pVar->vt == VT_UNKNOWN || pVar->vt == VT_DISPATCH || 
  39.         (pVar->vt & VT_ARRAY) || (pVar->vt & VT_BYREF))
  40.     {
  41.         HRESULT hr = pDisp->Invoke(dwDispID, IID_NULL,
  42.             LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF,
  43.             &dispparams, NULL, NULL, NULL);
  44.         if (SUCCEEDED(hr))
  45.             return hr;
  46.     }
  47.  
  48.     return pDisp->Invoke(dwDispID, IID_NULL,
  49.             LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT,
  50.             &dispparams, NULL, NULL, NULL);
  51. }
  52.  
  53. //////////////////////////////////////////////////////////////////////////////
  54. // CFirePropNotifyEvent
  55.  
  56. HRESULT CFirePropNotifyEvent::FireOnRequestEdit(IUnknown* pUnk, DISPID dispID)
  57. {
  58.     CComQIPtr<IConnectionPointContainer, &IID_IConnectionPointContainer> pCPC(pUnk);
  59.     if (!pCPC)
  60.         return S_OK;
  61.     CComPtr<IConnectionPoint> pCP;
  62.     pCPC->FindConnectionPoint(IID_IPropertyNotifySink, &pCP);
  63.     if (!pCP)
  64.         return S_OK;
  65.     CComPtr<IEnumConnections> pEnum;
  66.  
  67.     if (FAILED(pCP->EnumConnections(&pEnum)))
  68.         return S_OK;
  69.     CONNECTDATA cd;
  70.     while (pEnum->Next(1, &cd, NULL) == S_OK)
  71.     {
  72.         if (cd.pUnk)
  73.         {
  74.             HRESULT hr = S_OK;
  75.             CComQIPtr<IPropertyNotifySink, &IID_IPropertyNotifySink> pSink(cd.pUnk);
  76.             if (pSink)
  77.                 hr = pSink->OnRequestEdit(dispID);
  78.             cd.pUnk->Release();
  79.             if (hr == S_FALSE)
  80.                 return S_FALSE;
  81.         }
  82.     }
  83.     return S_OK;
  84. }
  85.  
  86. HRESULT CFirePropNotifyEvent::FireOnChanged(IUnknown* pUnk, DISPID dispID)
  87. {
  88.     CComQIPtr<IConnectionPointContainer, &IID_IConnectionPointContainer> pCPC(pUnk);
  89.     if (!pCPC)
  90.         return S_OK;
  91.     CComPtr<IConnectionPoint> pCP;
  92.     pCPC->FindConnectionPoint(IID_IPropertyNotifySink, &pCP);
  93.     if (!pCP)
  94.         return S_OK;
  95.     CComPtr<IEnumConnections> pEnum;
  96.  
  97.     if (FAILED(pCP->EnumConnections(&pEnum)))
  98.         return S_OK;
  99.     CONNECTDATA cd;
  100.     while (pEnum->Next(1, &cd, NULL) == S_OK)
  101.     {
  102.         if (cd.pUnk)
  103.         {
  104.             CComQIPtr<IPropertyNotifySink, &IID_IPropertyNotifySink> pSink(cd.pUnk);
  105.             if (pSink)
  106.                 pSink->OnChanged(dispID);
  107.             cd.pUnk->Release();
  108.         }
  109.     }
  110.     return S_OK;
  111. }
  112.  
  113. /////////////////////////////////////////////////////////////////////////////
  114. // Control support
  115.  
  116. HRESULT CComControlBase::IQuickActivate_QuickActivate(QACONTAINER *pQACont,
  117.     QACONTROL *pQACtrl)
  118. {
  119.     _ASSERTE(pQACont != NULL);
  120.     _ASSERTE(pQACtrl != NULL);
  121. #if !defined(__BORLANDC__)    // Older containers pass smaller structures
  122.     _ASSERTE(pQACont->cbSize >= sizeof(QACONTAINER));
  123.     _ASSERTE(pQACtrl->cbSize >= sizeof(QACONTROL));
  124. #endif
  125.  
  126.     if (!pQACont || !pQACtrl)
  127.         return E_POINTER;
  128.  
  129.     HRESULT hRes;
  130.     memset(pQACtrl, 0, sizeof(QACONTROL));
  131.     pQACtrl->cbSize = sizeof(QACONTROL);
  132.  
  133.     // get all interfaces we are going to need
  134.     CComPtr<IOleObject> pOO;
  135.     ControlQueryInterface(IID_IOleObject, (void**)&pOO);
  136.     CComPtr<IViewObjectEx> pVOEX;
  137.     ControlQueryInterface(IID_IViewObjectEx, (void**)&pVOEX);
  138.     CComPtr<IPointerInactive> pPI;
  139.     ControlQueryInterface(IID_IPointerInactive, (void**)&pPI);
  140.     CComPtr<IProvideClassInfo2> pPCI;
  141.     ControlQueryInterface(IID_IProvideClassInfo2, (void**)&pPCI);
  142.  
  143.     if (pOO == NULL || pVOEX == NULL)
  144.         return E_FAIL;
  145.  
  146.     pOO->SetClientSite(pQACont->pClientSite);
  147.  
  148.     if (pQACont->pAdviseSink != NULL)
  149.     {
  150.         ATLTRACE(_T("Setting up IOleObject Advise\n"));
  151.         pVOEX->SetAdvise(DVASPECT_CONTENT, 0, pQACont->pAdviseSink);
  152.     }
  153.  
  154.     CComPtr<IConnectionPointContainer> pCPC;
  155.     ControlQueryInterface(IID_IConnectionPointContainer, (void**)&pCPC);
  156.  
  157.     if (pQACont->pPropertyNotifySink)
  158.     {
  159.         ATLTRACE(_T("Setting up PropNotify CP\n"));
  160.         CComPtr<IConnectionPoint> pCP;
  161.         if (pCPC != NULL)
  162.         {
  163.             hRes = pCPC->FindConnectionPoint(IID_IPropertyNotifySink, &pCP);
  164.             if (SUCCEEDED(hRes))
  165.                 pCP->Advise(pQACont->pPropertyNotifySink, &pQACtrl->dwPropNotifyCookie);
  166.         }
  167.     }
  168.  
  169.     if (pPCI)
  170.     {
  171.         GUID iidDefaultSrc;
  172.         if (SUCCEEDED(pPCI->GetGUID(GUIDKIND_DEFAULT_SOURCE_DISP_IID,
  173.             &iidDefaultSrc)))
  174.         {
  175.             if (pQACont->pUnkEventSink)
  176.             {
  177.                 ATLTRACE(_T("Setting up Default Out Going Interface\n"));
  178.                 CComPtr<IConnectionPoint> pCP;
  179.                 if (pCPC != NULL)
  180.                 {
  181.                     hRes = pCPC->FindConnectionPoint(iidDefaultSrc, &pCP);
  182.                     if (SUCCEEDED(hRes))
  183.                         pCP->Advise(pQACont->pUnkEventSink, &pQACtrl->dwEventCookie);
  184.                 }
  185.             }
  186.         }
  187.     }
  188.     // give information to container
  189.     if (pOO != NULL)
  190.         pOO->GetMiscStatus(DVASPECT_CONTENT, &pQACtrl->dwMiscStatus);
  191.  
  192.     if (pVOEX != NULL)
  193.         pVOEX->GetViewStatus(&pQACtrl->dwViewStatus);
  194.  
  195.     if (pPI != NULL)
  196.         pPI->GetActivationPolicy(&pQACtrl->dwPointerActivationPolicy);
  197.     return S_OK;
  198. }
  199.  
  200. HRESULT CComControlBase::IPersistPropertyBag_Load(LPPROPERTYBAG pPropBag,
  201.     LPERRORLOG pErrorLog, ATL_PROPMAP_ENTRY* pMap)
  202. {
  203.     USES_CONVERSION;
  204.     CComPtr<IDispatch> pDispatch;
  205.     const IID* piidOld = NULL;
  206.     for(int i = 0; pMap[i].pclsidPropPage != NULL; i++)
  207.     {
  208.         if (pMap[i].szDesc == NULL)
  209.             continue;
  210.         CComVariant var;
  211.  
  212.         if(pMap[i].piidDispatch != piidOld)
  213.         {
  214.             pDispatch.Release();
  215.             if(FAILED(ControlQueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch)))
  216.             {
  217.                 ATLTRACE(_T("Failed to get a dispatch pointer for property #%i\n"), i);
  218.                 return E_FAIL;
  219.             }
  220.             piidOld = pMap[i].piidDispatch;
  221.         }
  222.  
  223.         if (FAILED(CComDispatchDriver::GetProperty(pDispatch, pMap[i].dispid, &var)))
  224.         {
  225.             ATLTRACE(_T("Invoked failed on DISPID %x\n"), pMap[i].dispid);
  226.             return E_FAIL;
  227.         }
  228.  
  229.         HRESULT hr = pPropBag->Read(pMap[i].szDesc, &var, pErrorLog);
  230.         if (FAILED(hr))
  231.         {
  232.             if (hr == E_INVALIDARG)
  233.             {
  234.                 ATLTRACE(_T("Property %s not in Bag\n"), OLE2CT(pMap[i].szDesc));
  235.             }
  236.             else
  237.             {
  238.                 // Many containers return different ERROR values for Member not found
  239.                 ATLTRACE(_T("Error attempting to read Property %s from PropertyBag \n"), OLE2CT(pMap[i].szDesc));
  240.             }
  241.             continue;
  242.         }
  243.  
  244.         if (FAILED(CComDispatchDriver::PutProperty(pDispatch, pMap[i].dispid, &var)))
  245.         {
  246.             ATLTRACE(_T("Invoked failed on DISPID %x\n"), pMap[i].dispid);
  247.             return E_FAIL;
  248.         }
  249.     }
  250.     return S_OK;
  251.  
  252. }
  253.  
  254. HRESULT CComControlBase::IPersistPropertyBag_Save(LPPROPERTYBAG pPropBag,
  255.     BOOL fClearDirty, BOOL /*fSaveAllProperties*/, ATL_PROPMAP_ENTRY* pMap)
  256. {
  257.     if (pPropBag == NULL)
  258.     {
  259.         ATLTRACE(_T("PropBag pointer passed in was invalid\n"));
  260.         return E_POINTER;
  261.     }
  262.  
  263.     CComPtr<IDispatch> pDispatch;
  264.     const IID* piidOld = NULL;
  265.     for(int i = 0; pMap[i].pclsidPropPage != NULL; i++)
  266.     {
  267.         if (pMap[i].szDesc == NULL)
  268.             continue;
  269.         CComVariant var;
  270.  
  271.         if(pMap[i].piidDispatch != piidOld)
  272.         {
  273.             pDispatch.Release();
  274.             if(FAILED(ControlQueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch)))
  275.             {
  276.                 ATLTRACE(_T("Failed to get a dispatch pointer for property #%i\n"), i);
  277.                 return E_FAIL;
  278.             }
  279.             piidOld = pMap[i].piidDispatch;
  280.         }
  281.  
  282.         if (FAILED(CComDispatchDriver::GetProperty(pDispatch, pMap[i].dispid, &var)))
  283.         {
  284.             ATLTRACE(_T("Invoked failed on DISPID %x\n"), pMap[i].dispid);
  285.             return E_FAIL;
  286.         }
  287.  
  288.         if (var.vt == VT_UNKNOWN || var.vt == VT_DISPATCH)
  289.         {
  290.             if (var.punkVal == NULL)
  291.             {
  292.                 ATLTRACE(_T("Warning skipping empty IUnknown in Save\n"));
  293.                 continue;
  294.             }
  295.         }
  296.  
  297.         HRESULT hr = pPropBag->Write(pMap[i].szDesc, &var);
  298.         if (FAILED(hr))
  299.             return hr;
  300.     }
  301.     m_bRequiresSave = FALSE;
  302.     return S_OK;
  303. }
  304.  
  305. HRESULT CComControlBase::ISpecifyPropertyPages_GetPages(CAUUID* pPages,
  306.     ATL_PROPMAP_ENTRY* pMap)
  307. {
  308.     _ASSERTE(pMap != NULL);
  309.     int nCnt = 0;
  310.     // Get count of unique pages
  311.     for(int i = 0; pMap[i].pclsidPropPage != NULL; i++)
  312.     {
  313.         if (!InlineIsEqualGUID(*pMap[i].pclsidPropPage, CLSID_NULL))
  314.             nCnt++;
  315.     }
  316.     pPages->pElems = NULL;
  317.     pPages->pElems = (GUID*) CoTaskMemAlloc(sizeof(CLSID)*nCnt);
  318.     if (pPages->pElems == NULL)
  319.         return E_OUTOFMEMORY;
  320.     nCnt = 0;
  321. #if defined(BCC32_COMPAT) && !defined(__MFC_COMPAT__)
  322.         int i;
  323. #endif        
  324.     for(i = 0; pMap[i].pclsidPropPage != NULL; i++)
  325.     {
  326.         if (!InlineIsEqualGUID(*pMap[i].pclsidPropPage, CLSID_NULL))
  327.         {
  328.             BOOL bMatch = FALSE;
  329.             for (int j=0;j<nCnt;j++)
  330.             {
  331.                 if (InlineIsEqualGUID(*(pMap[i].pclsidPropPage), pPages->pElems[j]))
  332.                 {
  333.                     bMatch = TRUE;
  334.                     break;
  335.                 }
  336.             }
  337.             if (!bMatch)
  338.                 pPages->pElems[nCnt++] = *pMap[i].pclsidPropPage;
  339.         }
  340.     }
  341.     pPages->cElems = nCnt;
  342.     return S_OK;
  343. }
  344.  
  345. BOOL CComControlBase::SetControlFocus(BOOL bGrab)
  346. {
  347.     if (m_bWndLess)
  348.     {
  349.         if (!m_bUIActive && bGrab)
  350.             if (FAILED(InPlaceActivate(OLEIVERB_UIACTIVATE)))
  351.                 return FALSE;
  352.  
  353.         return (m_spInPlaceSite->SetFocus(bGrab) == S_OK);
  354.     }
  355.     else
  356.     {
  357.         // we've got a window.
  358.         //
  359.         if (m_bInPlaceActive)
  360.         {
  361.             HWND hwnd = (bGrab) ? m_hWndCD : ::GetParent(m_hWndCD);
  362.             if (!m_bUIActive && bGrab)
  363.                 return SUCCEEDED(InPlaceActivate(OLEIVERB_UIACTIVATE));
  364.             else
  365.                 return (::SetFocus(hwnd) != NULL);
  366.         }
  367.     }
  368.     return FALSE;
  369. }
  370.  
  371. HRESULT CComControlBase::DoVerbProperties(LPCRECT /* prcPosRect */, HWND hwndParent)
  372. {
  373.     HRESULT hr = S_OK;
  374.     CComQIPtr <ISpecifyPropertyPages, &IID_ISpecifyPropertyPages> spPages;
  375.     CComQIPtr <IOleObject, &IID_IOleObject> spObj;
  376.     CComQIPtr <IOleControlSite, &IID_IOleControlSite> spSite(m_spClientSite);
  377.  
  378.     if (spSite)
  379.     {
  380.         hr = spSite->ShowPropertyFrame();
  381.         if (SUCCEEDED(hr))
  382.             return hr;
  383.     }
  384.  
  385.     CComPtr<IUnknown> pUnk;
  386.     ControlQueryInterface(IID_IUnknown, (void**)&pUnk);
  387.     _ASSERTE(pUnk != NULL);
  388.     CAUUID pages;
  389.     spPages = pUnk;
  390.     if (spPages)
  391.     {
  392.         spPages->GetPages(&pages);
  393.         spObj = pUnk;
  394.         if (spObj)
  395.         {
  396.             LPOLESTR szTitle = NULL;
  397.  
  398.             spObj->GetUserType(USERCLASSTYPE_SHORT, &szTitle);
  399.  
  400.             hr = OleCreatePropertyFrame(hwndParent, m_rcPos.top, m_rcPos.left, szTitle,
  401.                 1, &pUnk.p, pages.cElems, pages.pElems, LOCALE_USER_DEFAULT, 0, 0);
  402.  
  403.             CoTaskMemFree(szTitle);
  404.         }
  405.         else
  406.         {
  407.             hr = OLEOBJ_S_CANNOT_DOVERB_NOW;
  408.         }
  409.     }
  410.     else
  411.     {
  412.         hr = OLEOBJ_S_CANNOT_DOVERB_NOW;
  413.     }
  414.  
  415.     return hr;
  416. }
  417.  
  418. HRESULT CComControlBase::InPlaceActivate(LONG iVerb, const RECT* prcPosRect)
  419. {
  420.     HRESULT hr;
  421.  
  422.     if (m_spClientSite == NULL)
  423.         return S_OK;
  424.  
  425.     CComPtr<IOleInPlaceObject> pIPO;
  426.     ControlQueryInterface(IID_IOleInPlaceObject, (void**)&pIPO);
  427.     _ASSERTE(pIPO != NULL);
  428.     if (prcPosRect != NULL)
  429.         pIPO->SetObjectRects(prcPosRect, prcPosRect);
  430.  
  431.     if (!m_bNegotiatedWnd)
  432.     {
  433.         if (!m_bWindowOnly)
  434.             // Try for windowless site
  435.             hr = m_spClientSite->QueryInterface(IID_IOleInPlaceSiteWindowless, (void **)&m_spInPlaceSite);
  436.  
  437.         if (m_spInPlaceSite)
  438.         {
  439.             m_bInPlaceSiteEx = TRUE;
  440.             m_bWndLess = SUCCEEDED(m_spInPlaceSite->CanWindowlessActivate());
  441.             m_bWasOnceWindowless = TRUE;
  442.         }
  443.         else
  444.         {
  445.             m_spClientSite->QueryInterface(IID_IOleInPlaceSiteEx, (void **)&m_spInPlaceSite);
  446.             if (m_spInPlaceSite)
  447.                 m_bInPlaceSiteEx = TRUE;
  448.             else
  449.                 hr = m_spClientSite->QueryInterface(IID_IOleInPlaceSite, (void **)&m_spInPlaceSite);
  450.         }
  451.     }
  452.  
  453.     _ASSERTE(m_spInPlaceSite);
  454.     if (!m_spInPlaceSite)
  455.         return E_FAIL;
  456.  
  457.     m_bNegotiatedWnd = TRUE;
  458.  
  459.     if (!m_bInPlaceActive)
  460.     {
  461.  
  462.         BOOL bNoRedraw = FALSE;
  463.         if (m_bWndLess)
  464.             m_spInPlaceSite->OnInPlaceActivateEx(&bNoRedraw, ACTIVATE_WINDOWLESS);
  465.         else
  466.         {
  467.             if (m_bInPlaceSiteEx)
  468.                 m_spInPlaceSite->OnInPlaceActivateEx(&bNoRedraw, 0);
  469.             else
  470.             {
  471.                 HRESULT hr = m_spInPlaceSite->CanInPlaceActivate();
  472.                 if (FAILED(hr))
  473.                     return hr;
  474.                 m_spInPlaceSite->OnInPlaceActivate();
  475.             }
  476.         }
  477.     }
  478.  
  479.     m_bInPlaceActive = TRUE;
  480.  
  481.     // get location in the parent window,
  482.     // as well as some information about the parent
  483.     //
  484.     OLEINPLACEFRAMEINFO frameInfo;
  485.     RECT rcPos, rcClip;
  486.     CComPtr<IOleInPlaceFrame> spInPlaceFrame;
  487.     CComPtr<IOleInPlaceUIWindow> spInPlaceUIWindow;
  488.     frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);
  489.     HWND hwndParent;
  490.     if (m_spInPlaceSite->GetWindow(&hwndParent) == S_OK)
  491.     {
  492.         m_spInPlaceSite->GetWindowContext(&spInPlaceFrame,
  493.             &spInPlaceUIWindow, &rcPos, &rcClip, &frameInfo);
  494.  
  495.         if (!m_bWndLess)
  496.         {
  497.             if (m_hWndCD)
  498.             {
  499.                 ShowWindow(m_hWndCD, SW_SHOW);
  500.                         #ifdef BCC32_COMPAT // jmt.  Don't move focus from control to reflector
  501.                                 if (GetFocus()==NULL || !IsChild(m_hWndCD, GetFocus()))
  502.                                            SetFocus(m_hWndCD);
  503.                         #else
  504.                                 SetFocus(m_hWndCD);
  505.                         #endif
  506.             }
  507.             else
  508.             {
  509.                 HWND h = CreateControlWindow(hwndParent, rcPos);
  510.                 _ASSERTE(h == m_hWndCD);
  511.             }
  512.         }
  513.  
  514.         pIPO->SetObjectRects(&rcPos, &rcClip);
  515.     }
  516.  
  517.     CComPtr<IOleInPlaceActiveObject> spActiveObject;
  518.     ControlQueryInterface(IID_IOleInPlaceActiveObject, (void**)&spActiveObject);
  519.  
  520.     // Gone active by now, take care of UIACTIVATE
  521.     if (DoesVerbUIActivate(iVerb))
  522.     {
  523.         if (!m_bUIActive)
  524.         {
  525.             m_bUIActive = TRUE;
  526.             hr = m_spInPlaceSite->OnUIActivate();
  527.             if (FAILED(hr))
  528.                 return hr;
  529.  
  530.             SetControlFocus(TRUE);
  531.             // set ourselves up in the host.
  532.             //
  533.             if (spActiveObject)
  534.             {
  535.                 if (spInPlaceFrame)
  536.                     spInPlaceFrame->SetActiveObject(spActiveObject, NULL);
  537.                 if (spInPlaceUIWindow)
  538.                     spInPlaceUIWindow->SetActiveObject(spActiveObject, NULL);
  539.             }
  540.  
  541.             if (spInPlaceFrame)
  542.                 spInPlaceFrame->SetBorderSpace(NULL);
  543.             if (spInPlaceUIWindow)
  544.                 spInPlaceUIWindow->SetBorderSpace(NULL);
  545.         }
  546.     }
  547.  
  548.     m_spClientSite->ShowObject();
  549.  
  550.     return S_OK;
  551. }
  552.  
  553. HRESULT CComControlBase::IPersistStreamInit_Load(LPSTREAM pStm, ATL_PROPMAP_ENTRY* pMap)
  554. {
  555.     _ASSERTE(pMap != NULL);
  556.     HRESULT hr = S_OK;
  557.     DWORD dwVer;
  558.     hr = pStm->Read(&dwVer, sizeof(DWORD), NULL);
  559.     if (SUCCEEDED(hr) && dwVer <= _ATL_VER)
  560.         hr = pStm->Read(&m_sizeExtent, sizeof(m_sizeExtent), NULL);
  561.     if (FAILED(hr))
  562.         return hr;
  563.  
  564.     CComPtr<IDispatch> pDispatch;
  565.     const IID* piidOld = NULL;
  566.     for(int i = 0; pMap[i].pclsidPropPage != NULL; i++)
  567.     {
  568.         if (pMap[i].szDesc == NULL)
  569.             continue;
  570.         CComVariant var;
  571.  
  572.         HRESULT hr = var.ReadFromStream(pStm);
  573.         if (FAILED(hr))
  574.             break;
  575.  
  576.         if(pMap[i].piidDispatch != piidOld)
  577.         {
  578.             if(FAILED(ControlQueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch)))
  579.             {
  580.                 ATLTRACE(_T("Failed to get a dispatch pointer for property #%i\n"), i);
  581.                 hr = E_FAIL;
  582.                 break;
  583.             }
  584.             piidOld = pMap[i].piidDispatch;
  585.         }
  586.  
  587.         if (FAILED(CComDispatchDriver::PutProperty(pDispatch, pMap[i].dispid, &var)))
  588.         {
  589.             ATLTRACE(_T("Invoked failed on DISPID %x\n"), pMap[i].dispid);
  590.             hr = E_FAIL;
  591.             break;
  592.         }
  593.     }
  594.     return hr;
  595. }
  596.  
  597. HRESULT CComControlBase::IPersistStreamInit_Save(LPSTREAM pStm, BOOL /* fClearDirty */, ATL_PROPMAP_ENTRY* pMap)
  598. {
  599.     _ASSERTE(pMap != NULL);
  600.     DWORD dw = _ATL_VER;
  601.     HRESULT hr = pStm->Write(&dw, sizeof(DWORD), NULL);
  602.     if (FAILED(hr))
  603.         return hr;
  604.     hr = pStm->Write(&m_sizeExtent, sizeof(m_sizeExtent), NULL);
  605.     if (FAILED(hr))
  606.         return hr;
  607.  
  608.     CComPtr<IDispatch> pDispatch;
  609.     const IID* piidOld = NULL;
  610.     for(int i = 0; pMap[i].pclsidPropPage != NULL; i++)
  611.     {
  612.         if (pMap[i].szDesc == NULL)
  613.             continue;
  614.         CComVariant var;
  615.  
  616.         if(pMap[i].piidDispatch != piidOld)
  617.         {
  618.             if(FAILED(ControlQueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch)))
  619.             {
  620.                 ATLTRACE(_T("Failed to get a dispatch pointer for property #%i\n"), i);
  621.                 hr = E_FAIL;
  622.                 break;
  623.             }
  624.             piidOld = pMap[i].piidDispatch;
  625.         }
  626.  
  627.         if (FAILED(CComDispatchDriver::GetProperty(pDispatch, pMap[i].dispid, &var)))
  628.         {
  629.             ATLTRACE(_T("Invoked failed on DISPID %x\n"), pMap[i].dispid);
  630.             hr = E_FAIL;
  631.             break;
  632.         }
  633.  
  634.         HRESULT hr = var.WriteToStream(pStm);
  635.         if (FAILED(hr))
  636.             break;
  637.     }
  638.     if (SUCCEEDED(hr))
  639.         m_bRequiresSave = FALSE;
  640.  
  641.     return hr;
  642. }
  643.  
  644. HRESULT CComControlBase::SendOnDataChange(DWORD advf)
  645. {
  646.     HRESULT hRes = S_OK;
  647.     if (m_spDataAdviseHolder)
  648.     {
  649.         CComPtr<IDataObject> pdo;
  650.         if (SUCCEEDED(ControlQueryInterface(IID_IDataObject, (void**)&pdo)))
  651.             hRes = m_spDataAdviseHolder->SendOnDataChange(pdo, 0, advf);
  652.     }
  653.     return hRes;
  654. }
  655.  
  656. HRESULT CComControlBase::IOleObject_SetClientSite(IOleClientSite *pClientSite)
  657. {
  658.     _ASSERTE(pClientSite == NULL || m_spClientSite == NULL);
  659.     m_spClientSite = pClientSite;
  660.     m_spAmbientDispatch.Release();
  661.     if (m_spClientSite != NULL)
  662.     {
  663.         m_spClientSite->QueryInterface(IID_IDispatch,
  664.             (void**) &m_spAmbientDispatch.p);
  665.     }
  666.     return S_OK;
  667. }
  668.  
  669. HRESULT CComControlBase::IOleObject_GetClientSite(IOleClientSite **ppClientSite)
  670. {
  671.     _ASSERTE(ppClientSite);
  672.     HRESULT hRes = E_POINTER;
  673.     if (ppClientSite != NULL)
  674.     {
  675.         *ppClientSite = m_spClientSite;
  676.         m_spClientSite->AddRef();
  677.         hRes = S_OK;
  678.     }
  679.     return hRes;
  680. }
  681.  
  682. HRESULT CComControlBase::IOleObject_Advise(IAdviseSink *pAdvSink,
  683.     DWORD *pdwConnection)
  684. {
  685.     HRESULT hr = S_OK;
  686.     if (m_spOleAdviseHolder == NULL)
  687.         hr = CreateOleAdviseHolder(&m_spOleAdviseHolder);
  688.     if (SUCCEEDED(hr))
  689.         hr = m_spOleAdviseHolder->Advise(pAdvSink, pdwConnection);
  690.     return hr;
  691. }
  692.  
  693. HRESULT CComControlBase::IOleObject_Close(DWORD dwSaveOption)
  694. {
  695.     CComPtr<IOleInPlaceObject> pIPO;
  696.     ControlQueryInterface(IID_IOleInPlaceObject, (void**)&pIPO);
  697.     _ASSERTE(pIPO != NULL);
  698.     if (m_hWndCD)
  699.     {
  700.         if (m_spClientSite)
  701.             m_spClientSite->OnShowWindow(FALSE);
  702.     }
  703.  
  704.     if (m_bInPlaceActive)
  705.     {
  706.         HRESULT hr = pIPO->InPlaceDeactivate();
  707.         if (FAILED(hr))
  708.             return hr;
  709.         _ASSERTE(!m_bInPlaceActive);
  710.     }
  711.     if (m_hWndCD)
  712.     {
  713.         ATLTRACE(_T("Destroying Window\n"));
  714.         if (::IsWindow(m_hWndCD))
  715.             DestroyWindow(m_hWndCD);
  716.         m_hWndCD = NULL;
  717.     }
  718.  
  719.     // handle the save flag.
  720.     //
  721.     if ((dwSaveOption == OLECLOSE_SAVEIFDIRTY ||
  722.         dwSaveOption == OLECLOSE_PROMPTSAVE) && m_bRequiresSave)
  723.     {
  724.         if (m_spClientSite)
  725.             m_spClientSite->SaveObject();
  726.         SendOnSave();
  727.     }
  728.  
  729.     m_spInPlaceSite.Release();
  730.     m_bNegotiatedWnd = FALSE;
  731.     m_bWndLess = FALSE;
  732.     m_bInPlaceSiteEx = FALSE;
  733.     m_spAdviseSink.Release();
  734.     return S_OK;
  735. }
  736.  
  737. HRESULT CComControlBase::IOleInPlaceObject_InPlaceDeactivate(void)
  738. {
  739.     CComPtr<IOleInPlaceObject> pIPO;
  740.     ControlQueryInterface(IID_IOleInPlaceObject, (void**)&pIPO);
  741.     _ASSERTE(pIPO != NULL);
  742.  
  743.     if (!m_bInPlaceActive)
  744.         return S_OK;
  745.     pIPO->UIDeactivate();
  746.  
  747.     m_bInPlaceActive = FALSE;
  748.  
  749.     // if we have a window, tell it to go away.
  750.     //
  751.     if (m_hWndCD)
  752.     {
  753.         ATLTRACE(_T("Destroying Window\n"));
  754.         if (::IsWindow(m_hWndCD))
  755.             DestroyWindow(m_hWndCD);
  756.         m_hWndCD = NULL;
  757.     }
  758.  
  759.     if (m_spInPlaceSite)
  760.         m_spInPlaceSite->OnInPlaceDeactivate();
  761.  
  762.     return S_OK;
  763. }
  764.  
  765. HRESULT CComControlBase::IOleInPlaceObject_UIDeactivate(void)
  766. {
  767.     // if we're not UIActive, not much to do.
  768.     //
  769.     if (!m_bUIActive)
  770.         return S_OK;
  771.  
  772.     m_bUIActive = FALSE;
  773.  
  774.     // notify frame windows, if appropriate, that we're no longer ui-active.
  775.     //
  776.     CComPtr<IOleInPlaceFrame> spInPlaceFrame;
  777.     CComPtr<IOleInPlaceUIWindow> spInPlaceUIWindow;
  778.     OLEINPLACEFRAMEINFO frameInfo;
  779.     frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);
  780.     RECT rcPos, rcClip;
  781.  
  782.     HWND hwndParent; 
  783.     // This call to GetWindow is a fix for Delphi
  784.     if (m_spInPlaceSite->GetWindow(&hwndParent) == S_OK)
  785.     {
  786.         m_spInPlaceSite->GetWindowContext(&spInPlaceFrame,
  787.             &spInPlaceUIWindow, &rcPos, &rcClip, &frameInfo);
  788.         if (spInPlaceUIWindow)
  789.             spInPlaceUIWindow->SetActiveObject(NULL, NULL);
  790.         if (spInPlaceFrame)
  791.             spInPlaceFrame->SetActiveObject(NULL, NULL);
  792.     }
  793.     // we don't need to explicitly release the focus here since somebody
  794.     // else grabbing the focus is what is likely to cause us to get lose it
  795.     //
  796.     m_spInPlaceSite->OnUIDeactivate(FALSE);
  797.  
  798.     return S_OK;
  799. }
  800.  
  801. HRESULT CComControlBase::IOleInPlaceObject_SetObjectRects(LPCRECT prcPos,LPCRECT prcClip)
  802. {
  803.     if (prcPos == NULL || prcClip == NULL)
  804.         return E_POINTER;
  805.  
  806.     m_rcPos = *prcPos;
  807.     if (m_hWndCD)
  808.     {
  809.         // the container wants us to clip, so figure out if we really
  810.         // need to
  811.         //
  812.         RECT rcIXect;
  813.         BOOL b = IntersectRect(&rcIXect, prcPos, prcClip);
  814.         HRGN tempRgn = NULL;
  815.         if (b && !EqualRect(&rcIXect, prcPos))
  816.         {
  817.             OffsetRect(&rcIXect, -(prcPos->left), -(prcPos->top));
  818.             tempRgn = CreateRectRgnIndirect(&rcIXect);
  819.         }
  820.  
  821.         SetWindowRgn(m_hWndCD, tempRgn, TRUE);
  822.  
  823.         // set our control's location, but don't change it's size at all
  824.         // [people for whom zooming is important should set that up here]
  825.         //
  826.         SIZEL size = {prcPos->right - prcPos->left, prcPos->bottom - prcPos->top};
  827.         SetWindowPos(m_hWndCD, NULL, prcPos->left,
  828.                      prcPos->top, size.cx, size.cy, SWP_NOZORDER | SWP_NOACTIVATE);
  829.     }
  830.  
  831.     return S_OK;
  832. }
  833.  
  834. HRESULT CComControlBase::IOleObject_SetExtent(DWORD dwDrawAspect, SIZEL *psizel)
  835. {
  836.     if (dwDrawAspect != DVASPECT_CONTENT)
  837.         return DV_E_DVASPECT;
  838.     if (psizel == NULL)
  839.         return E_POINTER;
  840.  
  841.     BOOL bSizeMatchesNatural =
  842.         memcmp(psizel, &m_sizeNatural, sizeof(SIZE)) == 0;
  843.  
  844.     if (m_bAutoSize) //object can't do any other size
  845.         return (bSizeMatchesNatural) ? S_OK : E_FAIL;
  846.  
  847.     BOOL bResized = FALSE;
  848.     if (memcmp(psizel, &m_sizeExtent, sizeof(SIZE)) != 0)
  849.     {
  850.         m_sizeExtent = *psizel;
  851.         bResized = TRUE;
  852.     }
  853.     if (m_bResizeNatural && !bSizeMatchesNatural)
  854.     {
  855.         m_sizeNatural = *psizel;
  856.         bResized = TRUE;
  857.     }
  858.  
  859.     if (m_bRecomposeOnResize && bResized)
  860.     {
  861.         SendOnDataChange();
  862.         FireViewChange();
  863.     }
  864.     return S_OK;
  865. }
  866.  
  867. HRESULT CComControlBase::IViewObject_Draw(DWORD dwDrawAspect, LONG lindex,
  868.     void *pvAspect, DVTARGETDEVICE *ptd, HDC hicTargetDev, HDC hdcDraw,
  869.     LPCRECTL prcBounds, LPCRECTL prcWBounds)
  870. {
  871.     ATLTRACE(_T("Draw dwDrawAspect=%x lindex=%d ptd=%x hic=%x hdc=%x\n"),
  872.         dwDrawAspect, lindex, ptd, hicTargetDev, hdcDraw);
  873. #ifdef _DEBUG
  874.     if (prcBounds == NULL)
  875.         ATLTRACE(_T("\tprcBounds=NULL\n"));
  876.     else
  877.         ATLTRACE(_T("\tprcBounds=%d,%d,%d,%d\n"), prcBounds->left,
  878.             prcBounds->top, prcBounds->right, prcBounds->bottom);
  879.     if (prcWBounds == NULL)
  880.         ATLTRACE(_T("\tprcWBounds=NULL\n"));
  881.     else
  882.         ATLTRACE(_T("\tprcWBounds=%d,%d,%d,%d\n"), prcWBounds->left,
  883.             prcWBounds->top, prcWBounds->right, prcWBounds->bottom);
  884. #endif
  885. #ifdef BCC32_COMPAT
  886.         _ASSERTE(prcBounds != NULL || m_bWndLess);
  887. #else
  888.     _ASSERTE(prcBounds != NULL | m_bWndLess);
  889. #endif
  890.  
  891.     if (prcBounds == NULL)
  892.     {
  893.         if (!m_bWndLess)
  894.             return E_INVALIDARG;
  895.         prcBounds = (RECTL*)&m_rcPos;
  896.     }
  897.  
  898.     // support the aspects required for multi-pass drawing
  899.     switch (dwDrawAspect)
  900.     {
  901.         case DVASPECT_CONTENT:
  902.         case DVASPECT_OPAQUE:
  903.         case DVASPECT_TRANSPARENT:
  904.             break;
  905.         default:
  906.             _ASSERTE(FALSE);
  907.             return DV_E_DVASPECT;
  908. #if !defined(BCC32_COMPAT)
  909.             break;
  910. #endif                        
  911.     }
  912.  
  913.     // make sure nobody forgets to do this
  914.     if (ptd == NULL)
  915.         hicTargetDev = NULL;
  916.  
  917.     BOOL bOptimize = FALSE;
  918.     if (pvAspect && ((DVASPECTINFO *)pvAspect)->cb >= sizeof(DVASPECTINFO))
  919.         bOptimize = (((DVASPECTINFO *)pvAspect)->dwFlags & DVASPECTINFOFLAG_CANOPTIMIZE);
  920.  
  921.     ATL_DRAWINFO di;
  922.     memset(&di, 0, sizeof(di));
  923.     di.cbSize = sizeof(di);
  924.     di.dwDrawAspect = dwDrawAspect;
  925.     di.lindex = lindex;
  926.     di.ptd = ptd;
  927.     di.hicTargetDev = hicTargetDev;
  928.     di.hdcDraw = hdcDraw;
  929.     di.prcBounds = prcBounds;
  930.     di.prcWBounds = prcWBounds;
  931.     di.bOptimize = bOptimize;
  932.     return OnDrawAdvanced(di);
  933. }
  934.  
  935. HRESULT CComControlBase::IDataObject_GetData(FORMATETC *pformatetcIn,
  936.     STGMEDIUM *pmedium)
  937. {
  938.     if (pmedium == NULL)
  939.         return E_POINTER;
  940.     memset(pmedium, 0, sizeof(STGMEDIUM));
  941.     ATLTRACE(_T("Format = %x\n"), pformatetcIn->cfFormat);
  942.     ATLTRACE(_T("TYMED = %x\n"), pformatetcIn->tymed);
  943.  
  944.     if ((pformatetcIn->tymed & TYMED_MFPICT) == 0)
  945.         return DATA_E_FORMATETC;
  946.  
  947.     SIZEL sizeMetric, size;
  948.     if (m_bDrawFromNatural)
  949.         sizeMetric = m_sizeNatural;
  950.     else
  951.         sizeMetric = m_sizeExtent;
  952.     if (!m_bDrawGetDataInHimetric)
  953.         AtlHiMetricToPixel(&sizeMetric, &size);
  954.     else
  955.         size = sizeMetric;
  956.     RECTL rectl = {0 ,0, size.cx, size.cy};
  957.  
  958.     ATL_DRAWINFO di;
  959.     memset(&di, 0, sizeof(di));
  960.     di.cbSize = sizeof(di);
  961.     di.dwDrawAspect = DVASPECT_CONTENT;
  962.     di.lindex = -1;
  963.     di.ptd = NULL;
  964.     di.hicTargetDev = NULL;
  965.     di.prcBounds = &rectl;
  966.     di.prcWBounds = &rectl;
  967.     di.bOptimize = TRUE; //we do a SaveDC/RestoreDC
  968.     di.bRectInHimetric = m_bDrawGetDataInHimetric;
  969.     // create appropriate memory metafile DC
  970.     di.hdcDraw = CreateMetaFile(NULL);
  971.  
  972.     // create attribute DC according to pformatetcIn->ptd
  973.  
  974.     SaveDC(di.hdcDraw);
  975.     SetWindowOrgEx(di.hdcDraw, 0, 0, NULL);
  976.     SetWindowExtEx(di.hdcDraw, rectl.right, rectl.bottom, NULL);
  977.     OnDrawAdvanced(di);
  978.     RestoreDC(di.hdcDraw, -1);
  979.  
  980.     HMETAFILE hMF = CloseMetaFile(di.hdcDraw);
  981.     if (hMF == NULL)
  982.         return E_UNEXPECTED;
  983.  
  984.     HGLOBAL hMem=GlobalAlloc(GMEM_SHARE | GMEM_MOVEABLE, sizeof(METAFILEPICT));
  985.  
  986.     if (NULL==hMem)
  987.     {
  988.         DeleteMetaFile(hMF);
  989.         return ResultFromScode(STG_E_MEDIUMFULL);
  990.     }
  991.  
  992.     LPMETAFILEPICT pMF=(LPMETAFILEPICT)GlobalLock(hMem);
  993.     pMF->hMF=hMF;
  994.     pMF->mm=MM_ANISOTROPIC;
  995.     pMF->xExt=sizeMetric.cx;
  996.     pMF->yExt=sizeMetric.cy;
  997.     GlobalUnlock(hMem);
  998.  
  999.     pmedium->tymed = TYMED_MFPICT;
  1000.     pmedium->hGlobal = hMem;
  1001.     pmedium->pUnkForRelease = NULL;
  1002.  
  1003.     return S_OK;
  1004.  
  1005. }
  1006.  
  1007. HRESULT CComControlBase::FireViewChange()
  1008. {
  1009.     if (m_bInPlaceActive)
  1010.     {
  1011.         // Active
  1012.         if (m_hWndCD != NULL)
  1013.             return ::InvalidateRect(m_hWndCD, NULL, TRUE); // Window based
  1014.         if (m_spInPlaceSite != NULL)
  1015.             return m_spInPlaceSite->InvalidateRect(NULL, TRUE); // Windowless
  1016.     }
  1017.     // Inactive
  1018.     SendOnViewChange(DVASPECT_CONTENT);
  1019.     return S_OK;
  1020. }
  1021.  
  1022. void CComControlBase::GetZoomInfo(ATL_DRAWINFO& di)
  1023. {
  1024.     const RECTL& rcPos = *di.prcBounds;
  1025.     SIZEL sizeDen;
  1026.     if (m_bDrawFromNatural)
  1027.         sizeDen = m_sizeNatural;
  1028.     else
  1029.         sizeDen = m_sizeExtent;
  1030.     if (!di.bRectInHimetric)
  1031.         AtlHiMetricToPixel(&sizeDen, &sizeDen);
  1032.     SIZEL sizeNum = {rcPos.right-rcPos.left, rcPos.bottom-rcPos.top};
  1033.     di.ZoomNum.cx = sizeNum.cx;
  1034.     di.ZoomNum.cy = sizeNum.cy;
  1035.     di.ZoomDen.cx = sizeDen.cx;
  1036.     di.ZoomDen.cy = sizeDen.cy;
  1037.     if (sizeDen.cx == 0 || sizeDen.cy == 0 ||
  1038.         sizeNum.cx == 0 || sizeNum.cy == 0)
  1039.     {
  1040.         di.ZoomNum.cx = di.ZoomNum.cy = di.ZoomDen.cx = di.ZoomDen.cy = 1;
  1041.         di.bZoomed = FALSE;
  1042.     }
  1043.     else if (sizeNum.cx != sizeDen.cx || sizeNum.cy != sizeDen.cy)
  1044.         di.bZoomed = TRUE;
  1045.     else
  1046.         di.bZoomed = FALSE;
  1047. }
  1048.  
  1049. HRESULT CComControlBase::OnDrawAdvanced(ATL_DRAWINFO& di)
  1050. {
  1051.     BOOL bDeleteDC = FALSE;
  1052.     if (di.hicTargetDev == NULL)
  1053.     {
  1054.         di.hicTargetDev = AtlCreateTargetDC(di.hdcDraw, di.ptd);
  1055.         bDeleteDC = (di.hicTargetDev != di.hdcDraw);
  1056.     }
  1057.     RECTL rectBoundsDP = *di.prcBounds;
  1058.     BOOL bMetafile = GetDeviceCaps(di.hdcDraw, TECHNOLOGY) == DT_METAFILE;
  1059.     if (!bMetafile)
  1060.     {
  1061.         ::LPtoDP(di.hicTargetDev, (LPPOINT)&rectBoundsDP, 2);
  1062.         SaveDC(di.hdcDraw);
  1063.         SetMapMode(di.hdcDraw, MM_TEXT);
  1064.         SetWindowOrgEx(di.hdcDraw, 0, 0, NULL);
  1065.         SetViewportOrgEx(di.hdcDraw, 0, 0, NULL);
  1066.         di.bOptimize = TRUE; //since we save the DC we can do this
  1067.     }
  1068.     di.prcBounds = &rectBoundsDP;
  1069.     GetZoomInfo(di);
  1070.  
  1071.     HRESULT hRes = OnDraw(di);
  1072.     if (bDeleteDC)
  1073.         ::DeleteDC(di.hicTargetDev);
  1074.     if (!bMetafile)
  1075.         RestoreDC(di.hdcDraw, -1);
  1076.     return hRes;
  1077. }
  1078.  
  1079. LRESULT CComControlBase::OnPaint(UINT /* nMsg */, WPARAM /* wParam */,
  1080.     LPARAM /* lParam */, BOOL& /* lResult */)
  1081. {
  1082.     RECT rc;
  1083.     PAINTSTRUCT ps;
  1084.  
  1085.     HDC hdc = ::BeginPaint(m_hWndCD, &ps);
  1086.     if (hdc == NULL)
  1087.         return 0;
  1088.     ::GetClientRect(m_hWndCD, &rc);
  1089.  
  1090.     ATL_DRAWINFO di;
  1091.     memset(&di, 0, sizeof(di));
  1092.     di.cbSize = sizeof(di);
  1093.     di.dwDrawAspect = DVASPECT_CONTENT;
  1094.     di.lindex = -1;
  1095.     di.hdcDraw = hdc;
  1096.     di.prcBounds = (LPCRECTL)&rc;
  1097.  
  1098.     OnDrawAdvanced(di);
  1099.     ::EndPaint(m_hWndCD, &ps);
  1100.     return 0;
  1101. }
  1102.  
  1103. #ifndef ATL_NO_NAMESPACE
  1104. }; //namespace ATL
  1105. #endif
  1106.  
  1107. ///////////////////////////////////////////////////////////////////////////////
  1108. //All Global stuff goes below this line
  1109. ///////////////////////////////////////////////////////////////////////////////
  1110.  
  1111. #ifndef _ATL_DLL
  1112. ATLAPI_(HDC) AtlCreateTargetDC(HDC hdc, DVTARGETDEVICE* ptd)
  1113. {
  1114.     USES_CONVERSION;
  1115.  
  1116.     // cases  hdc, ptd, hdc is metafile, hic
  1117. //  NULL,    NULL,  n/a,    Display
  1118. //  NULL,   !NULL,  n/a,    ptd
  1119. //  !NULL,   NULL,  FALSE,  hdc
  1120. //  !NULL,   NULL,  TRUE,   display
  1121. //  !NULL,  !NULL,  FALSE,  ptd
  1122. //  !NULL,  !NULL,  TRUE,   ptd
  1123.  
  1124.     if (ptd != NULL)
  1125.     {
  1126.         LPDEVMODEOLE lpDevMode;
  1127.         LPOLESTR lpszDriverName;
  1128.         LPOLESTR lpszDeviceName;
  1129.         LPOLESTR lpszPortName;
  1130.  
  1131.         if (ptd->tdExtDevmodeOffset == 0)
  1132.             lpDevMode = NULL;
  1133.         else
  1134.             lpDevMode  = (LPDEVMODEOLE) ((LPSTR)ptd + ptd->tdExtDevmodeOffset);
  1135.  
  1136.         lpszDriverName = (LPOLESTR)((BYTE*)ptd + ptd->tdDriverNameOffset);
  1137.         lpszDeviceName = (LPOLESTR)((BYTE*)ptd + ptd->tdDeviceNameOffset);
  1138.         lpszPortName   = (LPOLESTR)((BYTE*)ptd + ptd->tdPortNameOffset);
  1139.  
  1140.         return ::CreateDC(OLE2CT(lpszDriverName), OLE2CT(lpszDeviceName),
  1141.             OLE2CT(lpszPortName), DEVMODEOLE2T(lpDevMode));
  1142.     }
  1143.     else if (hdc == NULL || GetDeviceCaps(hdc, TECHNOLOGY) == DT_METAFILE)
  1144.         return ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
  1145.     else
  1146.         return hdc;
  1147. }
  1148.  
  1149. #define HIMETRIC_PER_INCH   2540
  1150. #define MAP_PIX_TO_LOGHIM(x,ppli)   ( (HIMETRIC_PER_INCH*(x) + ((ppli)>>1)) / (ppli) )
  1151. #define MAP_LOGHIM_TO_PIX(x,ppli)   ( ((ppli)*(x) + HIMETRIC_PER_INCH/2) / HIMETRIC_PER_INCH )
  1152.  
  1153. ATLAPI_(void) AtlHiMetricToPixel(const SIZEL * lpSizeInHiMetric, LPSIZEL lpSizeInPix)
  1154. {
  1155.     int nPixelsPerInchX;    // Pixels per logical inch along width
  1156.     int nPixelsPerInchY;    // Pixels per logical inch along height
  1157.  
  1158.     HDC hDCScreen = GetDC(NULL);
  1159.     _ASSERTE(hDCScreen != NULL);
  1160.     nPixelsPerInchX = GetDeviceCaps(hDCScreen, LOGPIXELSX);
  1161.     nPixelsPerInchY = GetDeviceCaps(hDCScreen, LOGPIXELSY);
  1162.     ReleaseDC(NULL, hDCScreen);
  1163.  
  1164.     lpSizeInPix->cx = MAP_LOGHIM_TO_PIX(lpSizeInHiMetric->cx, nPixelsPerInchX);
  1165.     lpSizeInPix->cy = MAP_LOGHIM_TO_PIX(lpSizeInHiMetric->cy, nPixelsPerInchY);
  1166. }
  1167.  
  1168. ATLAPI_(void) AtlPixelToHiMetric(const SIZEL * lpSizeInPix, LPSIZEL lpSizeInHiMetric)
  1169. {
  1170.     int nPixelsPerInchX;    // Pixels per logical inch along width
  1171.     int nPixelsPerInchY;    // Pixels per logical inch along height
  1172.  
  1173.     HDC hDCScreen = GetDC(NULL);
  1174.     _ASSERTE(hDCScreen != NULL);
  1175.     nPixelsPerInchX = GetDeviceCaps(hDCScreen, LOGPIXELSX);
  1176.     nPixelsPerInchY = GetDeviceCaps(hDCScreen, LOGPIXELSY);
  1177.     ReleaseDC(NULL, hDCScreen);
  1178.  
  1179.     lpSizeInHiMetric->cx = MAP_PIX_TO_LOGHIM(lpSizeInPix->cx, nPixelsPerInchX);
  1180.     lpSizeInHiMetric->cy = MAP_PIX_TO_LOGHIM(lpSizeInPix->cy, nPixelsPerInchY);
  1181. }
  1182. #endif
  1183.