home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / activexcontrol / basectl / framewrk / ctlembed.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-05  |  53.1 KB  |  1,819 lines

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