Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1190 lines
30 KiB

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