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