Source code of Windows XP (NT5)
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.

1171 lines
33 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. int nCnt = 0;
  271. // Get count of unique pages
  272. for(int i = 0; pMap[i].pclsidPropPage != NULL; i++)
  273. {
  274. if (!InlineIsEqualGUID(*pMap[i].pclsidPropPage, CLSID_NULL))
  275. nCnt++;
  276. }
  277. pPages->pElems = NULL;
  278. pPages->pElems = (GUID*) CoTaskMemAlloc(sizeof(CLSID)*nCnt);
  279. if (pPages->pElems == NULL)
  280. return E_OUTOFMEMORY;
  281. nCnt = 0;
  282. for(i = 0; pMap[i].pclsidPropPage != NULL; i++)
  283. {
  284. if (!InlineIsEqualGUID(*pMap[i].pclsidPropPage, CLSID_NULL))
  285. {
  286. BOOL bMatch = FALSE;
  287. for (int j=0;j<nCnt;j++)
  288. {
  289. if (InlineIsEqualGUID(*(pMap[i].pclsidPropPage), pPages->pElems[j]))
  290. {
  291. bMatch = TRUE;
  292. break;
  293. }
  294. }
  295. if (!bMatch)
  296. pPages->pElems[nCnt++] = *pMap[i].pclsidPropPage;
  297. }
  298. }
  299. pPages->cElems = nCnt;
  300. return S_OK;
  301. }
  302. BOOL CComControlBase::SetControlFocus(BOOL bGrab)
  303. {
  304. if (m_bWndLess)
  305. {
  306. if (!m_bUIActive && bGrab)
  307. if (FAILED(InPlaceActivate(OLEIVERB_UIACTIVATE)))
  308. return FALSE;
  309. return (m_spInPlaceSite->SetFocus(bGrab) == S_OK);
  310. }
  311. else
  312. {
  313. // we've got a window.
  314. //
  315. if (m_bInPlaceActive)
  316. {
  317. HWND hwnd = (bGrab) ? m_hWndCD : ::GetParent(m_hWndCD);
  318. if (!m_bUIActive && bGrab)
  319. return SUCCEEDED(InPlaceActivate(OLEIVERB_UIACTIVATE));
  320. else
  321. return (::SetFocus(hwnd) != NULL);
  322. }
  323. }
  324. return FALSE;
  325. }
  326. HRESULT CComControlBase::DoVerbProperties(LPCRECT /* prcPosRect */, HWND hwndParent)
  327. {
  328. HRESULT hr = S_OK;
  329. CComQIPtr <ISpecifyPropertyPages, &IID_ISpecifyPropertyPages> spPages;
  330. CComQIPtr <IOleObject, &IID_IOleObject> spObj;
  331. CComQIPtr <IOleControlSite, &IID_IOleControlSite> spSite(m_spClientSite);
  332. if (spSite)
  333. {
  334. hr = spSite->ShowPropertyFrame();
  335. if (SUCCEEDED(hr))
  336. return hr;
  337. }
  338. CComPtr<IUnknown> pUnk;
  339. ControlQueryInterface(IID_IUnknown, (void**)&pUnk);
  340. _ASSERTE(pUnk != NULL);
  341. CAUUID pages;
  342. spPages = pUnk;
  343. if (spPages)
  344. {
  345. spPages->GetPages(&pages);
  346. spObj = pUnk;
  347. if (spObj)
  348. {
  349. LPOLESTR szTitle = NULL;
  350. spObj->GetUserType(USERCLASSTYPE_SHORT, &szTitle);
  351. hr = OleCreatePropertyFrame(hwndParent, m_rcPos.top, m_rcPos.left, szTitle,
  352. 1, &pUnk.p, pages.cElems, pages.pElems, LOCALE_USER_DEFAULT, 0, 0);
  353. CoTaskMemFree(szTitle);
  354. }
  355. else
  356. {
  357. hr = OLEOBJ_S_CANNOT_DOVERB_NOW;
  358. }
  359. }
  360. else
  361. {
  362. hr = OLEOBJ_S_CANNOT_DOVERB_NOW;
  363. }
  364. return hr;
  365. }
  366. HRESULT CComControlBase::InPlaceActivate(LONG iVerb, const RECT* prcPosRect)
  367. {
  368. HRESULT hr;
  369. if (m_spClientSite == NULL)
  370. return S_OK;
  371. CComPtr<IOleInPlaceObject> pIPO;
  372. ControlQueryInterface(IID_IOleInPlaceObject, (void**)&pIPO);
  373. _ASSERTE(pIPO != NULL);
  374. if (prcPosRect != NULL)
  375. pIPO->SetObjectRects(prcPosRect, prcPosRect);
  376. if (!m_bNegotiatedWnd)
  377. {
  378. if (!m_bWindowOnly)
  379. // Try for windowless site
  380. hr = m_spClientSite->QueryInterface(IID_IOleInPlaceSiteWindowless, (void **)&m_spInPlaceSite);
  381. if (m_spInPlaceSite)
  382. {
  383. m_bInPlaceSiteEx = TRUE;
  384. m_bWndLess = SUCCEEDED(m_spInPlaceSite->CanWindowlessActivate());
  385. m_bWasOnceWindowless = TRUE;
  386. }
  387. else
  388. {
  389. m_spClientSite->QueryInterface(IID_IOleInPlaceSiteEx, (void **)&m_spInPlaceSite);
  390. if (m_spInPlaceSite)
  391. m_bInPlaceSiteEx = TRUE;
  392. else
  393. hr = m_spClientSite->QueryInterface(IID_IOleInPlaceSite, (void **)&m_spInPlaceSite);
  394. }
  395. }
  396. _ASSERTE(m_spInPlaceSite);
  397. if (!m_spInPlaceSite)
  398. return E_FAIL;
  399. m_bNegotiatedWnd = TRUE;
  400. if (!m_bInPlaceActive)
  401. {
  402. BOOL bNoRedraw = FALSE;
  403. if (m_bWndLess)
  404. m_spInPlaceSite->OnInPlaceActivateEx(&bNoRedraw, ACTIVATE_WINDOWLESS);
  405. else
  406. {
  407. if (m_bInPlaceSiteEx)
  408. m_spInPlaceSite->OnInPlaceActivateEx(&bNoRedraw, 0);
  409. else
  410. {
  411. HRESULT hr = m_spInPlaceSite->CanInPlaceActivate();
  412. if (FAILED(hr))
  413. return hr;
  414. m_spInPlaceSite->OnInPlaceActivate();
  415. }
  416. }
  417. }
  418. m_bInPlaceActive = TRUE;
  419. // get location in the parent window,
  420. // as well as some information about the parent
  421. //
  422. OLEINPLACEFRAMEINFO frameInfo;
  423. RECT rcPos, rcClip;
  424. CComPtr<IOleInPlaceFrame> spInPlaceFrame;
  425. CComPtr<IOleInPlaceUIWindow> spInPlaceUIWindow;
  426. frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);
  427. HWND hwndParent;
  428. if (m_spInPlaceSite->GetWindow(&hwndParent) == S_OK)
  429. {
  430. m_spInPlaceSite->GetWindowContext(&spInPlaceFrame,
  431. &spInPlaceUIWindow, &rcPos, &rcClip, &frameInfo);
  432. if (!m_bWndLess)
  433. {
  434. if (m_hWndCD)
  435. {
  436. ShowWindow(m_hWndCD, SW_SHOW);
  437. SetFocus(m_hWndCD);
  438. }
  439. else
  440. {
  441. HWND h = CreateControlWindow(hwndParent, rcPos);
  442. _ASSERTE(h == m_hWndCD);
  443. }
  444. }
  445. pIPO->SetObjectRects(&rcPos, &rcClip);
  446. }
  447. CComPtr<IOleInPlaceActiveObject> spActiveObject;
  448. ControlQueryInterface(IID_IOleInPlaceActiveObject, (void**)&spActiveObject);
  449. // Gone active by now, take care of UIACTIVATE
  450. if (DoesVerbUIActivate(iVerb))
  451. {
  452. if (!m_bUIActive)
  453. {
  454. m_bUIActive = TRUE;
  455. hr = m_spInPlaceSite->OnUIActivate();
  456. if (FAILED(hr))
  457. return hr;
  458. SetControlFocus(TRUE);
  459. // set ourselves up in the host.
  460. //
  461. if (spActiveObject)
  462. {
  463. if (spInPlaceFrame)
  464. spInPlaceFrame->SetActiveObject(spActiveObject, NULL);
  465. if (spInPlaceUIWindow)
  466. spInPlaceUIWindow->SetActiveObject(spActiveObject, NULL);
  467. }
  468. if (spInPlaceFrame)
  469. spInPlaceFrame->SetBorderSpace(NULL);
  470. if (spInPlaceUIWindow)
  471. spInPlaceUIWindow->SetBorderSpace(NULL);
  472. }
  473. }
  474. m_spClientSite->ShowObject();
  475. return S_OK;
  476. }
  477. HRESULT CComControlBase::IPersistStreamInit_Load(LPSTREAM pStm, ATL_PROPMAP_ENTRY* pMap)
  478. {
  479. _ASSERTE(pMap != NULL);
  480. HRESULT hr = S_OK;
  481. DWORD dwVer;
  482. hr = pStm->Read(&dwVer, sizeof(DWORD), NULL);
  483. if (SUCCEEDED(hr) && dwVer <= _ATL_VER)
  484. hr = pStm->Read(&m_sizeExtent, sizeof(m_sizeExtent), NULL);
  485. if (FAILED(hr))
  486. return hr;
  487. CComPtr<IDispatch> pDispatch;
  488. const IID* piidOld = NULL;
  489. for(int i = 0; pMap[i].pclsidPropPage != NULL; i++)
  490. {
  491. if (pMap[i].szDesc == NULL)
  492. continue;
  493. CComVariant var;
  494. HRESULT hr = var.ReadFromStream(pStm);
  495. if (FAILED(hr))
  496. break;
  497. if(pMap[i].piidDispatch != piidOld)
  498. {
  499. if(FAILED(ControlQueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch)))
  500. {
  501. ATLTRACE(_T("Failed to get a dispatch pointer for property #%i\n"), i);
  502. hr = E_FAIL;
  503. break;
  504. }
  505. piidOld = pMap[i].piidDispatch;
  506. }
  507. if (FAILED(CComDispatchDriver::PutProperty(pDispatch, pMap[i].dispid, &var)))
  508. {
  509. ATLTRACE(_T("Invoked failed on DISPID %x\n"), pMap[i].dispid);
  510. hr = E_FAIL;
  511. break;
  512. }
  513. }
  514. return hr;
  515. }
  516. HRESULT CComControlBase::IPersistStreamInit_Save(LPSTREAM pStm, BOOL /* fClearDirty */, ATL_PROPMAP_ENTRY* pMap)
  517. {
  518. _ASSERTE(pMap != NULL);
  519. DWORD dw = _ATL_VER;
  520. HRESULT hr = pStm->Write(&dw, sizeof(DWORD), NULL);
  521. if (FAILED(hr))
  522. return hr;
  523. hr = pStm->Write(&m_sizeExtent, sizeof(m_sizeExtent), NULL);
  524. if (FAILED(hr))
  525. return hr;
  526. CComPtr<IDispatch> pDispatch;
  527. const IID* piidOld = NULL;
  528. for(int i = 0; pMap[i].pclsidPropPage != NULL; i++)
  529. {
  530. if (pMap[i].szDesc == NULL)
  531. continue;
  532. CComVariant var;
  533. if(pMap[i].piidDispatch != piidOld)
  534. {
  535. if(FAILED(ControlQueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch)))
  536. {
  537. ATLTRACE(_T("Failed to get a dispatch pointer for property #%i\n"), i);
  538. hr = E_FAIL;
  539. break;
  540. }
  541. piidOld = pMap[i].piidDispatch;
  542. }
  543. if (FAILED(CComDispatchDriver::GetProperty(pDispatch, pMap[i].dispid, &var)))
  544. {
  545. ATLTRACE(_T("Invoked failed on DISPID %x\n"), pMap[i].dispid);
  546. hr = E_FAIL;
  547. break;
  548. }
  549. HRESULT hr = var.WriteToStream(pStm);
  550. if (FAILED(hr))
  551. break;
  552. }
  553. if (SUCCEEDED(hr))
  554. m_bRequiresSave = FALSE;
  555. return hr;
  556. }
  557. HRESULT CComControlBase::SendOnDataChange(DWORD advf)
  558. {
  559. HRESULT hRes = S_OK;
  560. if (m_spDataAdviseHolder)
  561. {
  562. CComPtr<IDataObject> pdo;
  563. if (SUCCEEDED(ControlQueryInterface(IID_IDataObject, (void**)&pdo)))
  564. hRes = m_spDataAdviseHolder->SendOnDataChange(pdo, 0, advf);
  565. }
  566. return hRes;
  567. }
  568. HRESULT CComControlBase::IOleObject_SetClientSite(IOleClientSite *pClientSite)
  569. {
  570. _ASSERTE(pClientSite == NULL || m_spClientSite == NULL);
  571. m_spClientSite = pClientSite;
  572. m_spAmbientDispatch.Release();
  573. if (m_spClientSite != NULL)
  574. {
  575. m_spClientSite->QueryInterface(IID_IDispatch,
  576. (void**) &m_spAmbientDispatch.p);
  577. }
  578. return S_OK;
  579. }
  580. HRESULT CComControlBase::IOleObject_GetClientSite(IOleClientSite **ppClientSite)
  581. {
  582. _ASSERTE(ppClientSite);
  583. HRESULT hRes = E_POINTER;
  584. if (ppClientSite != NULL)
  585. {
  586. *ppClientSite = m_spClientSite;
  587. if (m_spClientSite)
  588. m_spClientSite->AddRef();
  589. hRes = S_OK;
  590. }
  591. return hRes;
  592. }
  593. HRESULT CComControlBase::IOleObject_Advise(IAdviseSink *pAdvSink,
  594. DWORD *pdwConnection)
  595. {
  596. HRESULT hr = S_OK;
  597. if (m_spOleAdviseHolder == NULL)
  598. hr = CreateOleAdviseHolder(&m_spOleAdviseHolder);
  599. if (SUCCEEDED(hr))
  600. hr = m_spOleAdviseHolder->Advise(pAdvSink, pdwConnection);
  601. return hr;
  602. }
  603. HRESULT CComControlBase::IOleObject_Close(DWORD dwSaveOption)
  604. {
  605. CComPtr<IOleInPlaceObject> pIPO;
  606. ControlQueryInterface(IID_IOleInPlaceObject, (void**)&pIPO);
  607. _ASSERTE(pIPO != NULL);
  608. if (m_hWndCD)
  609. {
  610. if (m_spClientSite)
  611. m_spClientSite->OnShowWindow(FALSE);
  612. }
  613. if (m_bInPlaceActive)
  614. {
  615. HRESULT hr = pIPO->InPlaceDeactivate();
  616. if (FAILED(hr))
  617. return hr;
  618. _ASSERTE(!m_bInPlaceActive);
  619. }
  620. if (m_hWndCD)
  621. {
  622. ATLTRACE(_T("Destroying Window\n"));
  623. if (::IsWindow(m_hWndCD))
  624. DestroyWindow(m_hWndCD);
  625. m_hWndCD = NULL;
  626. }
  627. // handle the save flag.
  628. //
  629. if ((dwSaveOption == OLECLOSE_SAVEIFDIRTY ||
  630. dwSaveOption == OLECLOSE_PROMPTSAVE) && m_bRequiresSave)
  631. {
  632. if (m_spClientSite)
  633. m_spClientSite->SaveObject();
  634. SendOnSave();
  635. }
  636. m_spInPlaceSite.Release();
  637. m_bNegotiatedWnd = FALSE;
  638. m_bWndLess = FALSE;
  639. m_bInPlaceSiteEx = FALSE;
  640. m_spAdviseSink.Release();
  641. return S_OK;
  642. }
  643. HRESULT CComControlBase::IOleInPlaceObject_InPlaceDeactivate(void)
  644. {
  645. CComPtr<IOleInPlaceObject> pIPO;
  646. ControlQueryInterface(IID_IOleInPlaceObject, (void**)&pIPO);
  647. _ASSERTE(pIPO != NULL);
  648. if (!m_bInPlaceActive)
  649. return S_OK;
  650. pIPO->UIDeactivate();
  651. m_bInPlaceActive = FALSE;
  652. // if we have a window, tell it to go away.
  653. //
  654. if (m_hWndCD)
  655. {
  656. ATLTRACE(_T("Destroying Window\n"));
  657. if (::IsWindow(m_hWndCD))
  658. DestroyWindow(m_hWndCD);
  659. m_hWndCD = NULL;
  660. }
  661. if (m_spInPlaceSite)
  662. m_spInPlaceSite->OnInPlaceDeactivate();
  663. return S_OK;
  664. }
  665. HRESULT CComControlBase::IOleInPlaceObject_UIDeactivate(void)
  666. {
  667. // if we're not UIActive, not much to do.
  668. //
  669. if (!m_bUIActive)
  670. return S_OK;
  671. m_bUIActive = FALSE;
  672. // notify frame windows, if appropriate, that we're no longer ui-active.
  673. //
  674. CComPtr<IOleInPlaceFrame> spInPlaceFrame;
  675. CComPtr<IOleInPlaceUIWindow> spInPlaceUIWindow;
  676. OLEINPLACEFRAMEINFO frameInfo;
  677. frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);
  678. RECT rcPos, rcClip;
  679. HWND hwndParent;
  680. // This call to GetWindow is a fix for Delphi
  681. if (m_spInPlaceSite->GetWindow(&hwndParent) == S_OK)
  682. {
  683. m_spInPlaceSite->GetWindowContext(&spInPlaceFrame,
  684. &spInPlaceUIWindow, &rcPos, &rcClip, &frameInfo);
  685. if (spInPlaceUIWindow)
  686. spInPlaceUIWindow->SetActiveObject(NULL, NULL);
  687. if (spInPlaceFrame)
  688. spInPlaceFrame->SetActiveObject(NULL, NULL);
  689. }
  690. // we don't need to explicitly release the focus here since somebody
  691. // else grabbing the focus is what is likely to cause us to get lose it
  692. //
  693. m_spInPlaceSite->OnUIDeactivate(FALSE);
  694. return S_OK;
  695. }
  696. HRESULT CComControlBase::IOleInPlaceObject_SetObjectRects(LPCRECT prcPos,LPCRECT prcClip)
  697. {
  698. if (prcPos == NULL || prcClip == NULL)
  699. return E_POINTER;
  700. m_rcPos = *prcPos;
  701. if (m_hWndCD)
  702. {
  703. // the container wants us to clip, so figure out if we really
  704. // need to
  705. //
  706. RECT rcIXect;
  707. BOOL b = IntersectRect(&rcIXect, prcPos, prcClip);
  708. HRGN tempRgn = NULL;
  709. if (b && !EqualRect(&rcIXect, prcPos))
  710. {
  711. OffsetRect(&rcIXect, -(prcPos->left), -(prcPos->top));
  712. tempRgn = CreateRectRgnIndirect(&rcIXect);
  713. }
  714. SetWindowRgn(m_hWndCD, tempRgn, TRUE);
  715. // set our control's location, but don't change it's size at all
  716. // [people for whom zooming is important should set that up here]
  717. //
  718. SIZEL size = {prcPos->right - prcPos->left, prcPos->bottom - prcPos->top};
  719. SetWindowPos(m_hWndCD, NULL, prcPos->left,
  720. prcPos->top, size.cx, size.cy, SWP_NOZORDER | SWP_NOACTIVATE);
  721. }
  722. return S_OK;
  723. }
  724. HRESULT CComControlBase::IOleObject_SetExtent(DWORD dwDrawAspect, SIZEL *psizel)
  725. {
  726. if (dwDrawAspect != DVASPECT_CONTENT)
  727. return DV_E_DVASPECT;
  728. if (psizel == NULL)
  729. return E_POINTER;
  730. BOOL bSizeMatchesNatural =
  731. memcmp(psizel, &m_sizeNatural, sizeof(SIZE)) == 0;
  732. if (m_bAutoSize) //object can't do any other size
  733. return (bSizeMatchesNatural) ? S_OK : E_FAIL;
  734. BOOL bResized = FALSE;
  735. if (memcmp(psizel, &m_sizeExtent, sizeof(SIZE)) != 0)
  736. {
  737. m_sizeExtent = *psizel;
  738. bResized = TRUE;
  739. }
  740. if (m_bResizeNatural && !bSizeMatchesNatural)
  741. {
  742. m_sizeNatural = *psizel;
  743. bResized = TRUE;
  744. }
  745. if (m_bRecomposeOnResize && bResized)
  746. {
  747. SendOnDataChange();
  748. FireViewChange();
  749. }
  750. return S_OK;
  751. }
  752. HRESULT CComControlBase::IViewObject_Draw(DWORD dwDrawAspect, LONG lindex,
  753. void *pvAspect, DVTARGETDEVICE *ptd, HDC hicTargetDev, HDC hdcDraw,
  754. LPCRECTL prcBounds, LPCRECTL prcWBounds)
  755. {
  756. ATLTRACE(_T("Draw dwDrawAspect=%x lindex=%d ptd=%x hic=%x hdc=%x\n"),
  757. dwDrawAspect, lindex, ptd, hicTargetDev, hdcDraw);
  758. #ifdef _DEBUG
  759. if (prcBounds == NULL)
  760. ATLTRACE(_T("\tprcBounds=NULL\n"));
  761. else
  762. ATLTRACE(_T("\tprcBounds=%d,%d,%d,%d\n"), prcBounds->left,
  763. prcBounds->top, prcBounds->right, prcBounds->bottom);
  764. if (prcWBounds == NULL)
  765. ATLTRACE(_T("\tprcWBounds=NULL\n"));
  766. else
  767. ATLTRACE(_T("\tprcWBounds=%d,%d,%d,%d\n"), prcWBounds->left,
  768. prcWBounds->top, prcWBounds->right, prcWBounds->bottom);
  769. #endif
  770. _ASSERTE(prcBounds != NULL || m_bWndLess);
  771. if (prcBounds == NULL)
  772. {
  773. if (!m_bWndLess)
  774. return E_INVALIDARG;
  775. prcBounds = (RECTL*)&m_rcPos;
  776. }
  777. // support the aspects required for multi-pass drawing
  778. switch (dwDrawAspect)
  779. {
  780. case DVASPECT_CONTENT:
  781. case DVASPECT_OPAQUE:
  782. case DVASPECT_TRANSPARENT:
  783. break;
  784. default:
  785. _ASSERTE(FALSE);
  786. return DV_E_DVASPECT;
  787. break;
  788. }
  789. // make sure nobody forgets to do this
  790. if (ptd == NULL)
  791. hicTargetDev = NULL;
  792. BOOL bOptimize = FALSE;
  793. if (pvAspect && ((DVASPECTINFO *)pvAspect)->cb >= sizeof(DVASPECTINFO))
  794. bOptimize = (((DVASPECTINFO *)pvAspect)->dwFlags & DVASPECTINFOFLAG_CANOPTIMIZE);
  795. ATL_DRAWINFO di;
  796. memset(&di, 0, sizeof(di));
  797. di.cbSize = sizeof(di);
  798. di.dwDrawAspect = dwDrawAspect;
  799. di.lindex = lindex;
  800. di.ptd = ptd;
  801. di.hicTargetDev = hicTargetDev;
  802. di.hdcDraw = hdcDraw;
  803. di.prcBounds = prcBounds;
  804. di.prcWBounds = prcWBounds;
  805. di.bOptimize = bOptimize;
  806. return OnDrawAdvanced(di);
  807. }
  808. HRESULT CComControlBase::IDataObject_GetData(FORMATETC *pformatetcIn,
  809. STGMEDIUM *pmedium)
  810. {
  811. if (pmedium == NULL)
  812. return E_POINTER;
  813. memset(pmedium, 0, sizeof(STGMEDIUM));
  814. ATLTRACE(_T("Format = %x\n"), pformatetcIn->cfFormat);
  815. ATLTRACE(_T("TYMED = %x\n"), pformatetcIn->tymed);
  816. if ((pformatetcIn->tymed & TYMED_MFPICT) == 0)
  817. return DATA_E_FORMATETC;
  818. SIZEL sizeMetric, size;
  819. if (m_bDrawFromNatural)
  820. sizeMetric = m_sizeNatural;
  821. else
  822. sizeMetric = m_sizeExtent;
  823. if (!m_bDrawGetDataInHimetric)
  824. AtlHiMetricToPixel(&sizeMetric, &size);
  825. else
  826. size = sizeMetric;
  827. RECTL rectl = {0 ,0, size.cx, size.cy};
  828. ATL_DRAWINFO di;
  829. memset(&di, 0, sizeof(di));
  830. di.cbSize = sizeof(di);
  831. di.dwDrawAspect = DVASPECT_CONTENT;
  832. di.lindex = -1;
  833. di.ptd = NULL;
  834. di.hicTargetDev = NULL;
  835. di.prcBounds = &rectl;
  836. di.prcWBounds = &rectl;
  837. di.bOptimize = TRUE; //we do a SaveDC/RestoreDC
  838. di.bRectInHimetric = m_bDrawGetDataInHimetric;
  839. // create appropriate memory metafile DC
  840. di.hdcDraw = CreateMetaFile(NULL);
  841. // create attribute DC according to pformatetcIn->ptd
  842. SaveDC(di.hdcDraw);
  843. SetWindowOrgEx(di.hdcDraw, 0, 0, NULL);
  844. SetWindowExtEx(di.hdcDraw, rectl.right, rectl.bottom, NULL);
  845. OnDrawAdvanced(di);
  846. RestoreDC(di.hdcDraw, -1);
  847. HMETAFILE hMF = CloseMetaFile(di.hdcDraw);
  848. if (hMF == NULL)
  849. return E_UNEXPECTED;
  850. HGLOBAL hMem=GlobalAlloc(GMEM_SHARE | GMEM_MOVEABLE, sizeof(METAFILEPICT));
  851. if (NULL==hMem)
  852. {
  853. DeleteMetaFile(hMF);
  854. return ResultFromScode(STG_E_MEDIUMFULL);
  855. }
  856. LPMETAFILEPICT pMF=(LPMETAFILEPICT)GlobalLock(hMem);
  857. pMF->hMF=hMF;
  858. pMF->mm=MM_ANISOTROPIC;
  859. pMF->xExt=sizeMetric.cx;
  860. pMF->yExt=sizeMetric.cy;
  861. GlobalUnlock(hMem);
  862. pmedium->tymed = TYMED_MFPICT;
  863. pmedium->hGlobal = hMem;
  864. pmedium->pUnkForRelease = NULL;
  865. return S_OK;
  866. }
  867. HRESULT CComControlBase::FireViewChange()
  868. {
  869. if (m_bInPlaceActive)
  870. {
  871. // Active
  872. if (m_hWndCD != NULL)
  873. return (::InvalidateRect(m_hWndCD, NULL, TRUE)) ? S_OK : E_FAIL; // Window based
  874. if (m_spInPlaceSite != NULL)
  875. return m_spInPlaceSite->InvalidateRect(NULL, TRUE); // Windowless
  876. }
  877. // Inactive
  878. SendOnViewChange(DVASPECT_CONTENT);
  879. return S_OK;
  880. }
  881. void CComControlBase::GetZoomInfo(ATL_DRAWINFO& di)
  882. {
  883. const RECTL& rcPos = *di.prcBounds;
  884. SIZEL sizeDen;
  885. if (m_bDrawFromNatural)
  886. sizeDen = m_sizeNatural;
  887. else
  888. sizeDen = m_sizeExtent;
  889. if (!di.bRectInHimetric)
  890. AtlHiMetricToPixel(&sizeDen, &sizeDen);
  891. SIZEL sizeNum = {rcPos.right-rcPos.left, rcPos.bottom-rcPos.top};
  892. di.ZoomNum.cx = sizeNum.cx;
  893. di.ZoomNum.cy = sizeNum.cy;
  894. di.ZoomDen.cx = sizeDen.cx;
  895. di.ZoomDen.cy = sizeDen.cy;
  896. if (sizeDen.cx == 0 || sizeDen.cy == 0 ||
  897. sizeNum.cx == 0 || sizeNum.cy == 0)
  898. {
  899. di.ZoomNum.cx = di.ZoomNum.cy = di.ZoomDen.cx = di.ZoomDen.cy = 1;
  900. di.bZoomed = FALSE;
  901. }
  902. else if (sizeNum.cx != sizeDen.cx || sizeNum.cy != sizeDen.cy)
  903. di.bZoomed = TRUE;
  904. else
  905. di.bZoomed = FALSE;
  906. }
  907. HRESULT CComControlBase::OnDrawAdvanced(ATL_DRAWINFO& di)
  908. {
  909. BOOL bDeleteDC = FALSE;
  910. if (di.hicTargetDev == NULL)
  911. {
  912. di.hicTargetDev = AtlCreateTargetDC(di.hdcDraw, di.ptd);
  913. bDeleteDC = (di.hicTargetDev != di.hdcDraw);
  914. }
  915. RECTL rectBoundsDP = *di.prcBounds;
  916. BOOL bMetafile = GetDeviceCaps(di.hdcDraw, TECHNOLOGY) == DT_METAFILE;
  917. if (!bMetafile)
  918. {
  919. ::LPtoDP(di.hicTargetDev, (LPPOINT)&rectBoundsDP, 2);
  920. SaveDC(di.hdcDraw);
  921. SetMapMode(di.hdcDraw, MM_TEXT);
  922. SetWindowOrgEx(di.hdcDraw, 0, 0, NULL);
  923. SetViewportOrgEx(di.hdcDraw, 0, 0, NULL);
  924. di.bOptimize = TRUE; //since we save the DC we can do this
  925. }
  926. di.prcBounds = &rectBoundsDP;
  927. GetZoomInfo(di);
  928. HRESULT hRes = OnDraw(di);
  929. if (bDeleteDC)
  930. ::DeleteDC(di.hicTargetDev);
  931. if (!bMetafile)
  932. RestoreDC(di.hdcDraw, -1);
  933. return hRes;
  934. }
  935. LRESULT CComControlBase::OnPaint(UINT /* nMsg */, WPARAM /* wParam */,
  936. LPARAM /* lParam */, BOOL& /* lResult */)
  937. {
  938. RECT rc;
  939. PAINTSTRUCT ps;
  940. HDC hdc = ::BeginPaint(m_hWndCD, &ps);
  941. if (hdc == NULL)
  942. return 0;
  943. ::GetClientRect(m_hWndCD, &rc);
  944. ATL_DRAWINFO di;
  945. memset(&di, 0, sizeof(di));
  946. di.cbSize = sizeof(di);
  947. di.dwDrawAspect = DVASPECT_CONTENT;
  948. di.lindex = -1;
  949. di.hdcDraw = hdc;
  950. di.prcBounds = (LPCRECTL)&rc;
  951. OnDrawAdvanced(di);
  952. ::EndPaint(m_hWndCD, &ps);
  953. return 0;
  954. }
  955. #ifndef ATL_NO_NAMESPACE
  956. }; //namespace ATL
  957. #endif
  958. ///////////////////////////////////////////////////////////////////////////////
  959. //All Global stuff goes below this line
  960. ///////////////////////////////////////////////////////////////////////////////
  961. #ifndef _ATL_DLL
  962. ATLAPI_(HDC) AtlCreateTargetDC(HDC hdc, DVTARGETDEVICE* ptd)
  963. {
  964. USES_CONVERSION;
  965. // cases hdc, ptd, hdc is metafile, hic
  966. // NULL, NULL, n/a, Display
  967. // NULL, !NULL, n/a, ptd
  968. // !NULL, NULL, FALSE, hdc
  969. // !NULL, NULL, TRUE, display
  970. // !NULL, !NULL, FALSE, ptd
  971. // !NULL, !NULL, TRUE, ptd
  972. if (ptd != NULL)
  973. {
  974. LPDEVMODEOLE lpDevMode;
  975. LPOLESTR lpszDriverName;
  976. LPOLESTR lpszDeviceName;
  977. LPOLESTR lpszPortName;
  978. if (ptd->tdExtDevmodeOffset == 0)
  979. lpDevMode = NULL;
  980. else
  981. lpDevMode = (LPDEVMODEOLE) ((LPSTR)ptd + ptd->tdExtDevmodeOffset);
  982. lpszDriverName = (LPOLESTR)((BYTE*)ptd + ptd->tdDriverNameOffset);
  983. lpszDeviceName = (LPOLESTR)((BYTE*)ptd + ptd->tdDeviceNameOffset);
  984. lpszPortName = (LPOLESTR)((BYTE*)ptd + ptd->tdPortNameOffset);
  985. return ::CreateDC(OLE2CT(lpszDriverName), OLE2CT(lpszDeviceName),
  986. OLE2CT(lpszPortName), DEVMODEOLE2T(lpDevMode));
  987. }
  988. else if (hdc == NULL || GetDeviceCaps(hdc, TECHNOLOGY) == DT_METAFILE)
  989. return ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
  990. else
  991. return hdc;
  992. }
  993. #define HIMETRIC_PER_INCH 2540
  994. #define MAP_PIX_TO_LOGHIM(x,ppli) ( (HIMETRIC_PER_INCH*(x) + ((ppli)>>1)) / (ppli) )
  995. #define MAP_LOGHIM_TO_PIX(x,ppli) ( ((ppli)*(x) + HIMETRIC_PER_INCH/2) / HIMETRIC_PER_INCH )
  996. ATLAPI_(void) AtlHiMetricToPixel(const SIZEL * lpSizeInHiMetric, LPSIZEL lpSizeInPix)
  997. {
  998. int nPixelsPerInchX; // Pixels per logical inch along width
  999. int nPixelsPerInchY; // Pixels per logical inch along height
  1000. HDC hDCScreen = GetDC(NULL);
  1001. if (hDCScreen) {
  1002. nPixelsPerInchX = GetDeviceCaps(hDCScreen, LOGPIXELSX);
  1003. nPixelsPerInchY = GetDeviceCaps(hDCScreen, LOGPIXELSY);
  1004. ReleaseDC(NULL, hDCScreen);
  1005. } else {
  1006. nPixelsPerInchX = nPixelsPerInchY = 1;
  1007. }
  1008. lpSizeInPix->cx = MAP_LOGHIM_TO_PIX(lpSizeInHiMetric->cx, nPixelsPerInchX);
  1009. lpSizeInPix->cy = MAP_LOGHIM_TO_PIX(lpSizeInHiMetric->cy, nPixelsPerInchY);
  1010. }
  1011. ATLAPI_(void) AtlPixelToHiMetric(const SIZEL * lpSizeInPix, LPSIZEL lpSizeInHiMetric)
  1012. {
  1013. int nPixelsPerInchX; // Pixels per logical inch along width
  1014. int nPixelsPerInchY; // Pixels per logical inch along height
  1015. HDC hDCScreen = GetDC(NULL);
  1016. if (hDCScreen) {
  1017. nPixelsPerInchX = GetDeviceCaps(hDCScreen, LOGPIXELSX);
  1018. nPixelsPerInchY = GetDeviceCaps(hDCScreen, LOGPIXELSY);
  1019. ReleaseDC(NULL, hDCScreen);
  1020. } else {
  1021. nPixelsPerInchX = nPixelsPerInchY = 1;
  1022. }
  1023. lpSizeInHiMetric->cx = MAP_PIX_TO_LOGHIM(lpSizeInPix->cx, nPixelsPerInchX);
  1024. lpSizeInHiMetric->cy = MAP_PIX_TO_LOGHIM(lpSizeInPix->cy, nPixelsPerInchY);
  1025. }
  1026. #endif