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.

1264 lines
30 KiB

  1. /*++
  2. Copyright (C) 1993-1999 Microsoft Corporation
  3. Module Name:
  4. polyline.cpp
  5. Abstract:
  6. Implementation of the CPolyline class that is exposed as a
  7. component object.
  8. --*/
  9. #include "polyline.h"
  10. #include "smonctrl.h"
  11. #include "unihelpr.h"
  12. #include "utils.h"
  13. /*
  14. * CPolyline:CPolyline
  15. * CPolyline::~CPolyline
  16. *
  17. * Constructor Parameters:
  18. * pUnkOuter LPUNKNOWN of the controlling unknown.
  19. * pfnDestroy PFNDESTROYED to call when an object is
  20. * destroyed.
  21. * hInst HINSTANCE of the application we're in.
  22. */
  23. CPolyline::CPolyline (
  24. LPUNKNOWN pUnkOuter,
  25. PFNDESTROYED pfnDestroy )
  26. : m_cRef ( 0 ),
  27. m_pUnkOuter ( pUnkOuter ),
  28. m_pfnDestroy ( pfnDestroy ),
  29. m_fDirty ( FALSE ),
  30. m_pImpIPolyline ( NULL ),
  31. m_pImpIConnPtCont ( NULL ),
  32. m_cf ( 0 ),
  33. m_clsID ( CLSID_SystemMonitor ),
  34. m_pIStorage ( NULL ),
  35. m_pIStream ( NULL ),
  36. m_pImpIPersistStorage ( NULL ),
  37. m_pImpIPersistStreamInit ( NULL ),
  38. m_pImpIPersistPropertyBag ( NULL ),
  39. m_pImpIPerPropertyBrowsing ( NULL ),
  40. m_pImpIDataObject ( NULL ),
  41. m_pImpIObjectSafety ( NULL ),
  42. m_pIDataAdviseHolder ( NULL ),
  43. m_pDefIUnknown ( NULL ),
  44. m_pDefIDataObject ( NULL ),
  45. m_pDefIViewObject ( NULL ),
  46. m_pDefIPersistStorage ( NULL ),
  47. m_pIOleAdviseHolder ( NULL ),
  48. m_pImpIOleObject ( NULL ),
  49. m_pIOleClientSite ( NULL ),
  50. m_pImpIViewObject ( NULL ),
  51. m_pIAdviseSink ( NULL ),
  52. m_dwFrozenAspects ( 0 ),
  53. m_dwAdviseAspects ( 0 ),
  54. m_dwAdviseFlags ( 0 ),
  55. m_pImpIRunnableObject ( NULL ),
  56. m_bIsRunning ( FALSE ),
  57. m_pImpIExternalConnection ( NULL ),
  58. m_fLockContainer ( FALSE ),
  59. m_dwRegROT ( 0L ),
  60. m_pIOleIPSite ( NULL ),
  61. m_pIOleIPFrame ( NULL ),
  62. m_pIOleIPUIWindow ( NULL ),
  63. m_pImpIOleIPObject ( NULL ),
  64. m_pImpIOleIPActiveObject ( NULL ),
  65. m_hMenuShared ( NULL ),
  66. m_hOLEMenu ( NULL ),
  67. m_pHW ( NULL ),
  68. m_fAllowInPlace ( TRUE ),
  69. m_fUIActive ( FALSE ),
  70. m_fContainerKnowsInsideOut ( FALSE ),
  71. m_pImpISpecifyPP ( NULL ),
  72. m_pImpIProvideClassInfo ( NULL ),
  73. m_pImpIDispatch ( NULL ),
  74. m_pImpISystemMonitor ( NULL ),
  75. m_pImpIOleControl ( NULL ),
  76. m_pImpICounters ( NULL ),
  77. m_pImpILogFiles ( NULL ),
  78. m_pITypeLib ( NULL ),
  79. m_pIOleControlSite ( NULL ),
  80. m_pIDispatchAmbients ( NULL ),
  81. m_fFreezeEvents ( FALSE ),
  82. m_fHatch ( TRUE ),
  83. m_pCtrl ( NULL )
  84. {
  85. // Set default extents
  86. SetRect(&m_RectExt, 0, 0, 300, 200);
  87. return;
  88. }
  89. CPolyline::~CPolyline(void)
  90. {
  91. LPUNKNOWN pIUnknown=this;
  92. if (NULL!=m_pUnkOuter)
  93. pIUnknown=m_pUnkOuter;
  94. if (NULL!=m_pHW) {
  95. delete m_pHW;
  96. m_pHW = NULL;
  97. }
  98. if (NULL != m_pCtrl) {
  99. delete m_pCtrl;
  100. m_pCtrl = NULL;
  101. }
  102. /*
  103. * In aggregation, release cached pointers but
  104. * AddRef the controlling unknown first.
  105. */
  106. pIUnknown->AddRef();
  107. pIUnknown->AddRef();
  108. pIUnknown->AddRef();
  109. ReleaseInterface(m_pDefIViewObject);
  110. ReleaseInterface(m_pDefIDataObject);
  111. ReleaseInterface(m_pDefIPersistStorage);
  112. //Cached pointer rules do not apply to IUnknown
  113. ReleaseInterface(m_pDefIUnknown);
  114. ReleaseInterface(m_pIAdviseSink);
  115. ReleaseInterface(m_pIOleClientSite);
  116. ReleaseInterface(m_pIOleAdviseHolder);
  117. DeleteInterfaceImp(m_pImpIOleObject);
  118. DeleteInterfaceImp(m_pImpIViewObject);
  119. DeleteInterfaceImp(m_pImpIRunnableObject);
  120. //Other in-place interfaces released in deactivation.
  121. DeleteInterfaceImp(m_pImpIOleIPObject);
  122. DeleteInterfaceImp(m_pImpIOleIPActiveObject);
  123. ReleaseInterface(m_pIDispatchAmbients);
  124. ReleaseInterface(m_pIOleControlSite);
  125. ReleaseInterface(m_pITypeLib);
  126. DeleteInterfaceImp(m_pImpISpecifyPP);
  127. DeleteInterfaceImp(m_pImpIProvideClassInfo);
  128. DeleteInterfaceImp(m_pImpIDispatch);
  129. DeleteInterfaceImp(m_pImpISystemMonitor);
  130. DeleteInterfaceImp(m_pImpIOleControl);
  131. DeleteInterfaceImp(m_pImpICounters);
  132. DeleteInterfaceImp(m_pImpILogFiles);
  133. //Anything we might have registered in IRunnableObject::Run
  134. if (m_dwRegROT != 0)
  135. {
  136. IRunningObjectTable *pROT;
  137. if (!FAILED(GetRunningObjectTable(0, &pROT)))
  138. {
  139. pROT->Revoke(m_dwRegROT);
  140. pROT->Release();
  141. }
  142. }
  143. DeleteInterfaceImp(m_pImpIExternalConnection);
  144. ReleaseInterface(m_pIDataAdviseHolder);
  145. DeleteInterfaceImp(m_pImpIDataObject);
  146. DeleteInterfaceImp(m_pImpIObjectSafety);
  147. DeleteInterfaceImp(m_pImpIPersistStreamInit);
  148. DeleteInterfaceImp(m_pImpIPersistStorage);
  149. DeleteInterfaceImp(m_pImpIPersistPropertyBag);
  150. DeleteInterfaceImp(m_pImpIPerPropertyBrowsing);
  151. ReleaseInterface(m_pIStream);
  152. ReleaseInterface(m_pIStorage);
  153. DeleteInterfaceImp(m_pImpIConnPtCont);
  154. DeleteInterfaceImp(m_pImpIPolyline);
  155. return;
  156. }
  157. /*
  158. * CPolyline::Init
  159. *
  160. * Purpose:
  161. * Performs any intiailization of a CPolyline that's prone to
  162. * failure that we also use internally before exposing the
  163. * object outside this DLL.
  164. *
  165. * Parameters:
  166. * None
  167. *
  168. * Return Value:
  169. * BOOL TRUE if the function is successful,
  170. * FALSE otherwise.
  171. */
  172. BOOL CPolyline::Init(void)
  173. {
  174. LPUNKNOWN pIUnknown=this;
  175. HRESULT hr;
  176. INT i;
  177. if (NULL!=m_pUnkOuter)
  178. pIUnknown=m_pUnkOuter;
  179. m_cf=(CLIPFORMAT)RegisterClipboardFormat(SZSYSMONCLIPFORMAT);
  180. m_pImpIPersistStorage=new CImpIPersistStorage(this, pIUnknown);
  181. if (NULL==m_pImpIPersistStorage)
  182. return FALSE;
  183. m_pImpIPersistStreamInit=new CImpIPersistStreamInit(this, pIUnknown);
  184. if (NULL==m_pImpIPersistStreamInit)
  185. return FALSE;
  186. m_pImpIPersistPropertyBag=new CImpIPersistPropertyBag(this, pIUnknown);
  187. if (NULL==m_pImpIPersistPropertyBag)
  188. return FALSE;
  189. m_pImpIPerPropertyBrowsing=new CImpIPerPropertyBrowsing(this, pIUnknown);
  190. if (NULL==m_pImpIPerPropertyBrowsing)
  191. return FALSE;
  192. m_pImpIPolyline=new CImpIPolyline(this, pIUnknown);
  193. if (NULL==m_pImpIPolyline)
  194. return FALSE;
  195. m_pImpIConnPtCont=new CImpIConnPtCont(this, pIUnknown);
  196. if (NULL==m_pImpIConnPtCont)
  197. return FALSE;
  198. for (i=0; i<CONNECTION_POINT_CNT; i++) {
  199. m_ConnectionPoint[i].Init(this, pIUnknown, i);
  200. }
  201. m_pImpIDataObject=new CImpIDataObject(this, pIUnknown);
  202. if (NULL==m_pImpIDataObject)
  203. return FALSE;
  204. m_pImpIOleObject=new CImpIOleObject(this, pIUnknown);
  205. if (NULL==m_pImpIOleObject)
  206. return FALSE;
  207. m_pImpIViewObject=new CImpIViewObject(this, pIUnknown);
  208. if (NULL==m_pImpIViewObject)
  209. return FALSE;
  210. m_pImpIRunnableObject=new CImpIRunnableObject(this, pIUnknown);
  211. if (NULL==m_pImpIRunnableObject)
  212. return FALSE;
  213. /***********************************
  214. m_pImpIExternalConnection=new CImpIExternalConnection(this
  215. , pIUnknown);
  216. if (NULL==m_pImpIExternalConnection)
  217. return FALSE;
  218. ************************************/
  219. m_pImpIOleIPObject=new CImpIOleInPlaceObject(this, pIUnknown);
  220. if (NULL==m_pImpIOleIPObject)
  221. return FALSE;
  222. m_pImpIOleIPActiveObject=new CImpIOleInPlaceActiveObject(this
  223. , pIUnknown);
  224. if (NULL==m_pImpIOleIPActiveObject)
  225. return FALSE;
  226. m_pImpISpecifyPP=new CImpISpecifyPP(this, pIUnknown);
  227. if (NULL==m_pImpISpecifyPP)
  228. return FALSE;
  229. m_pImpIProvideClassInfo=new CImpIProvideClassInfo(this, pIUnknown);
  230. if (NULL==m_pImpIProvideClassInfo)
  231. return FALSE;
  232. m_pImpISystemMonitor=new CImpISystemMonitor(this, pIUnknown);
  233. if (NULL==m_pImpISystemMonitor)
  234. return FALSE;
  235. m_pImpICounters = new CImpICounters(this, pIUnknown);
  236. if (NULL==m_pImpICounters)
  237. return FALSE;
  238. m_pImpILogFiles = new CImpILogFiles(this, pIUnknown);
  239. if (NULL==m_pImpILogFiles)
  240. return FALSE;
  241. m_pImpIDispatch=new CImpIDispatch(this, pIUnknown);
  242. if (NULL==m_pImpIDispatch)
  243. return FALSE;
  244. m_pImpIDispatch->SetInterface(DIID_DISystemMonitor, m_pImpISystemMonitor);
  245. m_pImpIOleControl=new CImpIOleControl(this, pIUnknown);
  246. if (NULL==m_pImpIOleControl)
  247. return FALSE;
  248. m_pImpIObjectSafety = new CImpIObjectSafety(this, pIUnknown);
  249. if (NULL == m_pImpIObjectSafety) {
  250. return FALSE;
  251. }
  252. m_pCtrl = new CSysmonControl(this);
  253. if (NULL==m_pCtrl)
  254. return FALSE;
  255. if ( !m_pCtrl->AllocateSubcomponents() )
  256. return FALSE;
  257. /*
  258. * We're sitting at ref count 0 and the next call will AddRef a
  259. * few times and Release a few times. This insures we don't
  260. * delete ourselves prematurely.
  261. */
  262. m_cRef++;
  263. //Aggregate OLE's cache for IOleCache* interfaces.
  264. hr=CreateDataCache(pIUnknown, CLSID_SystemMonitor
  265. , IID_IUnknown, (PPVOID)&m_pDefIUnknown);
  266. if (FAILED(hr))
  267. return FALSE;
  268. /*
  269. * NOTE: The spec specifically states that any interfaces
  270. * besides IUnknown that we obtain on an aggregated object
  271. * should be Released immediately after we QueryInterface for
  272. * them because the QueryInterface will AddRef us, and since
  273. * we would not release these interfaces until we were
  274. * destroyed, we'd never go away because we'd never get a zero
  275. * ref count.
  276. */
  277. //Now try to get other interfaces to which we delegate
  278. hr=m_pDefIUnknown->QueryInterface(IID_IViewObject2
  279. , (PPVOID)&m_pDefIViewObject);
  280. if (FAILED(hr))
  281. return FALSE;
  282. pIUnknown->Release();
  283. hr=m_pDefIUnknown->QueryInterface(IID_IDataObject
  284. , (PPVOID)&m_pDefIDataObject);
  285. if (FAILED(hr))
  286. return FALSE;
  287. pIUnknown->Release();
  288. hr=m_pDefIUnknown->QueryInterface(IID_IPersistStorage
  289. , (PPVOID)&m_pDefIPersistStorage);
  290. if (FAILED(hr))
  291. return FALSE;
  292. pIUnknown->Release();
  293. m_cRef--;
  294. m_pImpIPolyline->New();
  295. /*
  296. * Go load our own type information and save its ITypeLib
  297. * pointer that will be used be CImpIDispatch and
  298. * CImpIProvideClassInfo.
  299. */
  300. hr=LoadRegTypeLib(LIBID_SystemMonitor, SMONCTRL_MAJ_VERSION, SMONCTRL_MIN_VERSION
  301. , LANG_NEUTRAL, &m_pITypeLib);
  302. if (FAILED(hr))
  303. hr=LoadTypeLib(OLESTR("SYSMON.TLB"), &m_pITypeLib);
  304. if (FAILED(hr))
  305. return FALSE;
  306. //Set up our CONTROLINFO structure (we have two mnemonics)
  307. m_ctrlInfo.cb=sizeof(CONTROLINFO);
  308. m_ctrlInfo.dwFlags=0;
  309. m_ctrlInfo.hAccel=NULL;
  310. m_ctrlInfo.cAccel=0;
  311. /*
  312. * Note: we cannot initialize ambients until we get
  313. * a container interface pointer in IOleObject::SetClientSite.
  314. */
  315. return TRUE;
  316. }
  317. /*
  318. * CPolyline::QueryInterface
  319. * CPolyline::AddRef
  320. * CPolyline::Release
  321. *
  322. * Purpose:
  323. * IUnknown members for CPolyline object.
  324. */
  325. STDMETHODIMP CPolyline::QueryInterface(REFIID riid, PPVOID ppv)
  326. {
  327. *ppv=NULL;
  328. if (IID_IUnknown==riid)
  329. *ppv=this;
  330. else if (IID_IConnectionPointContainer==riid)
  331. *ppv=m_pImpIConnPtCont;
  332. else if (IID_IPersistStorage==riid)
  333. *ppv=m_pImpIPersistStorage;
  334. else if (IID_IPersist==riid || IID_IPersistStream==riid
  335. || IID_IPersistStreamInit==riid)
  336. *ppv=m_pImpIPersistStreamInit;
  337. else if (IID_IPersistPropertyBag==riid )
  338. *ppv=m_pImpIPersistPropertyBag;
  339. else if (IID_IPerPropertyBrowsing==riid )
  340. *ppv=m_pImpIPerPropertyBrowsing;
  341. else if (IID_IDataObject==riid)
  342. *ppv=m_pImpIDataObject;
  343. else if (IID_IOleObject==riid)
  344. *ppv=m_pImpIOleObject;
  345. else if (IID_IViewObject==riid || IID_IViewObject2==riid)
  346. *ppv=m_pImpIViewObject;
  347. else if (IID_IRunnableObject==riid)
  348. // *ppv=m_pImpIRunnableObject;
  349. return E_NOINTERFACE;
  350. else if (IID_IExternalConnection==riid)
  351. *ppv=m_pImpIExternalConnection;
  352. //IOleWindow will be the InPlaceObject
  353. else if (IID_IOleWindow==riid || IID_IOleInPlaceObject==riid)
  354. *ppv=m_pImpIOleIPObject;
  355. // The OLE rule state that InPlaceActiveObject should not be
  356. // provided in response to a query, but the current MFC (4.0)
  357. // won't work if we don't do it.
  358. else if (IID_IOleInPlaceActiveObject==riid)
  359. *ppv=m_pImpIOleIPActiveObject;
  360. else if (IID_ISpecifyPropertyPages==riid)
  361. *ppv=m_pImpISpecifyPP;
  362. else if (IID_IProvideClassInfo==riid)
  363. *ppv=m_pImpIProvideClassInfo;
  364. else if (IID_IDispatch==riid || DIID_DISystemMonitor==riid)
  365. *ppv=m_pImpIDispatch;
  366. else if (IID_ISystemMonitor==riid)
  367. *ppv=m_pImpISystemMonitor;
  368. else if (IID_IOleControl==riid)
  369. *ppv=m_pImpIOleControl;
  370. //Use the default handler's cache.
  371. else if (IID_IOleCache==riid || IID_IOleCache2==riid)
  372. return m_pDefIUnknown->QueryInterface(riid, ppv);
  373. else if (IID_IObjectSafety == riid) {
  374. *ppv = m_pImpIObjectSafety;
  375. }
  376. if (NULL!=*ppv)
  377. {
  378. ((LPUNKNOWN)*ppv)->AddRef();
  379. return NOERROR;
  380. }
  381. return E_NOINTERFACE;
  382. }
  383. STDMETHODIMP_(ULONG) CPolyline::AddRef(void)
  384. {
  385. return ++m_cRef;
  386. }
  387. STDMETHODIMP_(ULONG) CPolyline::Release(void)
  388. {
  389. if (0L!=--m_cRef)
  390. return m_cRef;
  391. // Prevent reentrant call
  392. m_cRef++;
  393. if (NULL!=m_pfnDestroy)
  394. (*m_pfnDestroy)();
  395. delete this;
  396. return 0L;
  397. }
  398. /*
  399. * CPolyline::RectConvertMappings
  400. *
  401. * Purpose:
  402. * Converts the contents of a rectangle from device (MM_TEXT) or
  403. * HIMETRIC to the other.
  404. *
  405. * Parameters:
  406. * pRect LPRECT containing the rectangle to convert.
  407. * fToDevice BOOL TRUE to convert from HIMETRIC to device,
  408. * FALSE to convert device to HIMETRIC.
  409. *
  410. * Return Value:
  411. * None
  412. */
  413. void
  414. CPolyline::RectConvertMappings(LPRECT pRect, BOOL fToDevice)
  415. {
  416. HDC hDC = NULL;
  417. INT iLpx, iLpy;
  418. if ( NULL != pRect ) {
  419. hDC=GetDC(NULL);
  420. if ( NULL != hDC ) {
  421. iLpx=GetDeviceCaps(hDC, LOGPIXELSX);
  422. iLpy=GetDeviceCaps(hDC, LOGPIXELSY);
  423. ReleaseDC(NULL, hDC);
  424. if (fToDevice) {
  425. pRect->left=MulDiv(iLpx, pRect->left, HIMETRIC_PER_INCH);
  426. pRect->top =MulDiv(iLpy, pRect->top , HIMETRIC_PER_INCH);
  427. pRect->right =MulDiv(iLpx, pRect->right, HIMETRIC_PER_INCH);
  428. pRect->bottom=MulDiv(iLpy, pRect->bottom,HIMETRIC_PER_INCH);
  429. } else {
  430. if ( 0 != iLpx && 0 != iLpy ) {
  431. pRect->left=MulDiv(pRect->left, HIMETRIC_PER_INCH, iLpx);
  432. pRect->top =MulDiv(pRect->top , HIMETRIC_PER_INCH, iLpy);
  433. pRect->right =MulDiv(pRect->right, HIMETRIC_PER_INCH, iLpx);
  434. pRect->bottom=MulDiv(pRect->bottom,HIMETRIC_PER_INCH, iLpy);
  435. }
  436. }
  437. }
  438. }
  439. return;
  440. }
  441. /*
  442. * CPolyline::RenderBitmap
  443. *
  444. * Purpose:
  445. * Creates a bitmap image of the current Polyline.
  446. *
  447. * Parameters:
  448. * phBmp HBITMAP * in which to return the bitmap.
  449. *
  450. * Return Value:
  451. * HRESULT NOERROR if successful, otherwise a
  452. * POLYLINE_E_ value.
  453. */
  454. STDMETHODIMP
  455. CPolyline::RenderBitmap(
  456. HBITMAP *phBmp,
  457. HDC hAttribDC )
  458. {
  459. //HDC hDC;
  460. HRESULT hr = NOERROR;
  461. HDC hMemDC;
  462. HBITMAP hBmp = NULL;
  463. RECT rc;
  464. HGDIOBJ hObj;
  465. HWND hWnd;
  466. if (NULL==phBmp) {
  467. hr = POLYLINE_E_INVALIDPOINTER;
  468. } else if ( NULL == hAttribDC ) {
  469. hr = E_INVALIDARG;
  470. } else {
  471. hWnd = m_pCtrl->Window();
  472. if ( NULL != hWnd ) {
  473. //Render a bitmap the size of the current rectangle.
  474. hMemDC = CreateCompatibleDC(hAttribDC);
  475. if ( NULL != hMemDC ) {
  476. GetClientRect(hWnd, &rc);
  477. hBmp = CreateCompatibleBitmap(hAttribDC, rc.right, rc.bottom);
  478. if (NULL!=hBmp) {
  479. //Draw the control into the bitmap.
  480. hObj = SelectObject(hMemDC, hBmp);
  481. Draw(hMemDC, hAttribDC, FALSE, TRUE, &rc);
  482. SelectObject(hMemDC, hObj);
  483. }
  484. DeleteDC(hMemDC);
  485. // ReleaseDC(hWnd, hDC);
  486. }
  487. *phBmp=hBmp;
  488. hr = NOERROR;
  489. } else {
  490. hr = E_UNEXPECTED;
  491. }
  492. }
  493. return hr;
  494. }
  495. /*
  496. * CPolyline::RenderMetafilePict
  497. *
  498. * Purpose:
  499. * Renders the current Polyline into a METAFILEPICT structure in
  500. * global memory.
  501. *
  502. * Parameters:
  503. * phMem HGLOBAL * in which to return the
  504. * METAFILEPICT.
  505. *
  506. * Return Value:
  507. * HRESULT NOERROR if successful, otherwise a
  508. * POLYLINE_E_ value.
  509. */
  510. STDMETHODIMP
  511. CPolyline::RenderMetafilePict(
  512. HGLOBAL *phMem,
  513. HDC hAttribDC )
  514. {
  515. HGLOBAL hMem;
  516. HMETAFILE hMF;
  517. LPMETAFILEPICT pMF;
  518. RECT rc;
  519. HDC hDC;
  520. if (NULL==phMem)
  521. return POLYLINE_E_INVALIDPOINTER;
  522. //Create a memory metafile and return its handle.
  523. hDC=(HDC)CreateMetaFile(NULL);
  524. if (NULL==hDC)
  525. return STG_E_MEDIUMFULL;
  526. SetMapMode(hDC, MM_ANISOTROPIC);
  527. //
  528. // Always set up the window extents to the real window size
  529. // so the drawing routines can work in their normal dev coords
  530. //
  531. /********* Use the extent rect, not the window rect *********/
  532. rc = m_RectExt;
  533. // GetClientRect(m_pCtrl->Window(), &rc);
  534. /************************************************************/
  535. Draw( hDC, hAttribDC, TRUE, TRUE, &rc );
  536. hMF=CloseMetaFile(hDC);
  537. if (NULL==hMF)
  538. return STG_E_MEDIUMFULL;
  539. //Allocate the METAFILEPICT structure.
  540. hMem=GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE
  541. , sizeof(METAFILEPICT));
  542. if (NULL==hMem)
  543. {
  544. DeleteMetaFile(hMF);
  545. return E_FAIL;
  546. }
  547. /*
  548. * Global lock only fails in PMODE if the selector is invalid
  549. * (like it was discarded) or references a 0 length segment,
  550. * neither of which can happen here.
  551. */
  552. pMF=(LPMETAFILEPICT)GlobalLock(hMem);
  553. pMF->hMF=hMF;
  554. pMF->mm=MM_ANISOTROPIC;
  555. //Insert the extents in MM_HIMETRIC units.
  556. /********* Use the extent rect, not the window rect *********/
  557. rc = m_RectExt;
  558. // GetClientRect(m_pCtrl->Window(), &rc);
  559. /************************************************************/
  560. RectConvertMappings(&rc, FALSE);
  561. pMF->xExt=rc.right;
  562. pMF->yExt=rc.bottom;
  563. GlobalUnlock(hMem);
  564. *phMem=hMem;
  565. return NOERROR;
  566. }
  567. /*
  568. * CPolyline::SendAdvise
  569. *
  570. * Purpose:
  571. * Calls the appropriate IOleClientSite or IAdviseSink member
  572. * function for various events such as closure, renaming, etc.
  573. *
  574. * Parameters:
  575. * uCode UINT OBJECTCODE_* identifying the notification.
  576. *
  577. * Return Value:
  578. * None
  579. */
  580. void CPolyline::SendAdvise(UINT uCode)
  581. {
  582. DWORD dwAspect=DVASPECT_CONTENT | DVASPECT_THUMBNAIL;
  583. switch (uCode)
  584. {
  585. case OBJECTCODE_SAVED:
  586. if (NULL!=m_pIOleAdviseHolder)
  587. m_pIOleAdviseHolder->SendOnSave();
  588. break;
  589. case OBJECTCODE_CLOSED:
  590. if (NULL!=m_pIOleAdviseHolder)
  591. m_pIOleAdviseHolder->SendOnClose();
  592. break;
  593. case OBJECTCODE_RENAMED:
  594. //Call IOleAdviseHolder::SendOnRename (later)
  595. break;
  596. case OBJECTCODE_SAVEOBJECT:
  597. if (m_fDirty && NULL!=m_pIOleClientSite)
  598. m_pIOleClientSite->SaveObject();
  599. m_fDirty=FALSE;
  600. break;
  601. case OBJECTCODE_DATACHANGED:
  602. m_fDirty=TRUE;
  603. //No flags are necessary here.
  604. if (NULL!=m_pIDataAdviseHolder)
  605. {
  606. m_pIDataAdviseHolder->SendOnDataChange
  607. (m_pImpIDataObject, 0, 0);
  608. }
  609. if ( ( NULL!=m_pIAdviseSink )
  610. & (dwAspect & m_dwAdviseAspects))
  611. {
  612. m_pIAdviseSink->OnViewChange(dwAspect
  613. & m_dwAdviseAspects, 0);
  614. }
  615. break;
  616. case OBJECTCODE_SHOWWINDOW:
  617. if (NULL!=m_pIOleClientSite)
  618. m_pIOleClientSite->OnShowWindow(TRUE);
  619. break;
  620. case OBJECTCODE_HIDEWINDOW:
  621. if (NULL!=m_pIOleClientSite)
  622. m_pIOleClientSite->OnShowWindow(FALSE);
  623. break;
  624. case OBJECTCODE_SHOWOBJECT:
  625. if (NULL!=m_pIOleClientSite)
  626. m_pIOleClientSite->ShowObject();
  627. break;
  628. }
  629. return;
  630. }
  631. /*
  632. * CPolyline::SendEvent
  633. *
  634. * Purpose:
  635. * Send an event to all connection points.
  636. *
  637. *
  638. * Parameters:
  639. * uEventType Event Type
  640. * dwParam Parameter to send with event.
  641. *
  642. * Return Value:
  643. * None
  644. */
  645. void CPolyline::SendEvent (
  646. IN UINT uEventType,
  647. IN DWORD dwParam
  648. )
  649. {
  650. INT i;
  651. // Don't send if container has frozen events
  652. if (m_fFreezeEvents)
  653. return;
  654. // Pass event to each connection point
  655. for (i=0; i<CONNECTION_POINT_CNT; i++) {
  656. m_ConnectionPoint[i].SendEvent(uEventType, dwParam);
  657. }
  658. }
  659. /*
  660. * CPolyline::InPlaceActivate
  661. *
  662. * Purpose:
  663. * Goes through all the steps of activating the Polyline as an
  664. * in-place object.
  665. *
  666. * Parameters:
  667. * pActiveSite LPOLECLIENTSITE of the active site we show in.
  668. * fIncludeUI BOOL controls whether we call UIActivate too.
  669. *
  670. * Return Value:
  671. * HRESULT Whatever error code is appropriate.
  672. */
  673. HRESULT CPolyline::InPlaceActivate(LPOLECLIENTSITE pActiveSite
  674. , BOOL fIncludeUI)
  675. {
  676. HRESULT hr;
  677. HWND hWndSite;
  678. HWND hWndHW;
  679. HWND hWndCtrl;
  680. RECT rcPos;
  681. RECT rcClip;
  682. OLEINPLACEFRAMEINFO frameInfo;
  683. if (NULL==pActiveSite)
  684. return E_POINTER;
  685. // If we already have a site, just handle UI
  686. if (NULL != m_pIOleIPSite)
  687. {
  688. if (fIncludeUI) {
  689. UIActivate();
  690. SetFocus(m_pCtrl->Window());
  691. }
  692. return NOERROR;
  693. }
  694. // Initialization, obtaining interfaces, OnInPlaceActivate.
  695. hr=pActiveSite->QueryInterface(IID_IOleInPlaceSite
  696. , (PPVOID)&m_pIOleIPSite);
  697. if (FAILED(hr))
  698. return hr;
  699. hr=m_pIOleIPSite->CanInPlaceActivate();
  700. if (NOERROR!=hr)
  701. {
  702. m_pIOleIPSite->Release();
  703. m_pIOleIPSite=NULL;
  704. return E_FAIL;
  705. }
  706. m_pIOleIPSite->OnInPlaceActivate();
  707. // Get the window context and create a window.
  708. m_pIOleIPSite->GetWindow(&hWndSite);
  709. frameInfo.cb=sizeof(OLEINPLACEFRAMEINFO);
  710. m_pIOleIPSite->GetWindowContext(&m_pIOleIPFrame
  711. , &m_pIOleIPUIWindow, &rcPos, &rcClip, &frameInfo);
  712. /*
  713. * Create the hatch window after we get a parent window. We
  714. * could not create the hatch window sooner because had nothing
  715. * to use for the parent.
  716. */
  717. m_pHW=new CHatchWin();
  718. if (NULL==m_pHW)
  719. {
  720. InPlaceDeactivate();
  721. return E_OUTOFMEMORY;
  722. }
  723. if (!m_pHW->Init(hWndSite, ID_HATCHWINDOW, NULL))
  724. {
  725. InPlaceDeactivate();
  726. return E_OUTOFMEMORY;
  727. }
  728. hr=m_pImpIRunnableObject->Run(NULL);
  729. // Move the hatch window to the container window.
  730. hWndHW = m_pHW->Window();
  731. SetParent(hWndHW, hWndSite);
  732. // Move the Polyline window from the hidden dialog to hatch window
  733. hWndCtrl = m_pCtrl->Window();
  734. m_pHW->HwndAssociateSet(hWndCtrl);
  735. m_pHW->ChildSet(hWndCtrl);
  736. m_pHW->RectsSet(&rcPos, &rcClip); //Positions polyline
  737. ShowWindow(hWndHW, SW_SHOW);
  738. SendAdvise(OBJECTCODE_SHOWOBJECT);
  739. // Critical for accelerators to work initially.
  740. SetFocus(hWndCtrl);
  741. if (fIncludeUI)
  742. hr = UIActivate();
  743. else
  744. hr = NOERROR;
  745. /*
  746. * Since we don't have an Undo while in-place, tell the continer
  747. * to free it's undo state immediately.
  748. */
  749. m_pIOleIPSite->DiscardUndoState();
  750. return hr;
  751. }
  752. /*
  753. * CPolyline::InPlaceDeactivate
  754. *
  755. * Purpose:
  756. * Reverses all the activation steps from InPlaceActivate.
  757. *
  758. * Parameters:
  759. * None
  760. *
  761. * Return Value:
  762. * None
  763. */
  764. void CPolyline::InPlaceDeactivate(void)
  765. {
  766. UIDeactivate();
  767. if (NULL!=m_pHW)
  768. {
  769. ShowWindow(m_pHW->Window(), SW_HIDE);
  770. // Move the window to its foster home
  771. if (m_pCtrl->Window()) {
  772. SetParent(m_pCtrl->Window(), g_hWndFoster);
  773. }
  774. m_pHW->ChildSet(NULL);
  775. delete m_pHW;
  776. m_pHW=NULL;
  777. }
  778. ReleaseInterface(m_pIOleIPFrame);
  779. ReleaseInterface(m_pIOleIPUIWindow)
  780. if (NULL!=m_pIOleIPSite)
  781. {
  782. m_pIOleIPSite->OnInPlaceDeactivate();
  783. ReleaseInterface(m_pIOleIPSite);
  784. }
  785. return;
  786. }
  787. /*
  788. * CPolyline::UIActivate
  789. *
  790. * Purpose:
  791. * Goes through all the steps of activating the user interface of
  792. * Polyline as an in-place object.
  793. *
  794. * Parameters:
  795. * None
  796. *
  797. * Return Value:
  798. * HRESULT NOERROR or error code.
  799. */
  800. HRESULT CPolyline::UIActivate(void)
  801. {
  802. LPWSTR szUserType;
  803. USES_CONVERSION
  804. // If already UI active, just return
  805. if (m_fUIActive)
  806. return NOERROR;
  807. m_fUIActive = TRUE;
  808. // Show hatched border only if enabled
  809. if (m_fHatch)
  810. m_pHW->ShowHatch(TRUE);
  811. // Call IOleInPlaceSite::UIActivate
  812. if (NULL!=m_pIOleIPSite)
  813. m_pIOleIPSite->OnUIActivate();
  814. // Set the active object
  815. szUserType = T2W(ResourceString(IDS_USERTYPE));
  816. if (NULL != m_pIOleIPFrame)
  817. m_pIOleIPFrame->SetActiveObject(m_pImpIOleIPActiveObject, szUserType);
  818. if (NULL != m_pIOleIPUIWindow)
  819. m_pIOleIPUIWindow->SetActiveObject(m_pImpIOleIPActiveObject, szUserType);
  820. // Negotiate border space. None needed.
  821. if (NULL != m_pIOleIPFrame)
  822. m_pIOleIPFrame->SetBorderSpace(NULL);
  823. if (NULL != m_pIOleIPUIWindow)
  824. m_pIOleIPUIWindow->SetBorderSpace(NULL);
  825. // Create the shared menu. No items added.
  826. if (NULL != m_pIOleIPFrame)
  827. m_pIOleIPFrame->SetMenu(NULL, NULL, m_pCtrl->Window());
  828. return NOERROR;
  829. }
  830. /*
  831. * CPolyline::UIDeactivate
  832. *
  833. * Purpose:
  834. * Reverses all the user interface activation steps from
  835. * UIActivate.
  836. *
  837. * Parameters:
  838. * None
  839. *
  840. * Return Value:
  841. * None
  842. */
  843. void CPolyline::UIDeactivate(void)
  844. {
  845. if (!m_fUIActive){
  846. return;
  847. }
  848. m_fUIActive=FALSE;
  849. // Hide hatched border if enabled
  850. if (m_fHatch && NULL != m_pHW ){
  851. m_pHW->ShowHatch(FALSE);
  852. }
  853. // Tell frame and UI Window we aren't active
  854. if (NULL!=m_pIOleIPFrame){
  855. m_pIOleIPFrame->SetActiveObject(NULL, NULL);
  856. }
  857. if (NULL!=m_pIOleIPUIWindow){
  858. m_pIOleIPUIWindow->SetActiveObject(NULL, NULL);
  859. }
  860. //We don't have any shared menu or tools to clean up.
  861. if (NULL!=m_pIOleIPSite){
  862. m_pIOleIPSite->OnUIDeactivate(FALSE);
  863. }
  864. }
  865. /*
  866. * AmbientGet
  867. *
  868. * Purpose:
  869. * Retrieves a specific ambient property into a VARIANT.
  870. *
  871. * Parameters:
  872. * dispID DISPID of the property to retrieve.
  873. * pva VARIANT * to fill with the new value.
  874. *
  875. * Return value
  876. * BOOL TRUE if the ambient was retrieved, FALSE
  877. * otherwise.
  878. */
  879. BOOL CPolyline::AmbientGet(DISPID dispID, VARIANT *pva)
  880. {
  881. HRESULT hr;
  882. DISPPARAMS dp;
  883. if (NULL==pva)
  884. return FALSE;
  885. if (NULL==m_pIDispatchAmbients)
  886. return FALSE;
  887. SETNOPARAMS(dp);
  888. hr=m_pIDispatchAmbients->Invoke(dispID, IID_NULL
  889. , LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET
  890. , &dp, pva, NULL, NULL);
  891. return SUCCEEDED(hr);
  892. }
  893. /*
  894. * AmbientsInitialize
  895. *
  896. * Purpose:
  897. * Attempts to retrieve the container's ambient properties
  898. * and initialize (or reinitialize) Polyline accordingly.
  899. *
  900. * Parameters:
  901. * dwWhich DWORD containing INITAMBIENT_... flags
  902. * describing which ambients to initialize.
  903. * This can be any combination.
  904. *
  905. * Return Value:
  906. * None
  907. */
  908. void CPolyline::AmbientsInitialize(DWORD dwWhich)
  909. {
  910. VARIANT va;
  911. LPFONT pIFont,pIFontClone;
  912. LPFONTDISP pIFontDisp;
  913. if (NULL == m_pIDispatchAmbients)
  914. return;
  915. /*
  916. * We need to retrieve these ambients into these variables:
  917. *
  918. * Ambient Property: Variable:
  919. * -----------------------------------------------
  920. * DISPID_AMBIENT_SHOWHATCHING m_fHatch
  921. * DISPID_AMBIENT_UIDEAD m_fUIDead
  922. * DISPID_AMBIENT_BACKCOLOR m_pCtrl...
  923. * DISPID_AMBIENT_FONT ..... m_pCtrl...
  924. * DISPID_AMBIENT_FORECOLOR m_pCtrl...
  925. * DISPID_AMBIENT_APPEARANCE m_pCtrl...
  926. * DISPID_AMBIENT_USERMODE m_pCtrl...
  927. */
  928. VariantInit(&va);
  929. if ((INITAMBIENT_SHOWHATCHING & dwWhich)
  930. &&AmbientGet(DISPID_AMBIENT_SHOWHATCHING, &va)) {
  931. m_fHatch=V_BOOL(&va);
  932. if (NULL != m_pHW)
  933. m_pHW->ShowHatch(m_fHatch && m_fUIActive);
  934. }
  935. if ((INITAMBIENT_UIDEAD & dwWhich)
  936. && AmbientGet(DISPID_AMBIENT_UIDEAD, &va)) {
  937. m_pCtrl->m_fUIDead = (BOOLEAN)V_BOOL(&va);
  938. }
  939. if ((INITAMBIENT_USERMODE & dwWhich)
  940. && AmbientGet(DISPID_AMBIENT_USERMODE, &va)) {
  941. m_pCtrl->m_fUserMode = (BOOLEAN)V_BOOL(&va);
  942. }
  943. if ((INITAMBIENT_APPEARANCE & dwWhich)
  944. && AmbientGet(DISPID_AMBIENT_APPEARANCE, &va)) {
  945. m_pCtrl->put_Appearance(V_I4(&va), TRUE);
  946. }
  947. if ((INITAMBIENT_BACKCOLOR & dwWhich)
  948. && AmbientGet(DISPID_AMBIENT_BACKCOLOR, &va)) {
  949. m_pCtrl->put_BackPlotColor(V_I4(&va), TRUE);
  950. }
  951. if ((INITAMBIENT_FORECOLOR & dwWhich)
  952. && AmbientGet(DISPID_AMBIENT_FORECOLOR, &va)) {
  953. m_pCtrl->put_FgndColor(V_I4(&va), TRUE);
  954. }
  955. if ((INITAMBIENT_FONT & dwWhich)
  956. && AmbientGet(DISPID_AMBIENT_FONT, &va)) {
  957. pIFontDisp = (LPFONTDISP)V_DISPATCH(&va);
  958. if (pIFontDisp != NULL) {
  959. if (SUCCEEDED(pIFontDisp->QueryInterface(IID_IFont, (PPVOID)&pIFont))) {
  960. if (SUCCEEDED(pIFont->Clone(&pIFontClone))) {
  961. m_pCtrl->put_Font(pIFontClone, TRUE);
  962. pIFontClone->Release();
  963. }
  964. pIFont->Release();
  965. }
  966. pIFontDisp->Release();
  967. }
  968. }
  969. }