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.

1698 lines
49 KiB

  1. //=--------------------------------------------------------------------------=
  2. // CtlMisc.Cpp
  3. //=--------------------------------------------------------------------------=
  4. // Copyright 1995-1996 Microsoft Corporation. All Rights Reserved.
  5. //
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  7. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  8. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  9. // PARTICULAR PURPOSE.
  10. //=--------------------------------------------------------------------------=
  11. //
  12. // things that aren't elsewhere, such as property pages, and connection
  13. // points.
  14. #include "IPServer.H"
  15. #include "CtrlObj.H"
  16. #include "CtlHelp.H"
  17. #include "Globals.H"
  18. #include "StdEnum.H"
  19. #include "Util.H"
  20. #include <stdarg.h>
  21. // for ASSERT and FAIL
  22. //
  23. SZTHISFILE
  24. // this is used in our window proc so that we can find out who was last created
  25. //
  26. static COleControl *s_pLastControlCreated;
  27. //=--------------------------------------------------------------------------=
  28. // COleControl::COleControl
  29. //=--------------------------------------------------------------------------=
  30. // constructor
  31. //
  32. // Parameters:
  33. // IUnknown * - [in] controlling Unknown
  34. // int - [in] type of primary dispatch interface OBJECT_TYPE_*
  35. // void * - [in] pointer to entire object
  36. // BOOL - [in] whether to enable IDispatchEx functionality
  37. // to allow dynamic adding of properties
  38. // Notes:
  39. //
  40. COleControl::COleControl
  41. (
  42. IUnknown *pUnkOuter,
  43. int iPrimaryDispatch,
  44. void *pMainInterface,
  45. BOOL fExpandoEnabled
  46. )
  47. : CAutomationObject(pUnkOuter, iPrimaryDispatch, pMainInterface, fExpandoEnabled),
  48. m_cpEvents(SINK_TYPE_EVENT),
  49. m_cpPropNotify(SINK_TYPE_PROPNOTIFY)
  50. {
  51. // initialize all our variables -- we decided against using a memory-zeroing
  52. // memory allocator, so we sort of have to do this work now ...
  53. //
  54. m_nFreezeEvents = 0;
  55. m_pClientSite = NULL;
  56. m_pControlSite = NULL;
  57. m_pInPlaceSite = NULL;
  58. m_pInPlaceFrame = NULL;
  59. m_pInPlaceUIWindow = NULL;
  60. m_pInPlaceSiteWndless = NULL;
  61. // certain hosts don't like 0,0 as your initial size, so we're going to set
  62. // our initial size to 100,50 [so it's at least sort of visible on the screen]
  63. //
  64. m_Size.cx = 0;
  65. m_Size.cy = 0;
  66. memset(&m_rcLocation, 0, sizeof(m_rcLocation));
  67. m_hRgn = NULL;
  68. m_hwnd = NULL;
  69. m_hwndParent = NULL;
  70. m_hwndReflect = NULL;
  71. m_fHostReflects = TRUE;
  72. m_fCheckedReflecting = FALSE;
  73. m_nFreezeEvents = 0;
  74. m_pSimpleFrameSite = NULL;
  75. m_pOleAdviseHolder = NULL;
  76. m_pViewAdviseSink = NULL;
  77. m_pDispAmbient = NULL;
  78. m_fDirty = FALSE;
  79. m_fModeFlagValid = FALSE;
  80. m_fInPlaceActive = FALSE;
  81. m_fInPlaceVisible = FALSE;
  82. m_fUIActive = FALSE;
  83. m_fSaveSucceeded = FALSE;
  84. m_fViewAdvisePrimeFirst = FALSE;
  85. m_fViewAdviseOnlyOnce = FALSE;
  86. m_fRunMode = FALSE;
  87. }
  88. //=--------------------------------------------------------------------------=
  89. // COleControl::~COleControl
  90. //=--------------------------------------------------------------------------=
  91. // "We are all of us resigned to death; it's life we aren't resigned to."
  92. // - Graham Greene (1904-91)
  93. //
  94. // Notes:
  95. //
  96. COleControl::~COleControl()
  97. {
  98. // if we've still got a window, go and kill it now.
  99. //
  100. if (m_hwnd) {
  101. // so our window proc doesn't crash.
  102. //
  103. SetWindowLongPtr(m_hwnd, GWLP_USERDATA, (LONG_PTR)0xFFFFFFFF);
  104. DestroyWindow(m_hwnd);
  105. }
  106. if (m_hwndReflect) {
  107. SetWindowLongPtr(m_hwndReflect, GWLP_USERDATA, 0);
  108. DestroyWindow(m_hwndReflect);
  109. }
  110. if (m_hRgn != NULL)
  111. {
  112. DeleteObject(m_hRgn);
  113. m_hRgn = NULL;
  114. }
  115. // clean up all the pointers we're holding around.
  116. //
  117. QUICK_RELEASE(m_pClientSite);
  118. QUICK_RELEASE(m_pControlSite);
  119. QUICK_RELEASE(m_pInPlaceSite);
  120. QUICK_RELEASE(m_pInPlaceFrame);
  121. QUICK_RELEASE(m_pInPlaceUIWindow);
  122. QUICK_RELEASE(m_pSimpleFrameSite);
  123. QUICK_RELEASE(m_pOleAdviseHolder);
  124. QUICK_RELEASE(m_pViewAdviseSink);
  125. QUICK_RELEASE(m_pDispAmbient);
  126. QUICK_RELEASE(m_pInPlaceSiteWndless);
  127. }
  128. #ifndef DEBUG
  129. #pragma optimize("t", on)
  130. #endif // DEBUG
  131. //=--------------------------------------------------------------------------=
  132. // COleControl::InternalQueryInterface
  133. //=--------------------------------------------------------------------------=
  134. // derived-controls should delegate back to this when they decide to support
  135. // additional interfaces
  136. //
  137. // Parameters:
  138. // REFIID - [in] interface they want
  139. // void ** - [out] where they want to put the resulting object ptr.
  140. //
  141. // Output:
  142. // HRESULT - S_OK, E_NOINTERFACE
  143. //
  144. // Notes:
  145. // - NOTE: this function is speed critical!!!!
  146. //
  147. HRESULT COleControl::InternalQueryInterface
  148. (
  149. REFIID riid,
  150. void **ppvObjOut
  151. )
  152. {
  153. switch (riid.Data1) {
  154. // private interface for prop page support
  155. case Data1_IControlPrv:
  156. if(DO_GUIDS_MATCH(riid, IID_IControlPrv)) {
  157. *ppvObjOut = (void *)this;
  158. ExternalAddRef();
  159. return S_OK;
  160. }
  161. goto NoInterface;
  162. QI_INHERITS(this, IOleControl);
  163. QI_INHERITS(this, IPointerInactive);
  164. QI_INHERITS(this, IQuickActivate);
  165. QI_INHERITS(this, IOleObject);
  166. QI_INHERITS((IPersistStorage *)this, IPersist);
  167. QI_INHERITS(this, IPersistStreamInit);
  168. QI_INHERITS(this, IOleInPlaceObject);
  169. QI_INHERITS(this, IOleInPlaceObjectWindowless);
  170. QI_INHERITS((IOleInPlaceActiveObject *)this, IOleWindow);
  171. QI_INHERITS(this, IOleInPlaceActiveObject);
  172. QI_INHERITS(this, IViewObject);
  173. QI_INHERITS(this, IViewObject2);
  174. QI_INHERITS(this, IViewObjectEx);
  175. QI_INHERITS(this, IConnectionPointContainer);
  176. QI_INHERITS(this, ISpecifyPropertyPages);
  177. QI_INHERITS(this, IPersistStorage);
  178. QI_INHERITS(this, IPersistPropertyBag);
  179. QI_INHERITS(this, IProvideClassInfo);
  180. default:
  181. goto NoInterface;
  182. }
  183. // we like the interface, so addref and return
  184. //
  185. ((IUnknown *)(*ppvObjOut))->AddRef();
  186. return S_OK;
  187. NoInterface:
  188. // delegate to super-class for automation interfaces, etc ...
  189. //
  190. return CAutomationObject::InternalQueryInterface(riid, ppvObjOut);
  191. }
  192. #ifndef DEBUG
  193. #pragma optimize("s", on)
  194. #endif // DEBUG
  195. //=--------------------------------------------------------------------------=
  196. // COleControl::FindConnectionPoint [IConnectionPointContainer]
  197. //=--------------------------------------------------------------------------=
  198. // given an IID, find a connection point sink for it.
  199. //
  200. // Parameters:
  201. // REFIID - [in] interfaces they want
  202. // IConnectionPoint ** - [out] where the cp should go
  203. //
  204. // Output:
  205. // HRESULT
  206. //
  207. // Notes:
  208. //
  209. STDMETHODIMP COleControl::FindConnectionPoint
  210. (
  211. REFIID riid,
  212. IConnectionPoint **ppConnectionPoint
  213. )
  214. {
  215. CHECK_POINTER(ppConnectionPoint);
  216. // we support the event interface, and IDispatch for it, and we also
  217. // support IPropertyNotifySink.
  218. //
  219. if (DO_GUIDS_MATCH(riid, EVENTIIDOFCONTROL(m_ObjectType)) || DO_GUIDS_MATCH(riid, IID_IDispatch))
  220. *ppConnectionPoint = &m_cpEvents;
  221. else if (DO_GUIDS_MATCH(riid, IID_IPropertyNotifySink))
  222. *ppConnectionPoint = &m_cpPropNotify;
  223. else
  224. return E_NOINTERFACE;
  225. // generic post-processing.
  226. //
  227. (*ppConnectionPoint)->AddRef();
  228. return S_OK;
  229. }
  230. //=--------------------------------------------------------------------------=
  231. // COleControl::EnumConnectionPoints [IConnectionPointContainer]
  232. //=--------------------------------------------------------------------------=
  233. // creates an enumerator for connection points.
  234. //
  235. // Parameters:
  236. // IEnumConnectionPoints ** - [out]
  237. //
  238. // Output:
  239. // HRESULT
  240. //
  241. // Notes:
  242. //
  243. STDMETHODIMP COleControl::EnumConnectionPoints
  244. (
  245. IEnumConnectionPoints **ppEnumConnectionPoints
  246. )
  247. {
  248. IConnectionPoint **rgConnectionPoints;
  249. CHECK_POINTER(ppEnumConnectionPoints);
  250. // HeapAlloc an array of connection points [since our standard enum
  251. // assumes this and HeapFree's it later ]
  252. //
  253. rgConnectionPoints = (IConnectionPoint **)HeapAlloc(g_hHeap, 0, sizeof(IConnectionPoint *) * 2);
  254. RETURN_ON_NULLALLOC(rgConnectionPoints);
  255. // we support the event interface for this dude as well as IPropertyNotifySink
  256. //
  257. rgConnectionPoints[0] = &m_cpEvents;
  258. rgConnectionPoints[1] = &m_cpPropNotify;
  259. *ppEnumConnectionPoints = (IEnumConnectionPoints *)(IEnumGeneric *) new CStandardEnum(IID_IEnumConnectionPoints,
  260. 2, sizeof(IConnectionPoint *), (void *)rgConnectionPoints,
  261. CopyAndAddRefObject);
  262. if (!*ppEnumConnectionPoints) {
  263. HeapFree(g_hHeap, 0, rgConnectionPoints);
  264. return E_OUTOFMEMORY;
  265. }
  266. return S_OK;
  267. }
  268. //=--------------------------------------------------------------------------=
  269. // COleControl::GetPages [ISpecifyPropertyPages]
  270. //=--------------------------------------------------------------------------=
  271. // returns a counted array with the guids for our property pages.
  272. //
  273. // parameters:
  274. // CAUUID * - [out] where to put the counted array.
  275. //
  276. // Output:
  277. // HRESULT
  278. //
  279. // NOtes:
  280. //
  281. STDMETHODIMP COleControl::GetPages
  282. (
  283. CAUUID *pPages
  284. )
  285. {
  286. const GUID **pElems;
  287. void *pv;
  288. WORD x;
  289. // if there are no property pages, this is actually pretty easy.
  290. //
  291. if (!CPROPPAGESOFCONTROL(m_ObjectType)) {
  292. pPages->cElems = 0;
  293. pPages->pElems = NULL;
  294. return S_OK;
  295. }
  296. // fill out the Counted array, using IMalloc'd memory.
  297. //
  298. pPages->cElems = CPROPPAGESOFCONTROL(m_ObjectType);
  299. pv = CoTaskMemAlloc(sizeof(GUID) * (pPages->cElems));
  300. RETURN_ON_NULLALLOC(pv);
  301. pPages->pElems = (GUID *)pv;
  302. // loop through our array of pages and get 'em.
  303. //
  304. pElems = PPROPPAGESOFCONTROL(m_ObjectType);
  305. for (x = 0; x < pPages->cElems; x++)
  306. pPages->pElems[x] = *(pElems[x]);
  307. return S_OK;
  308. }
  309. //=--------------------------------------------------------------------------=
  310. // COleControl::CConnectionPoint::m_pOleControl
  311. //=--------------------------------------------------------------------------=
  312. // returns a pointer to the control in which we are nested.
  313. //
  314. // Output:
  315. // COleControl *
  316. //
  317. // Notes:
  318. //
  319. inline COleControl *COleControl::CConnectionPoint::m_pOleControl
  320. (
  321. void
  322. )
  323. {
  324. return (COleControl *)((BYTE *)this - ((m_bType == SINK_TYPE_EVENT)
  325. ? offsetof(COleControl, m_cpEvents)
  326. : offsetof(COleControl, m_cpPropNotify)));
  327. }
  328. //=--------------------------------------------------------------------------=
  329. // COleControl::CConnectionPoint::QueryInterface
  330. //=--------------------------------------------------------------------------=
  331. // standard qi
  332. //
  333. // Parameters:
  334. // REFIID - [in] interface they want
  335. // void ** - [out] where they want to put the resulting object ptr.
  336. //
  337. // Output:
  338. // HRESULT - S_OK, E_NOINTERFACE
  339. //
  340. // Notes:
  341. //
  342. STDMETHODIMP COleControl::CConnectionPoint::QueryInterface
  343. (
  344. REFIID riid,
  345. void **ppvObjOut
  346. )
  347. {
  348. if (DO_GUIDS_MATCH(riid, IID_IConnectionPoint) || DO_GUIDS_MATCH(riid, IID_IUnknown)) {
  349. *ppvObjOut = (IConnectionPoint *)this;
  350. AddRef();
  351. return S_OK;
  352. }
  353. return E_NOINTERFACE;
  354. }
  355. //=--------------------------------------------------------------------------=
  356. // COleControl::CConnectionPoint::AddRef
  357. //=--------------------------------------------------------------------------=
  358. //
  359. // Output:
  360. // ULONG - the new reference count
  361. //
  362. // Notes:
  363. //
  364. ULONG COleControl::CConnectionPoint::AddRef
  365. (
  366. void
  367. )
  368. {
  369. return m_pOleControl()->ExternalAddRef();
  370. }
  371. //=--------------------------------------------------------------------------=
  372. // COleControl::CConnectionPoint::Release
  373. //=--------------------------------------------------------------------------=
  374. //
  375. // Output:
  376. // ULONG - remaining refs
  377. //
  378. // Notes:
  379. //
  380. ULONG COleControl::CConnectionPoint::Release
  381. (
  382. void
  383. )
  384. {
  385. return m_pOleControl()->ExternalRelease();
  386. }
  387. //=--------------------------------------------------------------------------=
  388. // COleControl::CConnectionPoint::GetConnectionInterface
  389. //=--------------------------------------------------------------------------=
  390. // returns the interface we support connections on.
  391. //
  392. // Parameters:
  393. // IID * - [out] interface we support.
  394. //
  395. // Output:
  396. // HRESULT
  397. //
  398. // Notes:
  399. //
  400. STDMETHODIMP COleControl::CConnectionPoint::GetConnectionInterface
  401. (
  402. IID *piid
  403. )
  404. {
  405. if (m_bType == SINK_TYPE_EVENT)
  406. *piid = EVENTIIDOFCONTROL(m_pOleControl()->m_ObjectType);
  407. else
  408. *piid = IID_IPropertyNotifySink;
  409. return S_OK;
  410. }
  411. //=--------------------------------------------------------------------------=
  412. // COleControl::CConnectionPoint::GetConnectionPointContainer
  413. //=--------------------------------------------------------------------------=
  414. // returns the connection point container
  415. //
  416. // Parameters:
  417. // IConnectionPointContainer **ppCPC
  418. //
  419. // Output:
  420. // HRESULT
  421. //
  422. // Notes:
  423. //
  424. STDMETHODIMP COleControl::CConnectionPoint::GetConnectionPointContainer
  425. (
  426. IConnectionPointContainer **ppCPC
  427. )
  428. {
  429. return m_pOleControl()->ExternalQueryInterface(IID_IConnectionPointContainer, (void **)ppCPC);
  430. }
  431. //=--------------------------------------------------------------------------=
  432. // COleControl::CConnectiontPoint::Advise
  433. //=--------------------------------------------------------------------------=
  434. // someboyd wants to be advised when something happens.
  435. //
  436. // Parameters:
  437. // IUnknown * - [in] guy who wants to be advised.
  438. // DWORD * - [out] cookie
  439. //
  440. // Output:
  441. // HRESULT
  442. //
  443. // Notes:
  444. //
  445. STDMETHODIMP COleControl::CConnectionPoint::Advise
  446. (
  447. IUnknown *pUnk,
  448. DWORD *pdwCookie
  449. )
  450. {
  451. HRESULT hr;
  452. void *pv;
  453. CHECK_POINTER(pdwCookie);
  454. // first, make sure everybody's got what they thinks they got
  455. //
  456. if (m_bType == SINK_TYPE_EVENT) {
  457. // CONSIDER: 12.95 -- this theoretically is broken -- if they do a find
  458. // connection point on IDispatch, and they just happened to also support
  459. // the Event IID, we'd advise on that. this is not awesome, but will
  460. // prove entirely acceptable short term.
  461. //
  462. hr = pUnk->QueryInterface(EVENTIIDOFCONTROL(m_pOleControl()->m_ObjectType), &pv);
  463. if (FAILED(hr))
  464. hr = pUnk->QueryInterface(IID_IDispatch, &pv);
  465. }
  466. else
  467. hr = pUnk->QueryInterface(IID_IPropertyNotifySink, &pv);
  468. RETURN_ON_FAILURE(hr);
  469. // finally, add the sink. it's now been cast to the correct type and has
  470. // been AddRef'd.
  471. //
  472. return AddSink(pv, pdwCookie);
  473. }
  474. //=--------------------------------------------------------------------------=
  475. // COleControl::CConnectionPoint::AddSink
  476. //=--------------------------------------------------------------------------=
  477. // in some cases, we'll already have done the QI, and won't need to do the
  478. // work that is done in the Advise routine above. thus, these people can
  479. // just call this instead. [this stems really from IQuickActivate]
  480. //
  481. // Parameters:
  482. // void * - [in] the sink to add. it's already been addref'd
  483. // DWORD * - [out] cookie
  484. //
  485. // Output:
  486. // HRESULT
  487. //
  488. // Notes:
  489. //
  490. HRESULT COleControl::CConnectionPoint::AddSink
  491. (
  492. void *pv,
  493. DWORD *pdwCookie
  494. )
  495. {
  496. IUnknown **rgUnkNew;
  497. int i;
  498. // we optimize the case where there is only one sink to not allocate
  499. // any storage. turns out very rarely is there more than one.
  500. //
  501. if (!m_cSinks) {
  502. m_SingleSink = (IUnknown *) pv;
  503. *pdwCookie = (DWORD)-1;
  504. m_cSinks = 1;
  505. return S_OK;
  506. }
  507. // Allocated the array yet?
  508. if (!m_rgSinks) {
  509. rgUnkNew = (IUnknown **)HeapAlloc(g_hHeap, HEAP_ZERO_MEMORY, 8 * sizeof(IUnknown *));
  510. RETURN_ON_NULLALLOC(rgUnkNew);
  511. m_cAllocatedSinks = 8;
  512. m_rgSinks = rgUnkNew;
  513. m_rgSinks[0] = m_SingleSink;
  514. m_rgSinks[1] = (IUnknown *)pv;
  515. m_SingleSink = NULL;
  516. m_cSinks = 2;
  517. *pdwCookie = 2;
  518. return S_OK;
  519. }
  520. // Find an empty slot.
  521. for (i = 0; i < m_cAllocatedSinks; i++) {
  522. if (!m_rgSinks[i]) {
  523. m_rgSinks[i] = (IUnknown *)pv;
  524. i++;
  525. *pdwCookie = i;
  526. m_cSinks++;
  527. return S_OK;
  528. }
  529. }
  530. // Didn't find one, grow the array.
  531. rgUnkNew = (IUnknown **)HeapReAlloc(g_hHeap, HEAP_ZERO_MEMORY, m_rgSinks, (m_cAllocatedSinks + 8) * sizeof(IUnknown *));
  532. RETURN_ON_NULLALLOC(rgUnkNew);
  533. m_rgSinks = rgUnkNew;
  534. m_rgSinks[m_cAllocatedSinks] = (IUnknown *)pv;
  535. i = m_cAllocatedSinks+1;
  536. m_cAllocatedSinks += 8;
  537. *pdwCookie = i;
  538. m_cSinks++;
  539. return S_OK;
  540. }
  541. //=--------------------------------------------------------------------------=
  542. // COleControl::CConnectionPoint::Unadvise
  543. //=--------------------------------------------------------------------------=
  544. // they don't want to be told any more.
  545. //
  546. // Parameters:
  547. // DWORD - [in] the cookie we gave 'em.
  548. //
  549. // Output:
  550. // HRESULT
  551. //
  552. // Notes:
  553. //
  554. STDMETHODIMP COleControl::CConnectionPoint::Unadvise
  555. (
  556. DWORD dwCookie
  557. )
  558. {
  559. IUnknown *pUnk;
  560. if (!dwCookie)
  561. return S_OK;
  562. if (dwCookie == (DWORD) -1) {
  563. pUnk = m_SingleSink;
  564. m_SingleSink = NULL;
  565. if (m_rgSinks) {
  566. m_rgSinks[0] = NULL;
  567. }
  568. } else {
  569. if (dwCookie <= (DWORD)m_cAllocatedSinks) {
  570. if (m_rgSinks) {
  571. pUnk = m_rgSinks[dwCookie-1];
  572. m_rgSinks[dwCookie-1] = NULL;
  573. } else {
  574. return CONNECT_E_NOCONNECTION;
  575. }
  576. } else {
  577. return CONNECT_E_NOCONNECTION;
  578. }
  579. }
  580. m_cSinks--;
  581. if (!m_cSinks && m_rgSinks) {
  582. HeapFree(g_hHeap, 0, m_rgSinks);
  583. m_cAllocatedSinks = 0;
  584. m_rgSinks = NULL;
  585. }
  586. if (pUnk) {
  587. pUnk->Release();
  588. return S_OK;
  589. } else {
  590. return CONNECT_E_NOCONNECTION;
  591. }
  592. }
  593. //=--------------------------------------------------------------------------=
  594. // COleControl::CConnectionPoint::EnumConnections
  595. //=--------------------------------------------------------------------------=
  596. // enumerates all current connections
  597. //
  598. // Paramters:
  599. // IEnumConnections ** - [out] new enumerator object
  600. //
  601. // Output:
  602. // HRESULT
  603. //
  604. // NOtes:
  605. //
  606. STDMETHODIMP COleControl::CConnectionPoint::EnumConnections
  607. (
  608. IEnumConnections **ppEnumOut
  609. )
  610. {
  611. CONNECTDATA *rgConnectData = NULL;
  612. unsigned int i;
  613. if (m_cSinks) {
  614. // allocate some memory big enough to hold all of the sinks.
  615. //
  616. rgConnectData = (CONNECTDATA *)HeapAlloc(g_hHeap, 0, m_cSinks * sizeof(CONNECTDATA));
  617. RETURN_ON_NULLALLOC(rgConnectData);
  618. if ((m_cSinks == 1) && !m_rgSinks) {
  619. rgConnectData[0].pUnk = m_SingleSink;
  620. rgConnectData[0].dwCookie = (DWORD)-1;
  621. } else {
  622. for (unsigned int x = 0, i=0; x < m_cAllocatedSinks; x++) {
  623. if (m_rgSinks[x]) {
  624. rgConnectData[i].pUnk = m_rgSinks[x];
  625. rgConnectData[i].dwCookie = x+1;
  626. i++;
  627. }
  628. }
  629. }
  630. }
  631. // create yon enumerator object.
  632. //
  633. *ppEnumOut = (IEnumConnections *)(IEnumGeneric *)new CStandardEnum(IID_IEnumConnections,
  634. m_cSinks, sizeof(CONNECTDATA), rgConnectData, CopyAndAddRefObject);
  635. if (!*ppEnumOut) {
  636. if (rgConnectData)
  637. {
  638. HeapFree(g_hHeap, 0, rgConnectData);
  639. }
  640. return E_OUTOFMEMORY;
  641. }
  642. return S_OK;
  643. }
  644. //=--------------------------------------------------------------------------=
  645. // COleControl::CConnectionPoint::~CConnectionPoint
  646. //=--------------------------------------------------------------------------=
  647. // cleans up
  648. //
  649. // Notes:
  650. //
  651. COleControl::CConnectionPoint::~CConnectionPoint ()
  652. {
  653. int x;
  654. // clean up some memory stuff
  655. //
  656. if (!m_cSinks)
  657. return;
  658. else if (m_SingleSink)
  659. ((IUnknown *)m_SingleSink)->Release();
  660. else {
  661. for (x = 0; x < m_cAllocatedSinks; x++) {
  662. if (m_rgSinks[x]) {
  663. QUICK_RELEASE(m_rgSinks[x]);
  664. }
  665. }
  666. HeapFree(g_hHeap, 0, m_rgSinks);
  667. }
  668. }
  669. //=--------------------------------------------------------------------------=
  670. // COleControl::CConnectionPiont::DoInvoke
  671. //=--------------------------------------------------------------------------=
  672. // fires an event to all listening on our event interface.
  673. //
  674. // Parameters:
  675. // DISPID - [in] event to fire.
  676. // DISPPARAMS - [in]
  677. //
  678. // Notes:
  679. //
  680. void COleControl::CConnectionPoint::DoInvoke
  681. (
  682. DISPID dispid,
  683. DISPPARAMS *pdispparams
  684. )
  685. {
  686. int iConnection;
  687. // if we don't have any sinks, then there's nothing to do. we intentionally
  688. // ignore errors here.
  689. //
  690. if (m_cSinks == 0)
  691. return;
  692. else if (m_SingleSink) {
  693. ((IDispatch *)m_SingleSink)->Invoke(dispid, IID_NULL, 0, DISPATCH_METHOD, pdispparams, NULL, NULL, NULL);
  694. } else {
  695. for (iConnection = 0; iConnection < m_cAllocatedSinks; iConnection++) {
  696. if (m_rgSinks[iConnection]) {
  697. ((IDispatch *)m_rgSinks[iConnection])->Invoke(dispid, IID_NULL, 0, DISPATCH_METHOD, pdispparams, NULL, NULL, NULL);
  698. }
  699. }
  700. }
  701. }
  702. //=--------------------------------------------------------------------------=
  703. // COleControl::CConnectionPoint::DoOnChanged
  704. //=--------------------------------------------------------------------------=
  705. // fires the OnChanged event for IPropertyNotifySink listeners.
  706. //
  707. // Parameters:
  708. // DISPID - [in] dude that changed.
  709. //
  710. // Output:
  711. // none
  712. //
  713. // Notes:
  714. //
  715. void COleControl::CConnectionPoint::DoOnChanged
  716. (
  717. DISPID dispid
  718. )
  719. {
  720. int iConnection;
  721. // if we don't have any sinks, then there's nothing to do.
  722. //
  723. if (m_cSinks == 0)
  724. return;
  725. else if (m_SingleSink) {
  726. ((IPropertyNotifySink *)m_SingleSink)->OnChanged(dispid);
  727. } else {
  728. for (iConnection = 0; iConnection < m_cAllocatedSinks; iConnection++) {
  729. if (m_rgSinks[iConnection]) {
  730. ((IPropertyNotifySink *)m_rgSinks[iConnection])->OnChanged(dispid);
  731. }
  732. }
  733. }
  734. }
  735. //=--------------------------------------------------------------------------=
  736. // COleControl::CConnectionPoint::DoOnRequestEdit
  737. //=--------------------------------------------------------------------------=
  738. // fires the OnRequestEdit for IPropertyNotifySinkListeners
  739. //
  740. // Parameters:
  741. // DISPID - [in] dispid user wants to change.
  742. //
  743. // Output:
  744. // BOOL - false means you cant
  745. //
  746. // Notes:
  747. //
  748. BOOL COleControl::CConnectionPoint::DoOnRequestEdit
  749. (
  750. DISPID dispid
  751. )
  752. {
  753. HRESULT hr;
  754. int iConnection;
  755. // if we don't have any sinks, then there's nothing to do.
  756. //
  757. if (m_cSinks == 0)
  758. hr = S_OK;
  759. else if (m_SingleSink) {
  760. hr =((IPropertyNotifySink *)m_SingleSink)->OnRequestEdit(dispid);
  761. } else {
  762. for (iConnection = 0; iConnection < m_cAllocatedSinks; iConnection++) {
  763. if (m_rgSinks[iConnection]) {
  764. hr = ((IPropertyNotifySink *)m_rgSinks[iConnection])->OnRequestEdit(dispid);
  765. if (hr != S_OK)
  766. break;
  767. }
  768. }
  769. }
  770. return (hr == S_OK) ? TRUE : FALSE;
  771. }
  772. //=--------------------------------------------------------------------------=
  773. // COleControl::CreateInPlaceWindow
  774. //=--------------------------------------------------------------------------=
  775. // creates the window with which we will be working.
  776. // yay.
  777. //
  778. // Parameters:
  779. // int - [in] left
  780. // int - [in] top
  781. // BOOL - [in] can we skip redrawing?
  782. //
  783. // Output:
  784. // HWND
  785. //
  786. // Notes:
  787. // - DANGER! DANGER! this function is protected so that anybody can call it
  788. // from their control. however, people should be extremely careful of when
  789. // and why they do this. preferably, this function would only need to be
  790. // called by an end-control writer in design mode to take care of some
  791. // hosting/painting issues. otherwise, the framework should be left to
  792. // call it when it wants.
  793. //
  794. HWND COleControl::CreateInPlaceWindow
  795. (
  796. int x,
  797. int y,
  798. BOOL fNoRedraw
  799. )
  800. {
  801. BOOL fVisible;
  802. HRESULT hr;
  803. DWORD dwWindowStyle, dwExWindowStyle;
  804. char szWindowTitle[128];
  805. // if we've already got a window, do nothing.
  806. //
  807. if (m_hwnd)
  808. return m_hwnd;
  809. // get the user to register the class if it's not already
  810. // been done. we have to critical section this since more than one thread
  811. // can be trying to create this control
  812. //
  813. EnterCriticalSection(&g_CriticalSection);
  814. if (!CTLWNDCLASSREGISTERED(m_ObjectType)) {
  815. if (!RegisterClassData()) {
  816. LeaveCriticalSection(&g_CriticalSection);
  817. return NULL;
  818. } else
  819. CTLWNDCLASSREGISTERED(m_ObjectType) = TRUE;
  820. }
  821. LeaveCriticalSection(&g_CriticalSection);
  822. // let the user set up things like the window title, the
  823. // style, and anything else they feel interested in fiddling
  824. // with.
  825. //
  826. dwWindowStyle = dwExWindowStyle = 0;
  827. szWindowTitle[0] = '\0';
  828. if (!BeforeCreateWindow(&dwWindowStyle, &dwExWindowStyle, szWindowTitle))
  829. return NULL;
  830. dwWindowStyle |= (WS_CHILD | WS_CLIPSIBLINGS);
  831. // create window visible if parent hidden (common case)
  832. // otherwise, create hidden, then shown. this is a little subtle, but
  833. // it makes sense eventually.
  834. //
  835. if (!m_hwndParent)
  836. m_hwndParent = GetParkingWindow();
  837. fVisible = IsWindowVisible(m_hwndParent);
  838. // if a control is subclassed, and we're in
  839. // a host that doesn't support Message Reflecting, we have to create
  840. // the user window in another window which will do all the reflecting.
  841. // VERY blech. [don't however, bother in design mode]
  842. //
  843. if (SUBCLASSWNDPROCOFCONTROL(m_ObjectType) && (m_hwndParent != GetParkingWindow())) {
  844. // determine if the host supports message reflecting.
  845. //
  846. if (!m_fCheckedReflecting) {
  847. VARIANT_BOOL f;
  848. hr = GetAmbientProperty(DISPID_AMBIENT_MESSAGEREFLECT, VT_BOOL, &f);
  849. if (FAILED(hr) || !f)
  850. m_fHostReflects = FALSE;
  851. m_fCheckedReflecting = TRUE;
  852. }
  853. // if the host doesn't support reflecting, then we have to create
  854. // an extra window around the control window, and then parent it
  855. // off that.
  856. //
  857. if (!m_fHostReflects) {
  858. ASSERT(m_hwndReflect == NULL, "Where'd this come from?");
  859. m_hwndReflect = CreateReflectWindow(!fVisible, m_hwndParent, x, y, &m_Size);
  860. if (!m_hwndReflect)
  861. return NULL;
  862. SetWindowLongPtr(m_hwndReflect, GWLP_USERDATA, (LONG_PTR)this);
  863. dwWindowStyle |= WS_VISIBLE;
  864. }
  865. } else {
  866. if (!fVisible)
  867. dwWindowStyle |= WS_VISIBLE;
  868. }
  869. // we have to mutex the entire create window process since we need to use
  870. // the s_pLastControlCreated to pass in the object pointer. nothing too
  871. // serious
  872. //
  873. EnterCriticalSection(&g_CriticalSection);
  874. s_pLastControlCreated = this;
  875. m_fCreatingWindow = TRUE;
  876. // finally, go create the window, parenting it as appropriate.
  877. //
  878. m_hwnd = CreateWindowEx(dwExWindowStyle,
  879. WNDCLASSNAMEOFCONTROL(m_ObjectType),
  880. szWindowTitle,
  881. dwWindowStyle,
  882. (m_hwndReflect) ? 0 : x,
  883. (m_hwndReflect) ? 0 : y,
  884. m_Size.cx, m_Size.cy,
  885. (m_hwndReflect) ? m_hwndReflect : m_hwndParent,
  886. NULL, g_hInstance, NULL);
  887. // clean up some variables, and leave the critical section
  888. //
  889. m_fCreatingWindow = FALSE;
  890. s_pLastControlCreated = NULL;
  891. LeaveCriticalSection(&g_CriticalSection);
  892. if (m_hwnd) {
  893. // let the derived-control do something if they so desire
  894. //
  895. if (!AfterCreateWindow()) {
  896. BeforeDestroyWindow();
  897. SetWindowLongPtr(m_hwnd, GWLP_USERDATA, (LONG_PTR)0xFFFFFFFF);
  898. DestroyWindow(m_hwnd);
  899. m_hwnd = NULL;
  900. return m_hwnd;
  901. }
  902. // if we didn't create the window visible, show it now.
  903. //
  904. if (fVisible)
  905. {
  906. if (GetParent(m_hwnd) != m_hwndParent)
  907. // SetWindowPos fails if parent hwnd is passed in so keep
  908. // this behaviour in those cases without ripping.
  909. SetWindowPos(m_hwnd, m_hwndParent, 0, 0, 0, 0,
  910. SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW | ((fNoRedraw) ? SWP_NOREDRAW : 0));
  911. }
  912. }
  913. // finally, tell the host of this
  914. //
  915. if (m_pClientSite)
  916. m_pClientSite->ShowObject();
  917. return m_hwnd;
  918. }
  919. //=--------------------------------------------------------------------------=
  920. // COleControl::SetInPlaceParent [helper]
  921. //=--------------------------------------------------------------------------=
  922. // sets up the parent window for our control.
  923. //
  924. // Parameters:
  925. // HWND - [in] new parent window
  926. //
  927. // Notes:
  928. //
  929. void COleControl::SetInPlaceParent
  930. (
  931. HWND hwndParent
  932. )
  933. {
  934. ASSERT(!m_pInPlaceSiteWndless, "This routine should only get called for windowed OLE controls");
  935. if (m_hwndParent == hwndParent)
  936. return;
  937. m_hwndParent = hwndParent;
  938. if (m_hwnd)
  939. SetParent(GetOuterWindow(), hwndParent);
  940. }
  941. //=--------------------------------------------------------------------------=
  942. // COleControl::ControlWindowProc
  943. //=--------------------------------------------------------------------------=
  944. // default window proc for an OLE Control. controls will have their own
  945. // window proc called from this one, after some processing is done.
  946. //
  947. // Parameters:
  948. // - see win32sdk docs.
  949. //
  950. // Notes:
  951. //
  952. LRESULT CALLBACK COleControl::ControlWindowProc
  953. (
  954. HWND hwnd,
  955. UINT msg,
  956. WPARAM wParam,
  957. LPARAM lParam
  958. )
  959. {
  960. COleControl *pCtl = ControlFromHwnd(hwnd);
  961. HRESULT hr;
  962. LRESULT lResult;
  963. DWORD dwCookie;
  964. // if the value isn't a positive value, then it's in some special
  965. // state [creation or destruction] this is safe because under win32,
  966. // the upper 2GB of an address space aren't available.
  967. //
  968. if (!pCtl) {
  969. pCtl = s_pLastControlCreated;
  970. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pCtl);
  971. // This test and else clause, which you would resonably expect to never
  972. // ever happen, is needed for the plugin control when hosting the SGI
  973. // COSMO plugin. That plugin queries GWL_USERDATA and uses it as a pointer.
  974. // In IE4.0 we in-place deactivate it when IE3 did not, causing the window
  975. // to be destroyed, and the SGI COSMO plugin to fault. The fix is for the
  976. // Plugin control to never use the GWL_USERDATA == -1 mechanism.
  977. // -Tomsn, 1/2/97 (happy new year), IE4 bug 13292.
  978. if( pCtl != NULL ) {
  979. pCtl->m_hwnd = hwnd;
  980. }
  981. else {
  982. return DefWindowProc(hwnd, msg, wParam, lParam);
  983. }
  984. } else if ((LONG_PTR)pCtl == (LONG_PTR)0xffffffff) {
  985. return DefWindowProc(hwnd, msg, wParam, lParam);
  986. }
  987. // message preprocessing
  988. //
  989. if (pCtl->m_pSimpleFrameSite) {
  990. hr = pCtl->m_pSimpleFrameSite->PreMessageFilter(hwnd, msg, wParam, lParam, &lResult, &dwCookie);
  991. if (hr == S_FALSE) return lResult;
  992. }
  993. // for certain messages, do not call the user window proc. instead,
  994. // we have something else we'd like to do.
  995. //
  996. switch (msg) {
  997. case WM_PAINT:
  998. {
  999. // call the user's OnDraw routine.
  1000. //
  1001. PAINTSTRUCT ps;
  1002. RECT rc;
  1003. HDC hdc;
  1004. // if we're given an HDC, then use it
  1005. //
  1006. if (!wParam)
  1007. hdc = BeginPaint(hwnd, &ps);
  1008. else
  1009. hdc = (HDC)wParam;
  1010. GetClientRect(hwnd, &rc);
  1011. pCtl->OnDraw(DVASPECT_CONTENT, hdc, (RECTL *)&rc, NULL, NULL, TRUE);
  1012. if (!wParam)
  1013. EndPaint(hwnd, &ps);
  1014. }
  1015. break;
  1016. default:
  1017. // call the derived-control's window proc
  1018. //
  1019. lResult = pCtl->WindowProc(msg, wParam, lParam);
  1020. break;
  1021. }
  1022. // message postprocessing
  1023. //
  1024. switch (msg) {
  1025. case WM_NCDESTROY:
  1026. // after this point, the window doesn't exist any more
  1027. //
  1028. pCtl->m_hwnd = NULL;
  1029. break;
  1030. case WM_SETFOCUS:
  1031. case WM_KILLFOCUS:
  1032. // give the control site focus notification
  1033. //
  1034. if (pCtl->m_fInPlaceActive && pCtl->m_pControlSite)
  1035. pCtl->m_pControlSite->OnFocus(msg == WM_SETFOCUS);
  1036. break;
  1037. case WM_SIZE:
  1038. // a change in size is a change in view
  1039. //
  1040. if (!pCtl->m_fCreatingWindow)
  1041. pCtl->ViewChanged();
  1042. break;
  1043. }
  1044. // lastly, simple frame postmessage processing
  1045. //
  1046. if (pCtl->m_pSimpleFrameSite)
  1047. pCtl->m_pSimpleFrameSite->PostMessageFilter(hwnd, msg, wParam, lParam, &lResult, dwCookie);
  1048. return lResult;
  1049. }
  1050. //=--------------------------------------------------------------------------=
  1051. // COleControl::SetFocus
  1052. //=--------------------------------------------------------------------------=
  1053. // we have to override this routine to get UI Activation correct.
  1054. //
  1055. // Parameters:
  1056. // BOOL - [in] true means take, false release
  1057. //
  1058. // Output:
  1059. // BOOL
  1060. //
  1061. // Notes:
  1062. // - CONSIDER: this is pretty messy, and it's still not entirely clear
  1063. // what the ole control/focus story is.
  1064. //
  1065. BOOL COleControl::SetFocus
  1066. (
  1067. BOOL fGrab
  1068. )
  1069. {
  1070. HRESULT hr;
  1071. HWND hwnd;
  1072. // first thing to do is check out UI Activation state, and then set
  1073. // focus [either with windows api, or via the host for windowless
  1074. // controls]
  1075. //
  1076. if (m_pInPlaceSiteWndless) {
  1077. if (!m_fUIActive && fGrab)
  1078. if (FAILED(InPlaceActivate(OLEIVERB_UIACTIVATE))) return FALSE;
  1079. hr = m_pInPlaceSiteWndless->SetFocus(fGrab);
  1080. return (hr == S_OK) ? TRUE : FALSE;
  1081. } else {
  1082. // we've got a window.
  1083. //
  1084. if (m_fInPlaceActive) {
  1085. hwnd = (fGrab) ? m_hwnd : m_hwndParent;
  1086. if (!m_fUIActive && fGrab)
  1087. return SUCCEEDED(InPlaceActivate(OLEIVERB_UIACTIVATE));
  1088. else
  1089. return SetGUIFocus(hwnd);
  1090. } else
  1091. return FALSE;
  1092. }
  1093. // dead code
  1094. }
  1095. //=--------------------------------------------------------------------------=
  1096. // COleControl::SetGUIFocus
  1097. //=--------------------------------------------------------------------------=
  1098. // does the work of setting the Windows GUI focus to the specified window
  1099. //
  1100. // Parameters:
  1101. // HWND - [in] window that should get focus
  1102. //
  1103. // Output:
  1104. // BOOL - [out] whether setting focus succeeded
  1105. //
  1106. // Notes:
  1107. // we do this because some controls host non-ole window hierarchies, like
  1108. // the Netscape plugin ocx. in such cases, the control may need to be UIActive
  1109. // to function properly in the document, but cannot take the windows focus
  1110. // away from one of its child windows. such controls may override this method
  1111. // and respond as appropriate.
  1112. //
  1113. BOOL COleControl::SetGUIFocus
  1114. (
  1115. HWND hwndSet
  1116. )
  1117. {
  1118. return (::SetFocus(hwndSet) == hwndSet);
  1119. }
  1120. //=--------------------------------------------------------------------------=
  1121. // COleControl::ReflectWindowProc
  1122. //=--------------------------------------------------------------------------=
  1123. // reflects window messages on to the child window.
  1124. //
  1125. // Parameters and Output:
  1126. // - see win32 sdk docs
  1127. //
  1128. // Notes:
  1129. //
  1130. LRESULT CALLBACK COleControl::ReflectWindowProc
  1131. (
  1132. HWND hwnd,
  1133. UINT msg,
  1134. WPARAM wParam,
  1135. LPARAM lParam
  1136. )
  1137. {
  1138. COleControl *pCtl;
  1139. switch (msg) {
  1140. case WM_COMMAND:
  1141. case WM_NOTIFY:
  1142. case WM_CTLCOLORBTN:
  1143. case WM_CTLCOLORDLG:
  1144. case WM_CTLCOLOREDIT:
  1145. case WM_CTLCOLORLISTBOX:
  1146. case WM_CTLCOLORMSGBOX:
  1147. case WM_CTLCOLORSCROLLBAR:
  1148. case WM_CTLCOLORSTATIC:
  1149. case WM_DRAWITEM:
  1150. case WM_MEASUREITEM:
  1151. case WM_DELETEITEM:
  1152. case WM_VKEYTOITEM:
  1153. case WM_CHARTOITEM:
  1154. case WM_COMPAREITEM:
  1155. case WM_HSCROLL:
  1156. case WM_VSCROLL:
  1157. case WM_PARENTNOTIFY:
  1158. case WM_SETFOCUS:
  1159. case WM_SIZE:
  1160. pCtl = (COleControl *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  1161. if (pCtl)
  1162. return SendMessage(pCtl->m_hwnd, OCM__BASE + msg, wParam, lParam);
  1163. break;
  1164. }
  1165. return DefWindowProc(hwnd, msg, wParam, lParam);
  1166. }
  1167. //=--------------------------------------------------------------------------=
  1168. // COleControl::GetAmbientProperty [callable]
  1169. //=--------------------------------------------------------------------------=
  1170. // returns the value of an ambient property
  1171. //
  1172. // Parameters:
  1173. // DISPID - [in] property to get
  1174. // VARTYPE - [in] type of desired data
  1175. // void * - [out] where to put the data
  1176. //
  1177. // Output:
  1178. // BOOL - FALSE means didn't work.
  1179. //
  1180. // Notes:
  1181. //
  1182. BOOL COleControl::GetAmbientProperty
  1183. (
  1184. DISPID dispid,
  1185. VARTYPE vt,
  1186. void *pData
  1187. )
  1188. {
  1189. DISPPARAMS dispparams;
  1190. VARIANT v, v2;
  1191. HRESULT hr;
  1192. v.vt = VT_EMPTY;
  1193. v.lVal = 0;
  1194. v2.vt = VT_EMPTY;
  1195. v2.lVal = 0;
  1196. // get a pointer to the source of ambient properties.
  1197. //
  1198. if (!m_pDispAmbient) {
  1199. if (m_pClientSite)
  1200. m_pClientSite->QueryInterface(IID_IDispatch, (void **)&m_pDispAmbient);
  1201. if (!m_pDispAmbient)
  1202. return FALSE;
  1203. }
  1204. // now go and get the property into a variant.
  1205. //
  1206. memset(&dispparams, 0, sizeof(DISPPARAMS));
  1207. hr = m_pDispAmbient->Invoke(dispid, IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams,
  1208. &v, NULL, NULL);
  1209. if (FAILED(hr)) return FALSE;
  1210. // we've got the variant, so now go an coerce it to the type that the user
  1211. // wants. if the types are the same, then this will copy the stuff to
  1212. // do appropriate ref counting ...
  1213. //
  1214. hr = VariantChangeType(&v2, &v, 0, vt);
  1215. if (FAILED(hr)) {
  1216. VariantClear(&v);
  1217. return FALSE;
  1218. }
  1219. // copy the data to where the user wants it
  1220. //
  1221. CopyMemory(pData, &(v2.lVal), g_rgcbDataTypeSize[vt]);
  1222. VariantClear(&v);
  1223. return TRUE;
  1224. }
  1225. //=--------------------------------------------------------------------------=
  1226. // COleControl::GetAmbientFont [callable]
  1227. //=--------------------------------------------------------------------------=
  1228. // gets the current font for the user.
  1229. //
  1230. // Parameters:
  1231. // IFont ** - [out] where to put the font.
  1232. //
  1233. // Output:
  1234. // BOOL - FALSE means couldn't get it.
  1235. //
  1236. // Notes:
  1237. //
  1238. BOOL COleControl::GetAmbientFont
  1239. (
  1240. IFont **ppFont
  1241. )
  1242. {
  1243. IDispatch *pFontDisp;
  1244. // we don't have to do much here except get the ambient property and QI
  1245. // it for the user.
  1246. //
  1247. *ppFont = NULL;
  1248. if (!GetAmbientProperty(DISPID_AMBIENT_FONT, VT_DISPATCH, &pFontDisp))
  1249. return FALSE;
  1250. pFontDisp->QueryInterface(IID_IFont, (void **)ppFont);
  1251. pFontDisp->Release();
  1252. return (*ppFont) ? TRUE : FALSE;
  1253. }
  1254. //=--------------------------------------------------------------------------=
  1255. // COleControl::DesignMode
  1256. //=--------------------------------------------------------------------------=
  1257. // returns TRUE if we're in Design mode.
  1258. //
  1259. // Output:
  1260. // BOOL - true is design mode, false is run mode
  1261. //
  1262. // Notes:
  1263. //
  1264. BOOL COleControl::DesignMode
  1265. (
  1266. void
  1267. )
  1268. {
  1269. VARIANT_BOOL f;
  1270. // if we don't already know our run mode, go and get it. we'll assume
  1271. // it's true unless told otherwise [or if the operation fails ...]
  1272. //
  1273. if (!m_fModeFlagValid) {
  1274. f = TRUE;
  1275. m_fModeFlagValid = TRUE;
  1276. GetAmbientProperty(DISPID_AMBIENT_USERMODE, VT_BOOL, &f);
  1277. m_fRunMode = f;
  1278. }
  1279. return !m_fRunMode;
  1280. }
  1281. //=--------------------------------------------------------------------------=
  1282. // COleControl::FireEvent
  1283. //=--------------------------------------------------------------------------=
  1284. // fires an event. handles arbitrary number of arguments.
  1285. //
  1286. // Parameters:
  1287. // EVENTINFO * - [in] struct that describes the event.
  1288. // ... - arguments to the event
  1289. //
  1290. // Output:
  1291. // none
  1292. //
  1293. // Notes:
  1294. // - use stdarg's va_* macros.
  1295. //
  1296. void __cdecl COleControl::FireEvent
  1297. (
  1298. EVENTINFO *pEventInfo,
  1299. ...
  1300. )
  1301. {
  1302. va_list valist;
  1303. DISPPARAMS dispparams;
  1304. VARIANT rgvParameters[MAX_ARGS];
  1305. VARIANT *pv;
  1306. VARTYPE vt;
  1307. int iParameter;
  1308. int cbSize;
  1309. ASSERT(pEventInfo->cParameters <= MAX_ARGS, "Don't support more than MAX_ARGS params. sorry.");
  1310. va_start(valist, pEventInfo);
  1311. // copy the Parameters into the rgvParameters array. make sure we reverse
  1312. // them for automation
  1313. //
  1314. pv = &(rgvParameters[pEventInfo->cParameters - 1]);
  1315. for (iParameter = 0; iParameter < pEventInfo->cParameters; iParameter++) {
  1316. vt = pEventInfo->rgTypes[iParameter];
  1317. // if it's a by value variant, then just copy the whole
  1318. // dang thing
  1319. //
  1320. if (vt == VT_VARIANT)
  1321. *pv = va_arg(valist, VARIANT);
  1322. else {
  1323. // copy the vt and the data value.
  1324. //
  1325. pv->vt = vt;
  1326. if (vt & VT_BYREF)
  1327. cbSize = sizeof(void *);
  1328. else
  1329. cbSize = g_rgcbDataTypeSize[vt];
  1330. // small optimization -- we can copy 2/4 bytes over quite
  1331. // quickly.
  1332. //
  1333. if (cbSize == sizeof(short))
  1334. V_I2(pv) = va_arg(valist, short);
  1335. else if (cbSize == 4)
  1336. V_I4(pv) = va_arg(valist, long);
  1337. else {
  1338. // copy over 8 bytes
  1339. //
  1340. ASSERT(cbSize == 8, "don't recognize the type!!");
  1341. V_CY(pv) = va_arg(valist, CURRENCY);
  1342. }
  1343. }
  1344. pv--;
  1345. }
  1346. // fire the event
  1347. //
  1348. dispparams.rgvarg = rgvParameters;
  1349. dispparams.cArgs = pEventInfo->cParameters;
  1350. dispparams.rgdispidNamedArgs = NULL;
  1351. dispparams.cNamedArgs = 0;
  1352. m_cpEvents.DoInvoke(pEventInfo->dispid, &dispparams);
  1353. va_end(valist);
  1354. }
  1355. //=--------------------------------------------------------------------------=
  1356. // COleControl::AfterCreateWindow [overridable]
  1357. //=--------------------------------------------------------------------------=
  1358. // something the user can pay attention to
  1359. //
  1360. // Output:
  1361. // BOOL - false means fatal error, can't continue
  1362. // Notes:
  1363. //
  1364. BOOL COleControl::AfterCreateWindow
  1365. (
  1366. void
  1367. )
  1368. {
  1369. return TRUE;
  1370. }
  1371. //=--------------------------------------------------------------------------=
  1372. // COleControl::BeforeCreateWindow [overridable]
  1373. //=--------------------------------------------------------------------------=
  1374. // called just before we create a window. the user should register their
  1375. // window class here, and set up any other things, such as the title of
  1376. // the window, and/or sytle bits, etc ...
  1377. //
  1378. // Parameters:
  1379. // DWORD * - [out] dwWindowFlags
  1380. // DWORD * - [out] dwExWindowFlags
  1381. // LPSTR - [out] name of window to create
  1382. //
  1383. // Output:
  1384. // BOOL - false means fatal error, can't continue
  1385. //
  1386. // Notes:
  1387. //
  1388. BOOL COleControl::BeforeCreateWindow
  1389. (
  1390. DWORD *pdwWindowStyle,
  1391. DWORD *pdwExWindowStyle,
  1392. LPSTR pszWindowTitle
  1393. )
  1394. {
  1395. return TRUE;
  1396. }
  1397. //=--------------------------------------------------------------------------=
  1398. // COleControl::InvalidateControl [callable]
  1399. //=--------------------------------------------------------------------------=
  1400. void COleControl::InvalidateControl
  1401. (
  1402. LPCRECT lpRect
  1403. )
  1404. {
  1405. if (m_fInPlaceActive)
  1406. InvalidateRect(m_hwnd, lpRect, TRUE);
  1407. else
  1408. ViewChanged();
  1409. // CONSIDER: one might want to call pOleAdviseHolder->OnDataChanged() here
  1410. // if there was support for IDataObject
  1411. }
  1412. //=--------------------------------------------------------------------------=
  1413. // COleControl::SetControlSize [callable]
  1414. //=--------------------------------------------------------------------------=
  1415. // sets the control size. they'll give us the size in pixels. we've got to
  1416. // convert them back to HIMETRIC before passing them on!
  1417. //
  1418. // Parameters:
  1419. // SIZEL * - [in] new size
  1420. //
  1421. // Output:
  1422. // BOOL
  1423. //
  1424. // Notes:
  1425. //
  1426. BOOL COleControl::SetControlSize
  1427. (
  1428. SIZEL *pSize
  1429. )
  1430. {
  1431. HRESULT hr;
  1432. SIZEL slHiMetric;
  1433. PixelToHiMetric(pSize, &slHiMetric);
  1434. hr = SetExtent(DVASPECT_CONTENT, &slHiMetric);
  1435. return (FAILED(hr)) ? FALSE : TRUE;
  1436. }
  1437. //=--------------------------------------------------------------------------=
  1438. // COleControl::RecreateControlWindow [callable]
  1439. //=--------------------------------------------------------------------------=
  1440. // called by a [subclassed, typically] control to recreate it's control
  1441. // window.
  1442. //
  1443. // Parameters:
  1444. // none
  1445. //
  1446. // Output:
  1447. // HRESULT
  1448. //
  1449. // Notes:
  1450. // - NOTE: USE ME EXTREMELY SPARINGLY! THIS IS AN EXTREMELY EXPENSIVE
  1451. // OPERATION!
  1452. //
  1453. HRESULT COleControl::RecreateControlWindow
  1454. (
  1455. void
  1456. )
  1457. {
  1458. HRESULT hr;
  1459. HWND hwndPrev = HWND_TOP;
  1460. // we need to correctly preserve the control's position within the
  1461. // z-order here.
  1462. //
  1463. if (m_hwnd)
  1464. hwndPrev = ::GetWindow(m_hwnd, GW_HWNDPREV);
  1465. // if we're in place active, then we have to deactivate, and reactivate
  1466. // ourselves with the new window ...
  1467. //
  1468. if (m_fInPlaceActive) {
  1469. hr = InPlaceDeactivate();
  1470. RETURN_ON_FAILURE(hr);
  1471. hr = InPlaceActivate((m_fUIActive) ? OLEIVERB_UIACTIVATE : OLEIVERB_INPLACEACTIVATE);
  1472. RETURN_ON_FAILURE(hr);
  1473. } else if (m_hwnd) {
  1474. DestroyWindow(m_hwnd);
  1475. m_hwnd = NULL;
  1476. if (m_hwndReflect) {
  1477. DestroyWindow(m_hwndReflect);
  1478. m_hwndReflect = NULL;
  1479. }
  1480. CreateInPlaceWindow(0, 0, FALSE);
  1481. }
  1482. // restore z-order position
  1483. //
  1484. if (m_hwnd)
  1485. SetWindowPos(m_hwnd, hwndPrev, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
  1486. return m_hwnd ? S_OK : E_FAIL;
  1487. }
  1488. // from Globals.C. don't need to mutex it here since we only read it.
  1489. //
  1490. extern HINSTANCE g_hInstResources;
  1491. //=--------------------------------------------------------------------------=
  1492. // COleControl::GetResourceHandle [callable]
  1493. //=--------------------------------------------------------------------------=
  1494. // gets the HINSTANCE of the DLL where the control should get resources
  1495. // from. implemented in such a way to support satellite DLLs.
  1496. //
  1497. // Output:
  1498. // HINSTANCE
  1499. //
  1500. // Notes:
  1501. //
  1502. HINSTANCE COleControl::GetResourceHandle
  1503. (
  1504. void
  1505. )
  1506. {
  1507. if (!g_fSatelliteLocalization)
  1508. return g_hInstance;
  1509. // if we've already got it, then there's not all that much to do.
  1510. // don't need to crit sect this one right here since even if they do fall
  1511. // into the ::GetResourceHandle call, it'll properly deal with things.
  1512. //
  1513. if (g_hInstResources)
  1514. return g_hInstResources;
  1515. // we'll get the ambient localeid from the host, and pass that on to the
  1516. // automation object.
  1517. //
  1518. // crit sect this for apartment threading support.
  1519. //
  1520. EnterCriticalSection(&g_CriticalSection);
  1521. if (!g_fHaveLocale)
  1522. // if we can't get the ambient locale id, then we'll just continue
  1523. // with the globally set up value.
  1524. //
  1525. if (!GetAmbientProperty(DISPID_AMBIENT_LOCALEID, VT_I4, &g_lcidLocale))
  1526. goto Done;
  1527. g_fHaveLocale = TRUE;
  1528. Done:
  1529. LeaveCriticalSection(&g_CriticalSection);
  1530. return ::GetResourceHandle();
  1531. }