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.

2018 lines
58 KiB

  1. //=--------------------------------------------------------------------------=
  2. // ControlEmbedding.Cpp
  3. //=--------------------------------------------------------------------------=
  4. // Copyright 1995 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. // implementation of the interfaces required for inplace activation for
  13. // COleControl
  14. //
  15. #include "pch.h"
  16. #include "CtrlObj.H"
  17. #include "CtlHelp.H"
  18. #include "StdEnum.H"
  19. // for ASSERT and FAIL
  20. //
  21. SZTHISFILE
  22. //=--------------------------------------------------------------------------=
  23. // all controls support the following in-place verbs at an absolute minimum.
  24. //
  25. #define CINPLACEVERBS 4
  26. const VERBINFO rgInPlaceVerbs [] = {
  27. { OLEIVERB_SHOW, 0, 0, 0},
  28. { OLEIVERB_HIDE, 0, 0, 0},
  29. { OLEIVERB_INPLACEACTIVATE, 0, 0, 0},
  30. { OLEIVERB_PRIMARY, 0, 0, 0}
  31. };
  32. // NOTE: Resource ID for Properties string must be 1000
  33. //
  34. const VERBINFO ovProperties =
  35. { CTLIVERB_PROPERTIES, 1000, 0, OLEVERBATTRIB_ONCONTAINERMENU };
  36. const VERBINFO ovUIActivate =
  37. { OLEIVERB_UIACTIVATE, 0, 0, 0};
  38. //=--------------------------------------------------------------------------=
  39. // COleControl::GetControlInfo (IOleControl)
  40. //=--------------------------------------------------------------------------=
  41. // returns some information on a control, such as an accelerator table, and
  42. // flags. really used for keyboard handling and mnemonics
  43. //
  44. // Parameters:
  45. // CONTROLINFO * - [in] where to put said information
  46. //
  47. // Output:
  48. // HRESULT - S_OK
  49. //
  50. // Notes:
  51. //
  52. STDMETHODIMP COleControl::GetControlInfo
  53. (
  54. CONTROLINFO *pControlInfo
  55. )
  56. {
  57. CHECK_POINTER(pControlInfo);
  58. // certain hosts have a bug in which it doesn't initialize the cb in the
  59. // CONTROLINFO structure, so we can only assert on that here.
  60. //
  61. ASSERT(pControlInfo->cb == sizeof(CONTROLINFO), "Host doesn't initialize CONTROLINFO structure");
  62. // NOTE: control writers should override this routine if they want to
  63. // return accelerator information in their control.
  64. //
  65. pControlInfo->hAccel = NULL;
  66. pControlInfo->cAccel = NULL;
  67. pControlInfo->dwFlags = 0; //joejo - Vegas #VBE9106 uninitialized dwFlags
  68. return S_OK;
  69. }
  70. //=--------------------------------------------------------------------------=
  71. // COleControl::OnMnemonic [IOleControl]
  72. //=--------------------------------------------------------------------------=
  73. // the container has decided to pass on a key that the end-user has pressed to
  74. // us. default implementation will be to just activate the control. people
  75. // looking for more functionality should override this method.
  76. //
  77. // Parameters:
  78. // LPMSG - [in] message for this mnemonic
  79. //
  80. // Output:
  81. // HRESULT - S_OK, E_POINTER
  82. //
  83. // Notes:
  84. //
  85. STDMETHODIMP COleControl::OnMnemonic
  86. (
  87. LPMSG pMsg
  88. )
  89. {
  90. // OVERRIDE: default implementation is to just activate our control.
  91. // user can override if they want more interesting behaviour.
  92. //
  93. return InPlaceActivate(OLEIVERB_UIACTIVATE);
  94. }
  95. //=--------------------------------------------------------------------------=
  96. // COleControl:OnAmbientPropertyChange [IOleControl]
  97. //=--------------------------------------------------------------------------=
  98. // a container calls this whenever it changes an ambient property.
  99. //
  100. // Parameters:
  101. // DISPID - [in] dispid of the property that changed.
  102. //
  103. // Output:
  104. // HRESULT - S_OK
  105. //
  106. // Notes:
  107. //
  108. STDMETHODIMP COleControl::OnAmbientPropertyChange
  109. (
  110. DISPID dispid
  111. )
  112. {
  113. // if we're being told about a change in mode [design/run] then
  114. // remember that so our stashing of mode will update itself
  115. // correctly
  116. //
  117. if (dispid == DISPID_AMBIENT_USERMODE || dispid == DISPID_UNKNOWN)
  118. m_fModeFlagValid = FALSE;
  119. if (dispid == DISPID_AMBIENT_LOCALEID || dispid == DISPID_UNKNOWN)
  120. {
  121. ENTERCRITICALSECTION1(&g_CriticalSection); // Should be a crit sect around this.
  122. g_fHaveLocale = FALSE; // Cause the lcid to be re-browsed when its needed
  123. LEAVECRITICALSECTION1(&g_CriticalSection);
  124. }
  125. // just pass this on to the derived control and see if they want
  126. // to do anything with it.
  127. //
  128. AmbientPropertyChanged(dispid);
  129. return S_OK;
  130. }
  131. //=--------------------------------------------------------------------------=
  132. // COleControL::FreezeEvents [IOleControl]
  133. //=--------------------------------------------------------------------------=
  134. // allows a container to freeze all of a controls events. when events are
  135. // frozen, a control will not fire any of them.
  136. //
  137. // Parameters:
  138. // BOOL - [in] TRUE means FREEZE, FALSE means THAW
  139. //
  140. // Output:
  141. // HRESULT - S_OK
  142. //
  143. // Notes:
  144. // - we maintain an internal count of freezes versus thaws.
  145. //
  146. STDMETHODIMP COleControl::FreezeEvents
  147. (
  148. BOOL fFreeze
  149. )
  150. {
  151. // OVERRIDE: by default, we don't care. user can override if they want to.
  152. //
  153. return S_OK;
  154. }
  155. //=--------------------------------------------------------------------------=
  156. // COleControl::SetClientSite [IOleObject]
  157. //=--------------------------------------------------------------------------=
  158. // informs the embedded object [control] of it's client site [display
  159. // location] within it's container
  160. //
  161. // Parameters:
  162. // IOleClientSite * - [in] pointer to client site.
  163. //
  164. // Output:
  165. // HRESULT - S_OK, E_UNEXPECTED
  166. //
  167. // Notes:
  168. //
  169. STDMETHODIMP COleControl::SetClientSite
  170. (
  171. IOleClientSite *pClientSite
  172. )
  173. {
  174. // make sure we free up all site pointers we're holding on to! otherwise,
  175. // we can run into problems during aggregation
  176. //
  177. RELEASE_OBJECT(m_pClientSite);
  178. RELEASE_OBJECT(m_pControlSite);
  179. RELEASE_OBJECT(m_pSimpleFrameSite);
  180. // store away the new client site
  181. //
  182. m_pClientSite = pClientSite;
  183. // if we've actually got one, then get some other interfaces we want to keep
  184. // around, and keep a handle on it
  185. //
  186. if (m_pClientSite) {
  187. m_pClientSite->AddRef();
  188. m_pClientSite->QueryInterface(IID_IOleControlSite, (void **)&m_pControlSite);
  189. if (OLEMISCFLAGSOFCONTROL(m_ObjectType) & OLEMISC_SIMPLEFRAME)
  190. m_pClientSite->QueryInterface(IID_ISimpleFrameSite, (void **)&m_pSimpleFrameSite);
  191. } else {
  192. // if they're telling us to clear our site pointers, go and release
  193. // everything else as well
  194. //
  195. RELEASE_OBJECT(m_pInPlaceSite);
  196. RELEASE_OBJECT(m_pInPlaceSiteWndless);
  197. RELEASE_OBJECT(m_pDispAmbient);
  198. }
  199. // now get the user to clear out/re-establish the pointers they want
  200. //
  201. return OnSetClientSite();
  202. }
  203. //=--------------------------------------------------------------------------=
  204. // COleControl::GetClientSite [IOleObject]
  205. //=--------------------------------------------------------------------------=
  206. // obtains a pointer to the controls client site.
  207. //
  208. // Parameters:
  209. // IOleClientSite ** - [out]
  210. //
  211. // Output:
  212. // HRESULT - S_OK
  213. //
  214. // Notes:
  215. //
  216. STDMETHODIMP COleControl::GetClientSite
  217. (
  218. IOleClientSite **ppClientSite
  219. )
  220. {
  221. CHECK_POINTER(ppClientSite);
  222. *ppClientSite = m_pClientSite;
  223. ADDREF_OBJECT(*ppClientSite);
  224. return S_OK;
  225. }
  226. //=--------------------------------------------------------------------------=
  227. // COleControl::SetHostNames [IOleObject]
  228. //=--------------------------------------------------------------------------=
  229. // Provides the control with the name of its container application and the
  230. // compound document in which it is embedded
  231. //
  232. // Parameters:
  233. // LPCOLESTR - [in] name of container application
  234. // LPCOLESTR - [in] name of container document
  235. //
  236. // Output:
  237. // HRESULT - S_OK
  238. //
  239. // Notes:
  240. // - we don't care about this
  241. //
  242. STDMETHODIMP COleControl::SetHostNames
  243. (
  244. LPCOLESTR szContainerApp,
  245. LPCOLESTR szContainerObject
  246. )
  247. {
  248. // we don't care about these
  249. //
  250. return S_OK;
  251. }
  252. //=--------------------------------------------------------------------------=
  253. // COleControl::Close [IOleObject]
  254. //=--------------------------------------------------------------------------=
  255. // Changes the control from the running to the loaded state
  256. //
  257. // Parameters:
  258. // DWORD - [in] indicates whether to save the object before closing
  259. //
  260. // Output:
  261. // HRESULT - S_OK, OLE_E_PROMPTSAVECANCELLED
  262. //
  263. // Notes:
  264. //
  265. STDMETHODIMP COleControl::Close
  266. (
  267. DWORD dwSaveOption
  268. )
  269. {
  270. HRESULT hr;
  271. if (m_fInPlaceActive) {
  272. hr = InPlaceDeactivate();
  273. RETURN_ON_FAILURE(hr);
  274. }
  275. // handle the save flag.
  276. //
  277. if ((dwSaveOption == OLECLOSE_SAVEIFDIRTY || dwSaveOption == OLECLOSE_PROMPTSAVE) && m_fDirty) {
  278. if (m_pClientSite) m_pClientSite->SaveObject();
  279. if (m_pOleAdviseHolder) m_pOleAdviseHolder->SendOnSave();
  280. }
  281. return S_OK;
  282. }
  283. //=--------------------------------------------------------------------------=
  284. // COleControl::SetMoniker [IOleObject]
  285. //=--------------------------------------------------------------------------=
  286. // Notifies an object of its container's moniker, the object's own moniker
  287. // relative to the container, or the object's full moniker
  288. //
  289. // Parameters:
  290. // DWORD - [in] which moniker is being set
  291. // IMoniker * - [in] the moniker
  292. //
  293. // Output:
  294. // HRESULT - S_OK, E_FAIL
  295. //
  296. // Notes:
  297. // - we don't support monikers.
  298. //
  299. STDMETHODIMP COleControl::SetMoniker
  300. (
  301. DWORD dwWhichMoniker,
  302. IMoniker *pMoniker
  303. )
  304. {
  305. return E_NOTIMPL;
  306. }
  307. //=--------------------------------------------------------------------------=
  308. // COleControl::GetMoniker [IOleObject]
  309. //=--------------------------------------------------------------------------=
  310. // Returns a embedded object's moniker, which the caller can use to link to
  311. // the object
  312. //
  313. // Parameters:
  314. // DWORD - [in] how it's assigned
  315. // DWORD - [in] which moniker
  316. // IMoniker ** - [out] duh.
  317. //
  318. // Output:
  319. // HRESULT - E_NOTIMPL
  320. //
  321. // Notes:
  322. // - we don't support monikers
  323. //
  324. STDMETHODIMP COleControl::GetMoniker
  325. (
  326. DWORD dwAssign,
  327. DWORD dwWhichMoniker,
  328. IMoniker **ppMonikerOut
  329. )
  330. {
  331. return E_NOTIMPL;
  332. }
  333. //=--------------------------------------------------------------------------=
  334. // COleControl::InitFromData [IOleObject]
  335. //=--------------------------------------------------------------------------=
  336. // Initializes a newly created object with data from a specified data object,
  337. // which can reside either in the same container or on the Clipboard
  338. //
  339. // Parameters:
  340. // IDataObject* - [in] data object with the data
  341. // BOOL - [in] how object is created
  342. // DWORD - reserved
  343. //
  344. // Output:
  345. // HRESULT - S_OK, S_FALSE, E_NOTIMPL, OLE_E_NOTRUNNING
  346. //
  347. // Notes:
  348. // - we don't have data object support
  349. //
  350. STDMETHODIMP COleControl::InitFromData
  351. (
  352. IDataObject *pDataObject,
  353. BOOL fCreation,
  354. DWORD dwReserved
  355. )
  356. {
  357. return E_NOTIMPL;
  358. }
  359. //=--------------------------------------------------------------------------=
  360. // COleControl::GetClipboardData [IOleObject]
  361. //=--------------------------------------------------------------------------=
  362. // Retrieves a data object containing the current contents of the control.
  363. // Using the pointer to this data object, it is possible to create a new control
  364. // with the same data as the original
  365. //
  366. // Parameters:
  367. // DWORD - reserved
  368. // IDataObject ** - [out] data object for this control
  369. //
  370. // Output:
  371. // HREUSLT - S_OK, E_NOTIMPL, OLE_E_NOTRUNNING
  372. //
  373. // Notes:
  374. //
  375. STDMETHODIMP COleControl::GetClipboardData
  376. (
  377. DWORD dwReserved,
  378. IDataObject **ppDataObject
  379. )
  380. {
  381. *ppDataObject = NULL; // be a good neighbour
  382. return E_NOTIMPL;
  383. }
  384. //=--------------------------------------------------------------------------=
  385. // COleControl::DoVerb [IOleObject]
  386. //=--------------------------------------------------------------------------=
  387. // Requests an object to perform an action in response to an end-user's
  388. // action.
  389. //
  390. // Parameters:
  391. // LONG - [in] verb to be performed
  392. // LPMSG - [in] event that invoked the verb
  393. // IOleClientSite * - [in] the controls active client site
  394. // LONG - [in] reserved
  395. // HWND - [in] handle of window containing the object.
  396. // LPCRECT - [in] pointer to objects's display rectangle
  397. //
  398. // Output:
  399. // HRESULT - S_OK, OLE_E_NOTINPLACEACTIVE, OLE_E_CANT_BINDTOSOURCE,
  400. // DV_E_LINK, OLEOBJ_S_CANNOT_DOVERB_NOW, OLEOBJ_S_INVALIDHWND,
  401. // OLEOBJ_E_NOVERBS, OLEOBJ_S_INVALIDVERB, MK_E_CONNECT,
  402. // OLE_CLASSDIFF, E_NOTIMPL
  403. //
  404. // Notes:
  405. //
  406. STDMETHODIMP COleControl::DoVerb
  407. (
  408. LONG lVerb,
  409. LPMSG pMsg,
  410. IOleClientSite *pActiveSite,
  411. LONG lIndex,
  412. HWND hwndParent,
  413. LPCRECT prcPosRect
  414. )
  415. {
  416. HRESULT hr;
  417. switch (lVerb) {
  418. case OLEIVERB_SHOW:
  419. case OLEIVERB_INPLACEACTIVATE:
  420. case OLEIVERB_UIACTIVATE:
  421. return InPlaceActivate(lVerb);
  422. case OLEIVERB_HIDE:
  423. UIDeactivate();
  424. if (m_fInPlaceVisible) SetInPlaceVisible(FALSE);
  425. return S_OK;
  426. // we used to have OLEIVERB_PRIMARY InPlaceActivate Ourselves, but it
  427. // turns out that the CDK and certain hosts expect this to show the
  428. // properties instead. Users can change what this verb does at will.
  429. //
  430. case OLEIVERB_PRIMARY:
  431. case CTLIVERB_PROPERTIES:
  432. case OLEIVERB_PROPERTIES:
  433. {
  434. int iPage;
  435. CLSID *prgPropPages;
  436. // Only allow the Property Page to be displayed in design-mode.
  437. //
  438. if (!DesignMode())
  439. return S_OK;
  440. // show the frame ourselves if the host can't.
  441. //
  442. if (m_pControlSite) {
  443. hr = m_pControlSite->ShowPropertyFrame();
  444. if (hr != E_NOTIMPL)
  445. return hr;
  446. }
  447. IUnknown *pUnk = (IUnknown *)(IOleObject *)this;
  448. MAKE_WIDEPTR_FROMANSI(pwsz, NAMEOFOBJECT(m_ObjectType));
  449. // Allocate an array of CLSIDs
  450. //
  451. prgPropPages = (CLSID *) CtlHeapAlloc(g_hHeap, 0, CPROPPAGESOFCONTROL(m_ObjectType) * sizeof(CLSID));
  452. if (!prgPropPages)
  453. return E_OUTOFMEMORY;
  454. // Copy the CLSIDs pointed to by the array of CLSID pointers to
  455. // an array of CLSIDs. This conversion is necessary since OleCreatePropertyFrame
  456. // expects a pointer to an array of CLSIDs. CPROPPAGESOFCONTROL(index) returns
  457. // a pointer to an array of CLSID pointers.
  458. //
  459. for (iPage = 0; iPage < CPROPPAGESOFCONTROL(m_ObjectType); iPage++)
  460. prgPropPages[iPage] = *((PPROPPAGESOFCONTROL(m_ObjectType))[iPage]);
  461. ModalDialog(TRUE);
  462. ENTERCRITICALSECTION1(&g_CriticalSection); // This is for g_lcidLocale.
  463. hr = OleCreatePropertyFrame(GetActiveWindow(),
  464. GetSystemMetrics(SM_CXSCREEN) / 2,
  465. GetSystemMetrics(SM_CYSCREEN) / 2,
  466. pwsz,
  467. 1,
  468. &pUnk,
  469. CPROPPAGESOFCONTROL(m_ObjectType),
  470. prgPropPages,
  471. g_lcidLocale,
  472. NULL, NULL);
  473. LEAVECRITICALSECTION1(&g_CriticalSection);
  474. ModalDialog(FALSE);
  475. CtlHeapFree(g_hHeap, 0, prgPropPages);
  476. return hr;
  477. }
  478. default:
  479. // if it's a derived-control defined verb, pass it on to them
  480. //
  481. if (lVerb > 0) {
  482. hr = DoCustomVerb(lVerb);
  483. if (hr == OLEOBJ_S_INVALIDVERB) {
  484. // unrecognised verb -- just do the primary verb and
  485. // activate the sucker.
  486. //
  487. hr = InPlaceActivate(OLEIVERB_PRIMARY);
  488. return (FAILED(hr)) ? hr : OLEOBJ_S_INVALIDVERB;
  489. } else
  490. return hr;
  491. } else {
  492. // it's a verb we don't implement.
  493. //
  494. return E_NOTIMPL;
  495. }
  496. break;
  497. }
  498. // dead code
  499. FAIL("this should be dead code!");
  500. }
  501. //=--------------------------------------------------------------------------=
  502. // COleControl::EnumVerbs [IOleObject]
  503. //=--------------------------------------------------------------------------=
  504. // create an enumerator object for the verbs this object supports.
  505. //
  506. // Parameters:
  507. // IEnumOleVERB ** - [out] new enumerator.
  508. //
  509. // Output:
  510. // HRESULT - S_OK, E_OUTOFMEMORY
  511. //
  512. // Notes:
  513. //
  514. STDMETHODIMP COleControl::EnumVerbs
  515. (
  516. IEnumOLEVERB **ppEnumVerbs
  517. )
  518. {
  519. int cVerbs;
  520. OLEVERB *rgVerbs, *pVerb;
  521. DWORD dw = OLEMISCFLAGSOFCONTROL(m_ObjectType);
  522. BOOL fCanInPlace = !(dw & OLEMISC_INVISIBLEATRUNTIME) || (dw & OLEMISC_ACTIVATEWHENVISIBLE);
  523. BOOL fCanUIActivate = !(dw & OLEMISC_NOUIACTIVATE);
  524. BOOL fHasProperties = (CPROPPAGESOFCONTROL(m_ObjectType) != 0);
  525. int cVerbExtra = CCUSTOMVERBSOFCONTROL(m_ObjectType);
  526. // count up all the verbs
  527. //
  528. cVerbs = (fCanInPlace ? CINPLACEVERBS : 0) + (fCanUIActivate ? 1 : 0)
  529. + (fHasProperties ? 1 : 0) + cVerbExtra;
  530. // if there aren't any, this suddenly gets really easy !
  531. //
  532. if (cVerbs == 0)
  533. return OLEOBJ_E_NOVERBS;
  534. // HeapAlloc some storage for these dudes so that we can pass them on to
  535. // the standard enumerator!
  536. //
  537. if (! (rgVerbs = (OLEVERB *)CtlHeapAlloc(g_hHeap, 0, cVerbs * sizeof(OLEVERB))))
  538. return E_OUTOFMEMORY;
  539. // start copying over verbs. first, the in-place guys
  540. //
  541. pVerb = rgVerbs;
  542. if (fCanInPlace) {
  543. memcpy(pVerb, rgInPlaceVerbs, CINPLACEVERBS * sizeof(OLEVERB));
  544. pVerb += CINPLACEVERBS;
  545. }
  546. if (fCanUIActivate)
  547. memcpy(pVerb++, &ovUIActivate, sizeof(OLEVERB));
  548. // if their control has properties, copy that over now.
  549. //
  550. if (fHasProperties) {
  551. memcpy(pVerb, &ovProperties, sizeof(OLEVERB));
  552. pVerb++;
  553. }
  554. // finally, any custom verbs!
  555. //
  556. if (cVerbExtra) {
  557. memcpy(pVerb, CUSTOMVERBSOFCONTROL(m_ObjectType), sizeof(OLEVERB) * cVerbExtra);
  558. }
  559. *ppEnumVerbs = (IEnumOLEVERB *) (IEnumGeneric *) New CStandardEnum(IID_IEnumOLEVERB,
  560. cVerbs, sizeof(OLEVERB), rgVerbs, CopyOleVerb);
  561. if (!*ppEnumVerbs)
  562. return E_OUTOFMEMORY;
  563. // this forces us to go and look for the Localized DLLs. This is necessary here
  564. // because the CopyOleVerb will get information from localized resources, but
  565. // will only use the global GetResourceHandle, which only uses the global value
  566. // for the LCID. This turns out to not be a big performance hit, since this
  567. // function is typically only called in design mode, and we stash this value.
  568. //
  569. GetResourceHandle();
  570. return S_OK;
  571. }
  572. //=--------------------------------------------------------------------------=
  573. // COleControl::Update [IOleObject]
  574. //=--------------------------------------------------------------------------=
  575. // Updates an object handler's or link object's data or view caches.
  576. //
  577. // Output:
  578. // HRESULT - S_OK
  579. //
  580. // Notes:
  581. //
  582. STDMETHODIMP COleControl::Update
  583. (
  584. void
  585. )
  586. {
  587. // nothing to do!!!
  588. //
  589. return S_OK;
  590. }
  591. //=--------------------------------------------------------------------------=
  592. // COleControl::IsUpToDate [IOleObject]
  593. //=--------------------------------------------------------------------------=
  594. // Checks recursively whether or not an object is up to date.
  595. //
  596. // Output:
  597. // HRESULT - S_OK, S_FALSE, OLE_E_UNVAILABLE
  598. //
  599. // Notes:
  600. //
  601. STDMETHODIMP COleControl::IsUpToDate
  602. (
  603. void
  604. )
  605. {
  606. // we're always up to date
  607. //
  608. return S_OK;
  609. }
  610. //=--------------------------------------------------------------------------=
  611. // COleControl::GetUserClassID [IOleObject]
  612. //=--------------------------------------------------------------------------=
  613. // Returns the controls class identifier, the CLSID corresponding to the
  614. // string identifying the object to an end user.
  615. //
  616. // Parameters:
  617. // CLSID * - [in] where to put the CLSID
  618. //
  619. // Output:
  620. // HRESULT - S_OK, E_FAIL
  621. //
  622. // Notes:
  623. //
  624. STDMETHODIMP COleControl::GetUserClassID
  625. (
  626. CLSID *pclsid
  627. )
  628. {
  629. // this is the same as IPersist::GetClassID
  630. //
  631. return GetClassID(pclsid);
  632. }
  633. //=--------------------------------------------------------------------------=
  634. // COleControl::GetUserType [IOleObject]
  635. //=--------------------------------------------------------------------------=
  636. // Retrieves the user-type name of the control for display in user-interface
  637. // elements such as menus, list boxes, and dialog boxes.
  638. //
  639. // Parameters:
  640. // DWORD - [in] specifies the form of the type name.
  641. // LPOLESTR * - [out] where to put user type
  642. //
  643. // Output:
  644. // HRESULT - S_OK, OLE_S_USEREG, E_OUTOFMEMORY
  645. //
  646. // Notes:
  647. //
  648. STDMETHODIMP COleControl::GetUserType
  649. (
  650. DWORD dwFormOfType,
  651. LPOLESTR *ppszUserType
  652. )
  653. {
  654. *ppszUserType = OLESTRFROMANSI(NAMEOFOBJECT(m_ObjectType));
  655. return (*ppszUserType) ? S_OK : E_OUTOFMEMORY;
  656. }
  657. //=--------------------------------------------------------------------------=
  658. // COleControl::SetExtent [IOleObject]
  659. //=--------------------------------------------------------------------------=
  660. // Informs the control of how much display space its container has assigned it.
  661. //
  662. // Parameters:
  663. // DWORD - [in] which form or 'aspect' is to be displayed.
  664. // SIZEL * - [in] size limit for the control.
  665. //
  666. // Output:
  667. // HRESULT - S_OK, E_FAIL, OLE_E_NOTRUNNING
  668. //
  669. // Notes:
  670. //
  671. STDMETHODIMP COleControl::SetExtent
  672. (
  673. DWORD dwDrawAspect,
  674. SIZEL *psizel
  675. )
  676. {
  677. SIZEL sl, slOld;
  678. RECT rect;
  679. BOOL f;
  680. if (dwDrawAspect & DVASPECT_CONTENT) {
  681. // Call to OnPosRectChange may cause our extents to be set again. Accept the extents if this happens.
  682. //
  683. if (m_fChangingExtents)
  684. return S_OK;
  685. m_fChangingExtents = TRUE;
  686. // change the units to pixels, and resize the control.
  687. //
  688. HiMetricToPixel(psizel, &sl);
  689. // first call the user version. if they return FALSE, they want
  690. // to keep their current size
  691. //
  692. slOld = m_Size;
  693. f = OnSetExtent(&sl);
  694. if (f)
  695. m_Size = sl; /// Note: subclassing control may change the passed in &sl extents
  696. if (slOld.cx != m_Size.cx || slOld.cy != m_Size.cy)
  697. m_fDirty = TRUE;
  698. // set things up with our HWND if we've got one.
  699. //
  700. if (!m_pInPlaceSiteWndless)
  701. {
  702. if (m_fInPlaceActive)
  703. {
  704. // theoretically, one should not need to call OnPosRectChange
  705. // here, but there appear to be a few host related issues that
  706. // will make us keep it here. we won't, however, both with
  707. // windowless ole controls, since they are all new hosts who
  708. // should know better
  709. //
  710. if (m_hwnd)
  711. {
  712. rect = m_rcLocation;
  713. rect.right = rect.left + m_Size.cx;
  714. rect.bottom = rect.top + m_Size.cy;
  715. GetInPlaceSite()->OnPosRectChange(&rect); // May cause container to call our SetObjectRects
  716. }
  717. }
  718. else if (m_hwnd)
  719. {
  720. SetWindowPos(m_hwnd, NULL, 0, 0, m_Size.cx, m_Size.cy, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  721. }
  722. else
  723. {
  724. ViewChanged();
  725. }
  726. }
  727. if (!m_fInPlaceActive)
  728. {
  729. // Due to trident, we need to call RequestNewObjectLayout
  730. // here so we visually display our new extents.
  731. if (m_pClientSite)
  732. m_pClientSite->RequestNewObjectLayout();
  733. }
  734. m_fChangingExtents = FALSE;
  735. // return code depending on whether or not user accepted given
  736. // size
  737. //
  738. return (f) ? S_OK : E_FAIL;
  739. } else {
  740. // we don't support any other aspects.
  741. //
  742. return DV_E_DVASPECT;
  743. }
  744. // dead code
  745. FAIL("This should be dead code");
  746. }
  747. //=--------------------------------------------------------------------------=
  748. // COleControl::GetExtent [IOleObject]
  749. //=--------------------------------------------------------------------------=
  750. // Retrieves the control's current display size.
  751. //
  752. // Parameters:
  753. // DWORD - [in] aspect
  754. // SIZEL * - [in] where to put results
  755. //
  756. // Output:
  757. // S_OK, E_INVALIDARG
  758. //
  759. // Notes:
  760. //
  761. STDMETHODIMP COleControl::GetExtent
  762. (
  763. DWORD dwDrawAspect,
  764. SIZEL *pSizeLOut
  765. )
  766. {
  767. if (dwDrawAspect & DVASPECT_CONTENT) {
  768. PixelToHiMetric((const SIZEL *)&m_Size, pSizeLOut);
  769. return S_OK;
  770. } else {
  771. return DV_E_DVASPECT;
  772. }
  773. // dead code
  774. }
  775. //=--------------------------------------------------------------------------=
  776. // COleControl::Advise [IOleObject]
  777. //=--------------------------------------------------------------------------=
  778. // establishes and advisory connection between the control and the container,
  779. // in which the control will notify the container of certain events.
  780. //
  781. // Parameters:
  782. // IAdviseSink * - [in] advise sink of calling object
  783. // DWORD - [out] cookie
  784. //
  785. // Output:
  786. // HRESULT - S_OK, E_OUTOFMEMORY
  787. //
  788. // Notes:
  789. //
  790. STDMETHODIMP COleControl::Advise
  791. (
  792. IAdviseSink *pAdviseSink,
  793. DWORD *pdwConnection
  794. )
  795. {
  796. HRESULT hr;
  797. // if we haven't yet created a standard advise holder object, do so
  798. // now
  799. //
  800. if (!m_pOleAdviseHolder) {
  801. hr = CreateOleAdviseHolder(&m_pOleAdviseHolder);
  802. RETURN_ON_FAILURE(hr);
  803. }
  804. // just get it to do the work for us!
  805. //
  806. return m_pOleAdviseHolder->Advise(pAdviseSink, pdwConnection);
  807. }
  808. //=--------------------------------------------------------------------------=
  809. // COleControl::Unadvise [IOleObject]
  810. //=--------------------------------------------------------------------------=
  811. // Deletes a previously established advisory connection.
  812. //
  813. // Parameters:
  814. // DWORD - [in] connection cookie
  815. //
  816. // Output:
  817. // HRESULT - S_OK, E_FAIL, OLE_E_NOCONNECTION
  818. //
  819. // Notes:
  820. //
  821. STDMETHODIMP COleControl::Unadvise
  822. (
  823. DWORD dwConnection
  824. )
  825. {
  826. if (!m_pOleAdviseHolder) {
  827. FAIL("Somebody called Unadvise on IOleObject without calling Advise!");
  828. CONNECT_E_NOCONNECTION;
  829. }
  830. return m_pOleAdviseHolder->Unadvise(dwConnection);
  831. }
  832. //=--------------------------------------------------------------------------=
  833. // COleControl::EnumAdvise [IOleObject]
  834. //=--------------------------------------------------------------------------=
  835. // Enumerates the advisory connections registered for an object, so a container
  836. // can know what to release prior to closing down.
  837. //
  838. // Parameters:
  839. // IEnumSTATDATA ** - [out] where to put enumerator
  840. //
  841. // Output:
  842. // HRESULT - S_OK, E_FAIL, E_NOTIMPL
  843. //
  844. // Notes:
  845. //
  846. STDMETHODIMP COleControl::EnumAdvise
  847. (
  848. IEnumSTATDATA **ppEnumOut
  849. )
  850. {
  851. if (!m_pOleAdviseHolder) {
  852. FAIL("Somebody Called EnumAdvise without setting up any connections");
  853. *ppEnumOut = NULL;
  854. return E_FAIL;
  855. }
  856. return m_pOleAdviseHolder->EnumAdvise(ppEnumOut);
  857. }
  858. //=--------------------------------------------------------------------------=
  859. // COleControl::GetMiscStatus [IOleObject]
  860. //=--------------------------------------------------------------------------=
  861. // Returns a value indicating the status of an object at creation and loading.
  862. //
  863. // Parameters:
  864. // DWORD - [in] aspect desired
  865. // DWORD * - [out] where to put the bits.
  866. //
  867. // Output:
  868. // HRESULT - S_OK, OLE_S_USEREG, CO_E_CLASSNOTREG, CO_E_READREGDB
  869. //
  870. // Notes:
  871. //
  872. STDMETHODIMP COleControl::GetMiscStatus
  873. (
  874. DWORD dwAspect,
  875. DWORD *pdwStatus
  876. )
  877. {
  878. CHECK_POINTER(pdwStatus);
  879. if (dwAspect == DVASPECT_CONTENT) {
  880. *pdwStatus = OLEMISCFLAGSOFCONTROL(m_ObjectType);
  881. return S_OK;
  882. } else {
  883. return DV_E_DVASPECT;
  884. }
  885. // dead code
  886. }
  887. //=--------------------------------------------------------------------------=
  888. // COleControl::SetColorScheme [IOleObject]
  889. //=--------------------------------------------------------------------------=
  890. // Specifies the color palette that the object application should use when it
  891. // edits the specified object.
  892. //
  893. // Parameters:
  894. // LOGPALETTE * - [in] new palette
  895. //
  896. // Output:
  897. // HRESULT - S_OK, E_NOTIMPL, OLE_E_PALETTE, OLE_E_NOTRUNNING
  898. //
  899. // Notes:
  900. // - we don't care.
  901. //
  902. STDMETHODIMP COleControl::SetColorScheme
  903. (
  904. LOGPALETTE *pLogpal
  905. )
  906. {
  907. // OVERRIDE: control writers can use this if they want to
  908. //
  909. return S_OK;
  910. }
  911. //=--------------------------------------------------------------------------=
  912. // COleControl::GetWindow [IOleWindow/IOleInPlaceObject]
  913. //=--------------------------------------------------------------------------=
  914. // Returns the window handle to one of the windows participating in in-place
  915. // activation (frame, document, parent, or in-place object window).
  916. //
  917. // Parameters:
  918. // HWND * - [out] where to return window handle.
  919. //
  920. // Output:
  921. // HRESULT - S_OK, E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, E_FAIL
  922. //
  923. // Notes:
  924. // - this routine has slightly different semantics for windowless controls
  925. //
  926. STDMETHODIMP COleControl::GetWindow
  927. (
  928. HWND *phwnd
  929. )
  930. {
  931. // if we're windowles, then we want to return E_FAIL for this so hosts
  932. // know we're windowless. we'll also fail if we're not in-place active
  933. //
  934. if (m_pInPlaceSiteWndless || !m_fInPlaceActive)
  935. return E_FAIL;
  936. // otherwise, just return our outer window.
  937. //
  938. *phwnd = GetOuterWindow();
  939. return (*phwnd) ? S_OK : E_UNEXPECTED;
  940. }
  941. //=--------------------------------------------------------------------------=
  942. // COleControl::ContextSensitiveHelp [IOleWindow/IOleInPlaceObject]
  943. //=--------------------------------------------------------------------------=
  944. // Determines whether context-sensitive help mode should be entered during an
  945. // in-place activation session.
  946. //
  947. // Parameters:
  948. // BOOL - [in] whether or not to enter help mode.
  949. //
  950. // Output:
  951. // HRESULT - S_OK, E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED
  952. //
  953. // Notes:
  954. //
  955. STDMETHODIMP COleControl::ContextSensitiveHelp
  956. (
  957. BOOL fEnterMode
  958. )
  959. {
  960. return E_NOTIMPL;
  961. }
  962. //=--------------------------------------------------------------------------=
  963. // COleControl::InPlaceActivate
  964. //=--------------------------------------------------------------------------=
  965. // activates the control, and depending on the verb, optionally ui activates
  966. // it as well.
  967. //
  968. // Parameters:
  969. // LONG - [in] the verb that caused us to activate
  970. //
  971. // Output:
  972. // HRESULT
  973. //
  974. // Notes:
  975. // - this is spaghetti code at it's worst. effectively, we have to
  976. // be able to handle three types of site pointers -- IOleInPlaceSIte,
  977. // IOleInPlaceSiteEx, and IOleInPlaceSiteWindowless. not terribly
  978. // pretty.
  979. //
  980. HRESULT COleControl::InPlaceActivate
  981. (
  982. LONG lVerb
  983. )
  984. {
  985. BOOL f;
  986. SIZEL sizel;
  987. IOleInPlaceSiteEx *pIPSEx = NULL;
  988. HRESULT hr;
  989. BOOL fNoRedraw = FALSE;
  990. HWND hwndParent;
  991. // if we don't have a client site, then there's not much to do.
  992. //
  993. if (!m_pClientSite)
  994. return S_OK;
  995. // get an InPlace site pointer.
  996. //
  997. if (!GetInPlaceSite()) {
  998. // if they want windowless support, then we want IOleInPlaceSiteWindowless
  999. //
  1000. if (FCONTROLISWINDOWLESS(m_ObjectType))
  1001. m_pClientSite->QueryInterface(IID_IOleInPlaceSiteWindowless, (void **)&m_pInPlaceSiteWndless);
  1002. // if we're not able to do windowless siting, then we'll just get an
  1003. // IOleInPlaceSite pointer.
  1004. //
  1005. if (!m_pInPlaceSiteWndless) {
  1006. hr = m_pClientSite->QueryInterface(IID_IOleInPlaceSite, (void **)&m_pInPlaceSite);
  1007. RETURN_ON_FAILURE(hr);
  1008. }
  1009. }
  1010. // now, we want an IOleInPlaceSiteEx pointer for windowless and flicker free
  1011. // activation. if we're windowless, we've already got it, else we need to
  1012. // try and get it
  1013. //
  1014. if (m_pInPlaceSiteWndless) {
  1015. pIPSEx = (IOleInPlaceSiteEx *)m_pInPlaceSiteWndless;
  1016. pIPSEx->AddRef();
  1017. } else
  1018. m_pClientSite->QueryInterface(IID_IOleInPlaceSiteEx, (void **)&pIPSEx);
  1019. // if we're not already active, go and do it.
  1020. //
  1021. if (!m_fInPlaceActive || !m_fInPlaceVisible) {
  1022. OLEINPLACEFRAMEINFO InPlaceFrameInfo;
  1023. RECT rcPos, rcClip;
  1024. BOOL fJustSetPosition = m_fInPlaceActive;
  1025. // if we have a windowless site, see if we can go in-place windowless
  1026. // active
  1027. //
  1028. hr = S_FALSE;
  1029. if (fJustSetPosition)
  1030. hr = S_OK;
  1031. else if (m_pInPlaceSiteWndless) {
  1032. hr = m_pInPlaceSiteWndless->CanWindowlessActivate();
  1033. CLEANUP_ON_FAILURE(hr);
  1034. // if they refused windowless, we'll try windowed
  1035. //
  1036. if (S_OK != hr) {
  1037. ASSERT(m_pInPlaceSite == NULL, "In-place site is non-NULL. We're gonna leak.");
  1038. RELEASE_OBJECT(m_pInPlaceSiteWndless);
  1039. hr = m_pClientSite->QueryInterface(IID_IOleInPlaceSite, (void **)&m_pInPlaceSite);
  1040. CLEANUP_ON_FAILURE(hr);
  1041. }
  1042. }
  1043. // just try regular windowed in-place activation
  1044. //
  1045. if (hr != S_OK) {
  1046. hr = m_pInPlaceSite->CanInPlaceActivate();
  1047. if (hr != S_OK) {
  1048. hr = (FAILED(hr)) ? E_FAIL : hr;
  1049. goto CleanUp;
  1050. }
  1051. }
  1052. if (!fJustSetPosition)
  1053. {
  1054. // if we are here, then we have permission to go in-place active.
  1055. // now, announce our intentions to actually go ahead and do this.
  1056. //
  1057. hr = (pIPSEx) ? pIPSEx->OnInPlaceActivateEx(&fNoRedraw, (m_pInPlaceSiteWndless) ? ACTIVATE_WINDOWLESS : 0)
  1058. : m_pInPlaceSite->OnInPlaceActivate();
  1059. CLEANUP_ON_FAILURE(hr);
  1060. // if we're here, we're ready to go in-place active. we just need
  1061. // to set up some flags, and then create the window [if we have
  1062. // one]
  1063. //
  1064. m_fInPlaceActive = TRUE;
  1065. }
  1066. // In VB4, the position could have been changed while we
  1067. // were invisible, so if we were already InPlaceActive but not visible
  1068. // we need to get our size.
  1069. // REVIEW: Is this much of a performance hit? Is there a way to tell
  1070. // we've been resized in this case?
  1071. // we need to get some information about our location in the parent
  1072. // window, as well as some information about the parent
  1073. //
  1074. InPlaceFrameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);
  1075. hr = GetInPlaceSite()->GetWindow(&hwndParent);
  1076. if (SUCCEEDED(hr))
  1077. {
  1078. #ifdef MDAC_BUILD
  1079. #if 0
  1080. // hack fix for MDAC 8536 & 8738.
  1081. // To be used if VB doesn't/can't fix the real bug(s); hwndParent (or it's parent) is not sized properly.
  1082. // Unfortunately, this code also affects the hf grid. If we need to add a virtual function bool ResizeParentBeforeCreation()
  1083. // to COleControl (it should return false) and to the de.
  1084. if ( ResizeParentBeforeCreation() )
  1085. {
  1086. SIZE parent_size = m_Size;
  1087. if ( HWND grandparent = GetParent(hwndParent) )
  1088. {
  1089. RECT grandparent_bounds;
  1090. GetClientRect(grandparent,&grandparent_bounds);
  1091. parent_size.cx = grandparent_bounds.right;
  1092. parent_size.cy = grandparent_bounds.bottom;
  1093. }
  1094. if ( parent_size.cx > 0 && parent_size.cy > 0 )
  1095. {
  1096. SetWindowPos(hwndParent,NULL,0,0,parent_size.cx,parent_size.cy,SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE);
  1097. }
  1098. }
  1099. #endif
  1100. #endif
  1101. if(m_pInPlaceFrame)
  1102. RELEASE_OBJECT(m_pInPlaceFrame);
  1103. if(m_pInPlaceUIWindow)
  1104. RELEASE_OBJECT(m_pInPlaceUIWindow);
  1105. hr = GetInPlaceSite()->GetWindowContext(&m_pInPlaceFrame, &m_pInPlaceUIWindow, &rcPos, &rcClip, &InPlaceFrameInfo);
  1106. }
  1107. CLEANUP_ON_FAILURE(hr);
  1108. // make sure we'll display ourselves in the correct location with the correct size
  1109. //
  1110. sizel.cx = rcPos.right - rcPos.left;
  1111. sizel.cy = rcPos.bottom - rcPos.top;
  1112. f = OnSetExtent(&sizel);
  1113. if (f) m_Size = sizel;
  1114. SetObjectRects(&rcPos, &rcClip);
  1115. // finally, create our window if we have to!
  1116. //
  1117. if (!fJustSetPosition &&
  1118. !m_pInPlaceSiteWndless) {
  1119. SetInPlaceParent(hwndParent);
  1120. // create the window, and display it. die horribly if we couldnt'
  1121. //
  1122. if (!CreateInPlaceWindow(rcPos.left, rcPos.top, fNoRedraw)) {
  1123. hr = E_FAIL;
  1124. goto CleanUp;
  1125. }
  1126. // finally, tell the host of this
  1127. //
  1128. if (m_pClientSite)
  1129. m_pClientSite->ShowObject();
  1130. }
  1131. }
  1132. // don't need this any more
  1133. //
  1134. RELEASE_OBJECT(pIPSEx);
  1135. // if we're not inplace visible yet, do so now.
  1136. //
  1137. if (!m_fInPlaceVisible)
  1138. SetInPlaceVisible(TRUE);
  1139. // if we weren't asked to UIActivate, then we're done.
  1140. //
  1141. if (lVerb != OLEIVERB_PRIMARY && lVerb != OLEIVERB_UIACTIVATE)
  1142. return S_OK;
  1143. // if we're not already UI active, do sow now.
  1144. //
  1145. if (!m_fUIActive) {
  1146. m_fUIActive = TRUE;
  1147. // inform the container of our intent
  1148. //
  1149. GetInPlaceSite()->OnUIActivate();
  1150. // take the focus [which is what UI Activation is all about !]
  1151. //
  1152. SetFocus(TRUE);
  1153. // set ourselves up in the host.
  1154. //
  1155. m_pInPlaceFrame->SetActiveObject((IOleInPlaceActiveObject *)this, NULL);
  1156. if (m_pInPlaceUIWindow)
  1157. m_pInPlaceUIWindow->SetActiveObject((IOleInPlaceActiveObject *)this, NULL);
  1158. // we have to explicitly say we don't wany any border space.
  1159. //
  1160. m_pInPlaceFrame->SetBorderSpace(NULL);
  1161. if (m_pInPlaceUIWindow)
  1162. m_pInPlaceUIWindow->SetBorderSpace(NULL);
  1163. }
  1164. // be-de-be-de-be-de that's all folks!
  1165. //
  1166. return S_OK;
  1167. CleanUp:
  1168. // something catastrophic happened [or, at least something bad].
  1169. // die a horrible fiery mangled painful death.
  1170. //
  1171. QUICK_RELEASE(pIPSEx);
  1172. m_fInPlaceActive = FALSE;
  1173. return hr;
  1174. }
  1175. //=--------------------------------------------------------------------------=
  1176. // COleControl::InPlaceDeactivate [IOleInPlaceObject]
  1177. //=--------------------------------------------------------------------------=
  1178. // Deactivates an active in-place object and discards the object's undo state.
  1179. //
  1180. // Output:
  1181. // HRESULT - S_OK, E_UNEXPECTED
  1182. //
  1183. // Notes:
  1184. //
  1185. STDMETHODIMP COleControl::InPlaceDeactivate
  1186. (
  1187. void
  1188. )
  1189. {
  1190. // if we're not in-place active yet, then this is easy.
  1191. //
  1192. if (!m_fInPlaceActive)
  1193. return S_OK;
  1194. // transition from UIActive back to active
  1195. //
  1196. if (m_fUIActive)
  1197. UIDeactivate();
  1198. // tell the host we're going away
  1199. //
  1200. GetInPlaceSite()->OnInPlaceDeactivate();
  1201. m_fInPlaceActive = FALSE;
  1202. m_fInPlaceVisible = FALSE;
  1203. // if we have a window, tell it to go away.
  1204. //
  1205. if (m_hwnd) {
  1206. ASSERT(!m_pInPlaceSiteWndless, "internal state really messed up");
  1207. DestroyWindow(m_hwnd);
  1208. if (m_hwndReflect) {
  1209. SetWindowLong(m_hwndReflect, GWL_USERDATA, 0);
  1210. DestroyWindow(m_hwndReflect);
  1211. m_hwndReflect = NULL;
  1212. }
  1213. }
  1214. RELEASE_OBJECT(m_pInPlaceFrame);
  1215. RELEASE_OBJECT(m_pInPlaceUIWindow);
  1216. return S_OK;
  1217. }
  1218. //=--------------------------------------------------------------------------=
  1219. // COleControl::UIDeactivate [IOleInPlaceObject]
  1220. //=--------------------------------------------------------------------------=
  1221. // transitions us from UI Active to merely being active [visible] for
  1222. // a control, this doesn't mean all that much.
  1223. //
  1224. // Output:
  1225. // HRESULT - S_OK, E_UNEXPECTED
  1226. //
  1227. // Notes:
  1228. //
  1229. STDMETHODIMP COleControl::UIDeactivate
  1230. (
  1231. void
  1232. )
  1233. {
  1234. // if we're not UIActive, not much to do.
  1235. //
  1236. if (!m_fUIActive)
  1237. return S_OK;
  1238. m_fUIActive = FALSE;
  1239. // notify frame windows, if appropriate, that we're no longer ui-active.
  1240. //
  1241. if (m_pInPlaceUIWindow) m_pInPlaceUIWindow->SetActiveObject(NULL, NULL);
  1242. m_pInPlaceFrame->SetActiveObject(NULL, NULL);
  1243. // we don't need to explicitly release the focus here since somebody
  1244. // else grabbing the focus is what is likely to cause us to get lose it
  1245. //
  1246. GetInPlaceSite()->OnUIDeactivate(FALSE);
  1247. return S_OK;
  1248. }
  1249. //=--------------------------------------------------------------------------=
  1250. // COleControl::SetObjectRects [IOleInPlaceObject]
  1251. //=--------------------------------------------------------------------------=
  1252. // Indicates how much of the control is visible.
  1253. //
  1254. // Parameters:
  1255. // LPCRECT - [in] position of the control.
  1256. // LPCRECT - [in] clipping rectangle for the control.
  1257. //
  1258. // Output:
  1259. // HRESULT - S_OK, E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED
  1260. //
  1261. // Notes:
  1262. //
  1263. STDMETHODIMP COleControl::SetObjectRects
  1264. (
  1265. LPCRECT prcPos,
  1266. LPCRECT prcClip
  1267. )
  1268. {
  1269. #ifdef DEBUG
  1270. RECT rcDebug;
  1271. POINT ptDebug;
  1272. #endif
  1273. BOOL fRemoveWindowRgn;
  1274. // save out our current location. windowless controls want this more
  1275. // that windowed ones do, but everybody can have it just in case
  1276. //
  1277. // VEGAS#25109: a-cmai 3/9/98 -- Update m_rcLocation prior to doing
  1278. // work for windowed controls. This is because the SetWindowPos call
  1279. // may reenter when the control resizes itself. SetExtent requires that
  1280. // m_rcLocation contains the recent window location
  1281. //
  1282. m_rcLocation = *prcPos;
  1283. // move our window to the new location and handle clipping. not applicable
  1284. // for windowless controls, since the container will be responsible for all
  1285. // clipping.
  1286. //
  1287. if (m_hwnd) {
  1288. fRemoveWindowRgn = m_fUsingWindowRgn;
  1289. if (prcClip) {
  1290. // the container wants us to clip, so figure out if we really
  1291. // need to
  1292. //
  1293. RECT rcIXect;
  1294. if ( IntersectRect(&rcIXect, prcPos, prcClip) ) {
  1295. if (!EqualRect(&rcIXect, prcPos)) {
  1296. OffsetRect(&rcIXect, -(prcPos->left), -(prcPos->top));
  1297. SetWindowRgn(GetOuterWindow(), CreateRectRgnIndirect(&rcIXect), TRUE);
  1298. m_fUsingWindowRgn = TRUE;
  1299. fRemoveWindowRgn = FALSE;
  1300. }
  1301. }
  1302. }
  1303. if (fRemoveWindowRgn) {
  1304. SetWindowRgn(GetOuterWindow(), NULL, TRUE);
  1305. m_fUsingWindowRgn = FALSE;
  1306. }
  1307. RECT rc;
  1308. POINT pt;
  1309. pt.x = pt.y = 0;
  1310. ClientToScreen(GetParent(GetOuterWindow()), &pt);
  1311. GetWindowRect(GetOuterWindow(), &rc);
  1312. OffsetRect(&rc, - pt.x, - pt.y);
  1313. DWORD dwFlags = SWP_NOZORDER | SWP_NOACTIVATE;
  1314. if (rc.left == prcPos->left && rc.top == prcPos->top)
  1315. dwFlags |= SWP_NOMOVE;
  1316. if ((rc.right - rc.left) == (prcPos->right - prcPos->left) &&
  1317. (rc.bottom - rc.top) == (prcPos->bottom - prcPos->top))
  1318. dwFlags |= SWP_NOSIZE;
  1319. // We don't support zooming. Instead we resize the window
  1320. // to the given size and redraw within the new size.
  1321. //
  1322. // Note: The OuterWindow is either the reflector or control window
  1323. //
  1324. SetWindowPos(GetOuterWindow(), NULL, prcPos->left,
  1325. prcPos->top,
  1326. prcPos->right - prcPos->left,
  1327. prcPos->bottom - prcPos->top,
  1328. dwFlags);
  1329. #if DEBUG
  1330. // Make sure we caused a size change
  1331. //
  1332. if (!(dwFlags & SWP_NOSIZE))
  1333. {
  1334. ptDebug.x = ptDebug.y = 0;
  1335. ClientToScreen(GetParent(GetOuterWindow()), &ptDebug);
  1336. GetWindowRect(GetOuterWindow(), &rcDebug);
  1337. OffsetRect(&rcDebug, - ptDebug.x, - ptDebug.y);
  1338. // If these asserts get tripped that means the size changed between the SetWindowPos call and here
  1339. // Note: SetWindowPos will generate WM_NCCALCSIZE, WM_WINDOWPOSCHANGING and WM_WINDOWPOSCHANGED along with
  1340. // possible WM_NCPAINT, WM_PAINT and WM_SIZE. If in response to any of these messages we end up changing
  1341. // the size, then we may have a problem.
  1342. //
  1343. if ((prcPos->right - prcPos->left) != (rcDebug.right - rcDebug.left))
  1344. OutputDebugString("Width not set to expected value");
  1345. if ((prcPos->bottom - prcPos->top) != (rcDebug.bottom - rcDebug.top))
  1346. OutputDebugString("Height not set to expected value");
  1347. }
  1348. #endif
  1349. // VEGAS#25109: a-cmai 3/9/98 -- Update m_rcLocation
  1350. // after the call to SetWindowPos, since the window pos
  1351. // and or size may have been altered by the control
  1352. //
  1353. GetWindowRect(GetOuterWindow(), &m_rcLocation);
  1354. OffsetRect(&m_rcLocation, - pt.x, - pt.y);
  1355. // No need to resize the window again if GetOuterWindow is the same
  1356. //
  1357. if (m_hwnd && GetOuterWindow() != m_hwnd)
  1358. // We're position within the reflector window, so set position to 0, 0
  1359. //
  1360. SetWindowPos(m_hwnd, 0, 0, 0,
  1361. m_rcLocation.right - m_rcLocation.left,
  1362. m_rcLocation.bottom - m_rcLocation.top,
  1363. SWP_NOZORDER | SWP_NOACTIVATE);
  1364. }
  1365. return S_OK;
  1366. }
  1367. //=--------------------------------------------------------------------------=
  1368. // COleControl::ReactivateAndUndo [IOleInPlaceObject]
  1369. //=--------------------------------------------------------------------------=
  1370. // Reactivates a previously deactivated object, undoing the last state of the object.
  1371. //
  1372. // Output:
  1373. // HRESULT - S_OK, E_NOTUNDOABLE
  1374. //
  1375. // Notes:
  1376. //
  1377. STDMETHODIMP COleControl::ReactivateAndUndo
  1378. (
  1379. void
  1380. )
  1381. {
  1382. return E_NOTIMPL;
  1383. }
  1384. //=--------------------------------------------------------------------------=
  1385. // COleControl::OnWindowMessage [IOleInPlaceObjectWindowless]
  1386. //=--------------------------------------------------------------------------=
  1387. // this method lets the container dispatch a message to a windowless OLE
  1388. // object.
  1389. //
  1390. // Parameters:
  1391. // UINT - [in] the message
  1392. // WPARAM - [in] the messages wparam
  1393. // LPARAM - [in] duh.
  1394. // LRESULT * - [out] the output value
  1395. //
  1396. // Output:
  1397. // HRESULT - S_OK
  1398. //
  1399. // Notes:
  1400. // - people should call m_pInPlaceSiteWndless->OnDefWindowMessage [control
  1401. // writers should just call OcxDefWindowProc(msg, wparam, lparam)];
  1402. //
  1403. STDMETHODIMP COleControl::OnWindowMessage
  1404. (
  1405. UINT msg,
  1406. WPARAM wParam,
  1407. LPARAM lParam,
  1408. LRESULT *plResult
  1409. )
  1410. {
  1411. // little bit of pre-processing -- we need to handle some cases here
  1412. // before passing the messages on
  1413. //
  1414. switch (msg) {
  1415. // make sure our UI Activation correctly matches the focus
  1416. //
  1417. case WM_KILLFOCUS:
  1418. case WM_SETFOCUS:
  1419. // give the control site focus notification
  1420. //
  1421. if (m_fInPlaceActive && m_pControlSite)
  1422. m_pControlSite->OnFocus(msg == WM_SETFOCUS);
  1423. break;
  1424. }
  1425. // just pass it to the control's window proc.
  1426. //
  1427. *plResult = WindowProc(msg, wParam, lParam);
  1428. return S_OK;
  1429. }
  1430. //=--------------------------------------------------------------------------=
  1431. // COleControl::GetDropTarget [IOleInPlaceObjectWindowless]
  1432. //=--------------------------------------------------------------------------=
  1433. // this method returns a pointer to the objects IDropTarget interface. since
  1434. // they do not have a window, windowless objects cannot register an IDropTarget
  1435. // interface.
  1436. //
  1437. // Parameters:
  1438. // IDropTarget ** - [out]
  1439. //
  1440. // Output:
  1441. // HRESULT - S_OK, E_NOTIMPL
  1442. //
  1443. // Notes:
  1444. //
  1445. STDMETHODIMP COleControl::GetDropTarget
  1446. (
  1447. IDropTarget **ppDropTarget
  1448. )
  1449. {
  1450. // OVERRIDE: if you want to do drag and drop and you're windowless,
  1451. // override me.
  1452. //
  1453. return E_NOTIMPL;
  1454. }
  1455. //=--------------------------------------------------------------------------=
  1456. // COleControl::TranslateAccelerator [IOleInPlaceActiveObject]
  1457. //=--------------------------------------------------------------------------=
  1458. // Processes menu accelerator-key messages from the container's message queue.
  1459. //
  1460. // Parameters:
  1461. // LPMSG - [in] the message that has the special key in it.
  1462. //
  1463. // Output:
  1464. // HRESULT - S_OK, S_FALSE, E_UNEXPECTED
  1465. //
  1466. // Notes:
  1467. //
  1468. STDMETHODIMP COleControl::TranslateAccelerator
  1469. (
  1470. LPMSG pmsg
  1471. )
  1472. {
  1473. // see if we want it or not.
  1474. //
  1475. if (OnSpecialKey(pmsg))
  1476. return S_OK;
  1477. // if not, then we want to forward it back to the site for further processing
  1478. //
  1479. if (m_pControlSite)
  1480. return m_pControlSite->TranslateAccelerator(pmsg, _SpecialKeyState());
  1481. // we didn't want it.
  1482. //
  1483. return S_FALSE;
  1484. }
  1485. //=--------------------------------------------------------------------------=
  1486. // COleControl::OnFrameWindowActivate [IOleInPlaceActiveObject]
  1487. //=--------------------------------------------------------------------------=
  1488. // Notifies the control when the container's top-level frame window is
  1489. // activated or deactivated.
  1490. //
  1491. // Parameters:
  1492. // BOOL - [in] state of containers top level window.
  1493. //
  1494. // Output:
  1495. // HRESULT - S_OK
  1496. //
  1497. // Notes:
  1498. //
  1499. STDMETHODIMP COleControl::OnFrameWindowActivate
  1500. (
  1501. BOOL fActivate
  1502. )
  1503. {
  1504. // OVERRIDE: override this routine if you want floating toolbars,
  1505. // toolboxes, etc.
  1506. //
  1507. return S_OK;
  1508. }
  1509. //=--------------------------------------------------------------------------=
  1510. // COleControl::OnDocWindowActivate [IOleInPlaceActiveObject]
  1511. //=--------------------------------------------------------------------------=
  1512. // Notifies the active control when the container's document window is
  1513. // activated or deactivated.
  1514. //
  1515. // Parameters:
  1516. // BOOL - state of mdi child window.
  1517. //
  1518. // Output:
  1519. // HRESULT - S_OK
  1520. //
  1521. // Notes:
  1522. //
  1523. STDMETHODIMP COleControl::OnDocWindowActivate
  1524. (
  1525. BOOL fActivate
  1526. )
  1527. {
  1528. // OVERRIDE: override this routine if you want floating toolbars,
  1529. // toolboxes, etc.
  1530. // if we're supposed to activate and we're UI active, then just go and
  1531. // default to clearing out the toolbar space.
  1532. //
  1533. if (m_fUIActive && fActivate)
  1534. m_pInPlaceFrame->SetBorderSpace(NULL);
  1535. return S_OK;
  1536. }
  1537. //=--------------------------------------------------------------------------=
  1538. // COleControl::ResizeBorder [IOleInPlaceActiveObject]
  1539. //=--------------------------------------------------------------------------=
  1540. // Alerts the control that it needs to resize its border space.
  1541. //
  1542. // Parameters:
  1543. // LPCRECT - [in] new outer rectangle for border space
  1544. // IOleInPlaceUIWindow * - [in] the document or frame who's border has changed
  1545. // BOOL - [in] true if it was the fram window taht called.
  1546. //
  1547. // Output:
  1548. // HRESULT - S_OK
  1549. //
  1550. // Notes:
  1551. //
  1552. STDMETHODIMP COleControl::ResizeBorder
  1553. (
  1554. LPCRECT prcBorder,
  1555. IOleInPlaceUIWindow *pInPlaceUIWindow,
  1556. BOOL fFrame
  1557. )
  1558. {
  1559. // this is largely uninteresting to us, since we have no border.
  1560. //
  1561. return S_OK;
  1562. }
  1563. //=--------------------------------------------------------------------------=
  1564. // COleControl::EnableModeless [IOleInPlaceActiveObject]
  1565. //=--------------------------------------------------------------------------=
  1566. // Enables or disables modeless dialog boxes when the container creates or
  1567. // destroys a modal dialog box.
  1568. //
  1569. // Parameters:
  1570. // BOOL - [in] enable or disable modeless dialogs.
  1571. //
  1572. // Output:
  1573. // HRESULT - S_OK
  1574. //
  1575. // Notes:
  1576. //
  1577. STDMETHODIMP COleControl::EnableModeless
  1578. (
  1579. BOOL fEnable
  1580. )
  1581. {
  1582. // phenomenally uninteresting
  1583. //
  1584. return S_OK;
  1585. }
  1586. //=--------------------------------------------------------------------------=
  1587. // COleControl::GetClassInfo [IProvideClassInfo]
  1588. //=--------------------------------------------------------------------------=
  1589. // returns the TypeInfo for the control's coclass.
  1590. //
  1591. // Parameters:
  1592. // ITypeInfo ** - [out]
  1593. //
  1594. // Output:
  1595. // HRESULT
  1596. //
  1597. // Notes:
  1598. //
  1599. STDMETHODIMP COleControl::GetClassInfo
  1600. (
  1601. ITypeInfo **ppTypeInfo
  1602. )
  1603. {
  1604. ITypeLib *pTypeLib;
  1605. HRESULT hr;
  1606. CHECK_POINTER(ppTypeInfo);
  1607. *ppTypeInfo = NULL;
  1608. // go and get our type library.
  1609. // CONSIDER: - go to the same sorta scheme that we use for TypeInfo caching.
  1610. // CONSIDER: - consider trying to register our typelib if this fails.
  1611. //
  1612. ENTERCRITICALSECTION1(&g_CriticalSection); // This is for g_lcidlocale.
  1613. hr = LoadRegTypeLib(*g_pLibid, (USHORT)VERSIONOFOBJECT(m_ObjectType),
  1614. (USHORT)VERSIONMINOROFOBJECT(m_ObjectType),
  1615. LANGIDFROMLCID(g_lcidLocale), &pTypeLib);
  1616. LEAVECRITICALSECTION1(&g_CriticalSection);
  1617. RETURN_ON_FAILURE(hr);
  1618. // got the typelib. get typeinfo for our coclass.
  1619. //
  1620. hr = pTypeLib->GetTypeInfoOfGuid((REFIID)CLSIDOFOBJECT(m_ObjectType), ppTypeInfo);
  1621. pTypeLib->Release();
  1622. RETURN_ON_FAILURE(hr);
  1623. return S_OK;
  1624. }
  1625. //=--------------------------------------------------------------------------=
  1626. // COleControl::ViewChange [callable]
  1627. //=--------------------------------------------------------------------------=
  1628. // called whenever the view of the object has changed.
  1629. //
  1630. // Notes:
  1631. //
  1632. void COleControl::ViewChanged
  1633. (
  1634. void
  1635. )
  1636. {
  1637. // send the view change notification to anybody listening.
  1638. //
  1639. if (m_pViewAdviseSink) {
  1640. m_pViewAdviseSink->OnViewChange(DVASPECT_CONTENT, -1);
  1641. // if they only asked to be advised once, kill the connection
  1642. //
  1643. if (m_fViewAdviseOnlyOnce)
  1644. SetAdvise(DVASPECT_CONTENT, 0, NULL);
  1645. }
  1646. }
  1647. //=--------------------------------------------------------------------------=
  1648. // COleControl::SetInPlaceVisible [helper]
  1649. //=--------------------------------------------------------------------------=
  1650. // controls the visibility of the control window.
  1651. //
  1652. // Parameters:
  1653. // BOOL - TRUE shows FALSE hides.
  1654. //
  1655. // Notes:
  1656. //
  1657. void COleControl::SetInPlaceVisible
  1658. (
  1659. BOOL fShow
  1660. )
  1661. {
  1662. BOOL fVisible;
  1663. m_fInPlaceVisible = fShow;
  1664. // don't do anything if we don't have a window. otherwise, set it
  1665. //
  1666. if (m_hwnd) {
  1667. fVisible = ((GetWindowLong(GetOuterWindow(), GWL_STYLE) & WS_VISIBLE) != 0);
  1668. if (fVisible && !fShow)
  1669. ShowWindow(GetOuterWindow(), SW_HIDE);
  1670. else if (!fVisible && fShow)
  1671. ShowWindow(GetOuterWindow(), SW_SHOWNA);
  1672. }
  1673. }
  1674. //=--------------------------------------------------------------------------=
  1675. // COleControl::AmbientPropertyChanged [overridable]
  1676. //=--------------------------------------------------------------------------=
  1677. // a method that derived controls can override to do whatever they want.
  1678. // we don't particularily care about this event.
  1679. //
  1680. // Parameters:
  1681. // DISPID - [in] dispid of prop that changed.
  1682. //
  1683. // Notes:
  1684. //
  1685. void COleControl::AmbientPropertyChanged
  1686. (
  1687. DISPID dispid
  1688. )
  1689. {
  1690. // do nothing
  1691. }
  1692. //=--------------------------------------------------------------------------=
  1693. // COleControl::DoCustomVerb [overridable]
  1694. //=--------------------------------------------------------------------------=
  1695. // we were asked to execute a verb we don't know about right away. see if
  1696. // it's a verb that the dervied-control defined.
  1697. //
  1698. // Parameters:
  1699. // LONG - [in] the verb.
  1700. //
  1701. // Output:
  1702. // HRESULT - S_OK, OLEOBJ_S_INVALIDVERB
  1703. //
  1704. // Notes:
  1705. //
  1706. HRESULT COleControl::DoCustomVerb
  1707. (
  1708. LONG lVerb
  1709. )
  1710. {
  1711. return OLEOBJ_S_INVALIDVERB;
  1712. }
  1713. //=--------------------------------------------------------------------------=
  1714. // COleControl::OnSetExtent [overridable]
  1715. //=--------------------------------------------------------------------------=
  1716. // let the user do something in the resize, if they care.
  1717. //
  1718. // Parameters:
  1719. // SIZEL * - [in] new values.
  1720. //
  1721. // Output:
  1722. // BOOL - FALSE means keep current size
  1723. //
  1724. // Notes:
  1725. //
  1726. BOOL COleControl::OnSetExtent
  1727. (
  1728. SIZEL *pSizeL
  1729. )
  1730. {
  1731. return TRUE;
  1732. }
  1733. //=--------------------------------------------------------------------------=
  1734. // COleControl::OnSpecialKey [overridable]
  1735. //=--------------------------------------------------------------------------=
  1736. // allows controls to handle special keys such as arrows, CTRL+, etc ...
  1737. //
  1738. // Parameters:
  1739. // LPMSG - [in] the special key msg.
  1740. //
  1741. // Output:
  1742. // BOOL - TRUE we processed it, FALSE we didn't.
  1743. //
  1744. // Notes:
  1745. //
  1746. BOOL COleControl::OnSpecialKey
  1747. (
  1748. LPMSG pmsg
  1749. )
  1750. {
  1751. // do nothing.
  1752. //
  1753. return FALSE;
  1754. }
  1755. //=--------------------------------------------------------------------------=
  1756. // COleControl::ModalDialog [callable, utility]
  1757. //=--------------------------------------------------------------------------=
  1758. // should be called when the control is about to show and hide a modal dialog.
  1759. //
  1760. // Parameters:
  1761. // BOOL - [in] true means showing a modal dialog, false means done
  1762. //
  1763. // Notes:
  1764. //
  1765. void COleControl::ModalDialog
  1766. (
  1767. BOOL fShow
  1768. )
  1769. {
  1770. // notify the container of our intention to show a modal dialog...
  1771. //
  1772. if (m_pInPlaceFrame)
  1773. m_pInPlaceFrame->EnableModeless(!fShow);
  1774. }
  1775. //=--------------------------------------------------------------------------=
  1776. // COleControl::BeforeDestroyWindow [overridable]
  1777. //=--------------------------------------------------------------------------=
  1778. // called just before we destroy a window. gives the user the opportunity to
  1779. // save information out, especially if they're a subclassed control, and this
  1780. // is an interesting thing to do.
  1781. //
  1782. // Notes:
  1783. //
  1784. void COleControl::BeforeDestroyWindow
  1785. (
  1786. void
  1787. )
  1788. {
  1789. // fweeee
  1790. }
  1791. //=--------------------------------------------------------------------------=
  1792. // COleControl::OnSetClientSite [overrideable]
  1793. //=--------------------------------------------------------------------------=
  1794. // controls should implement this if they hold on to anything off the site.
  1795. // this is important to correctly support aggregation. they must free up
  1796. // everything they hold on to, and if m_pClientSite is not NULL, then they
  1797. // can re-establish things as they wish.
  1798. //
  1799. // Parameters:
  1800. // none
  1801. //
  1802. // Output:
  1803. // HRESULT
  1804. //
  1805. // Notes:
  1806. //
  1807. HRESULT COleControl::OnSetClientSite
  1808. (
  1809. void
  1810. )
  1811. {
  1812. // by default, the framework frees up everything in SetClientSite
  1813. //
  1814. return S_OK;
  1815. }