CTLEMBED.CPP
//=--------------------------------------------------------------------------= 
// CtlEmbed.Cpp 
//=--------------------------------------------------------------------------= 
// Copyright 1995 - 1998 Microsoft Corporation.  All Rights Reserved. 
// 
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF  
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO  
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A  
// PARTICULAR PURPOSE. 
//=--------------------------------------------------------------------------= 
// 
// implementation of the interfaces required for inplace activation for 
// COleControl 
// 
 
#include "IPServer.H" 
#include "CtrlObj.H" 
 
#include "CtlHelp.H" 
#include "Globals.H" 
#include "StdEnum.H" 
#include "Util.H" 
 
// for ASSERT and FAIL 
// 
SZTHISFILE 
 
 
//=--------------------------------------------------------------------------= 
// all controls support the following in-place verbs at an absolute minimum. 
// 
#define CINPLACEVERBS 4 
 
const VERBINFO rgInPlaceVerbs [] = { 
    { OLEIVERB_SHOW,            0, 0, 0}, 
    { OLEIVERB_HIDE,            0, 0, 0}, 
    { OLEIVERB_INPLACEACTIVATE, 0, 0, 0}, 
    { OLEIVERB_PRIMARY,         0, 0, 0} 
}; 
 
// NOTE: Resource ID for Properties string must be 1000 
// 
const VERBINFO ovProperties = 
    { CTLIVERB_PROPERTIES, 1000, 0, OLEVERBATTRIB_ONCONTAINERMENU }; 
 
const VERBINFO ovUIActivate = 
    { OLEIVERB_UIACTIVATE, 0, 0, 0}; 
 
 
//=--------------------------------------------------------------------------= 
// COleControl::GetControlInfo    (IOleControl) 
//=--------------------------------------------------------------------------= 
// returns some information on a control, such as an accelerator table, and 
// flags.  really used for keyboard handling and mnemonics 
// 
// Parameters: 
//    CONTROLINFO *        - [in]  where to put said information 
// 
// Output: 
//    HRESULT              - S_OK 
// 
// Notes: 
// 
STDMETHODIMP COleControl::GetControlInfo 
( 
    CONTROLINFO *pControlInfo 
) 
{ 
    CHECK_POINTER(pControlInfo); 
 
    // certain hosts have a bug in which it doesn't initialize the cb in the 
    // CONTROLINFO structure, so we can only assert on that here. 
    // 
    ASSERT(pControlInfo->cb == sizeof(CONTROLINFO), "Host doesn't initialize CONTROLINFO structure"); 
 
    // NOTE: control writers should override this routine if they want to 
    // return accelerator information in their control. 
    // 
    pControlInfo->hAccel = NULL; 
    pControlInfo->cAccel = NULL; 
 
    return S_OK; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::OnMnemonic    [IOleControl] 
//=--------------------------------------------------------------------------= 
// the container has decided to pass on a key that the end-user has pressed to 
// us.  default implementation will be to just activate the control.  people 
// looking for more functionality should override this method. 
// 
// Parameters: 
//    LPMSG                - [in] message for this mnemonic 
// 
// Output: 
//    HRESULT              - S_OK, E_POINTER 
// 
// Notes: 
// 
STDMETHODIMP COleControl::OnMnemonic 
( 
    LPMSG pMsg 
) 
{ 
    // OVERRIDE: default implementation is to just activate our control.   
    // user can override if they want more interesting behaviour. 
    // 
    return InPlaceActivate(OLEIVERB_UIACTIVATE); 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl:OnAmbientPropertyChange    [IOleControl] 
//=--------------------------------------------------------------------------= 
// a container calls this whenever it changes an ambient property. 
// 
// Parameters: 
//    DISPID            - [in] dispid of the property that changed. 
// 
// Output: 
//    HRESULT           - S_OK 
// 
// Notes: 
// 
STDMETHODIMP COleControl::OnAmbientPropertyChange 
( 
    DISPID dispid 
) 
{ 
    // if we're being told about a change in mode [design/run] then 
    // remember that so our stashing of mode will update itself 
    // correctly 
    // 
    if (dispid == DISPID_AMBIENT_USERMODE || dispid == DISPID_UNKNOWN) 
        m_fModeFlagValid = FALSE; 
 
    // just pass this on to the derived control and see if they want 
    // to do anything with it. 
    // 
    AmbientPropertyChanged(dispid); 
    return S_OK; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControL::FreezeEvents    [IOleControl] 
//=--------------------------------------------------------------------------= 
// allows a container to freeze all of a controls events.  when events are 
// frozen, a control will not fire any of them. 
// 
// Parameters: 
//    BOOL            - [in] TRUE means FREEZE, FALSE means THAW 
// 
// Output: 
//    HRESULT         - S_OK 
// 
// Notes: 
//    - we maintain an internal count of freezes versus thaws. 
// 
STDMETHODIMP COleControl::FreezeEvents 
( 
    BOOL fFreeze 
) 
{ 
    // OVERRIDE: by default, we don't care.  user can override if they want to. 
    // 
    return S_OK; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::SetClientSite    [IOleObject] 
//=--------------------------------------------------------------------------= 
// informs the embedded object [control] of it's client site [display 
// location] within it's container 
// 
// Parameters: 
//    IOleClientSite *        - [in] pointer to client site. 
// 
// Output: 
//    HRESULT                 - S_OK, E_UNEXPECTED 
// 
// Notes: 
// 
STDMETHODIMP COleControl::SetClientSite 
( 
    IOleClientSite *pClientSite 
) 
{ 
    RELEASE_OBJECT(m_pClientSite); 
    RELEASE_OBJECT(m_pControlSite); 
    RELEASE_OBJECT(m_pSimpleFrameSite); 
 
    // store away the new client site 
    // 
    m_pClientSite = pClientSite; 
 
    // if we've actually got one, then get some other interfaces we want to keep 
    // around, and keep a handle on it 
    // 
    if (m_pClientSite) { 
        m_pClientSite->AddRef(); 
        m_pClientSite->QueryInterface(IID_IOleControlSite, (void **)&m_pControlSite); 
 
        if (OLEMISCFLAGSOFCONTROL(m_ObjectType) & OLEMISC_SIMPLEFRAME) 
            m_pClientSite->QueryInterface(IID_ISimpleFrameSite, (void **)&m_pSimpleFrameSite); 
    } 
 
    return S_OK; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::GetClientSite    [IOleObject] 
//=--------------------------------------------------------------------------= 
// obtains a pointer to the controls client site. 
// 
// Parameters: 
//    IOleClientSite **        - [out] 
// 
// Output: 
//    HRESULT                  - S_OK 
// 
// Notes: 
// 
STDMETHODIMP COleControl::GetClientSite 
( 
    IOleClientSite **ppClientSite 
) 
{ 
    CHECK_POINTER(ppClientSite); 
 
    *ppClientSite = m_pClientSite; 
    ADDREF_OBJECT(*ppClientSite); 
    return S_OK; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::SetHostNames    [IOleObject] 
//=--------------------------------------------------------------------------= 
// Provides the control with the name of its container application and the 
// compound document in which it is embedded 
// 
// Parameters: 
//    LPCOLESTR        - [in] name of container application 
//    LPCOLESTR        - [in] name of container document 
// 
// Output: 
//    HRESULT          - S_OK 
// 
// Notes: 
//    - we don't care about this 
// 
STDMETHODIMP COleControl::SetHostNames 
( 
    LPCOLESTR szContainerApp, 
    LPCOLESTR szContainerObject 
) 
{ 
    // we don't care about these 
    // 
    return S_OK; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::Close    [IOleObject] 
//=--------------------------------------------------------------------------= 
// Changes the control from the running to the loaded state 
// 
// Parameters: 
//    DWORD             - [in] indicates whether to save the object before closing 
// 
// Output: 
//    HRESULT           - S_OK, OLE_E_PROMPTSAVECANCELLED 
// 
// Notes: 
// 
STDMETHODIMP COleControl::Close 
( 
    DWORD dwSaveOption 
) 
{ 
    HRESULT hr; 
 
    if (m_fInPlaceActive) { 
        hr = InPlaceDeactivate(); 
        RETURN_ON_FAILURE(hr); 
    } 
 
    // handle the save flag. 
    // 
    if ((dwSaveOption == OLECLOSE_SAVEIFDIRTY || dwSaveOption == OLECLOSE_PROMPTSAVE) && m_fDirty) { 
        if (m_pClientSite) m_pClientSite->SaveObject(); 
        if (m_pOleAdviseHolder) m_pOleAdviseHolder->SendOnSave(); 
    } 
    return S_OK; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::SetMoniker    [IOleObject] 
//=--------------------------------------------------------------------------= 
// Notifies an object of its container's moniker, the object's own moniker 
// relative to the container, or the object's full moniker 
// 
// Parameters: 
//    DWORD                - [in] which moniker is being set 
//    IMoniker *           - [in] the moniker 
// 
// Output: 
//    HRESULT              - S_OK, E_FAIL 
// 
// Notes: 
//    - we don't support monikers. 
// 
STDMETHODIMP COleControl::SetMoniker 
( 
    DWORD     dwWhichMoniker, 
    IMoniker *pMoniker 
) 
{ 
    return E_NOTIMPL; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::GetMoniker    [IOleObject] 
//=--------------------------------------------------------------------------= 
// Returns a embedded object's moniker, which the caller can use to link to 
// the object 
// 
// Parameters: 
//    DWORD            - [in]  how it's assigned 
//    DWORD            - [in]  which moniker 
//    IMoniker **      - [out] duh. 
// 
// Output: 
//    HRESULT          - E_NOTIMPL 
// 
// Notes: 
//    - we don't support monikers 
// 
STDMETHODIMP COleControl::GetMoniker 
( 
    DWORD      dwAssign, 
    DWORD      dwWhichMoniker, 
    IMoniker **ppMonikerOut 
) 
{ 
    return E_NOTIMPL; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::InitFromData    [IOleObject] 
//=--------------------------------------------------------------------------= 
// Initializes a newly created object with data from a specified data object, 
// which can reside either in the same container or on the Clipboard 
// 
// Parameters: 
//    IDataObject*    - [in] data object with the data 
//    BOOL            - [in] how object is created 
//    DWORD           - reserved 
// 
// Output: 
//    HRESULT         - S_OK, S_FALSE, E_NOTIMPL, OLE_E_NOTRUNNING 
// 
// Notes: 
//    - we don't have data object support 
// 
STDMETHODIMP COleControl::InitFromData 
( 
    IDataObject *pDataObject, 
    BOOL         fCreation, 
    DWORD        dwReserved 
) 
{ 
    return E_NOTIMPL; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::GetClipboardData    [IOleObject] 
//=--------------------------------------------------------------------------= 
// Retrieves a data object containing the current contents of the control. 
// Using the pointer to this data object, it is possible to create a new control 
// with the same data as the original 
// 
// Parameters: 
//    DWORD          - reserved 
//    IDataObject ** - [out] data object for this control 
// 
// Output: 
//    HREUSLT        - S_OK, E_NOTIMPL, OLE_E_NOTRUNNING 
// 
// Notes: 
// 
STDMETHODIMP COleControl::GetClipboardData 
( 
    DWORD         dwReserved, 
    IDataObject **ppDataObject 
) 
{ 
    *ppDataObject = NULL;        // be a good neighbour 
    return E_NOTIMPL; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::DoVerb    [IOleObject] 
//=--------------------------------------------------------------------------= 
// Requests an object to perform an action in response to an end-user's 
// action. 
// 
// Parameters: 
//    LONG             - [in]  verb to be performed 
//    LPMSG            - [in]  event that invoked the verb 
//    IOleClientSite * - [in]  the controls active client site 
//    LONG             - [in]  reserved 
//    HWND             - [in]  handle of window containing the object. 
//    LPCRECT          - [in]  pointer to objects's display rectangle 
// 
// Output: 
//    HRESULT          - S_OK, OLE_E_NOTINPLACEACTIVE, OLE_E_CANT_BINDTOSOURCE, 
//                       DV_E_LINK, OLEOBJ_S_CANNOT_DOVERB_NOW, OLEOBJ_S_INVALIDHWND, 
//                       OLEOBJ_E_NOVERBS, OLEOBJ_S_INVALIDVERB, MK_E_CONNECT, 
//                       OLE_CLASSDIFF, E_NOTIMPL 
// 
// Notes: 
// 
STDMETHODIMP COleControl::DoVerb 
( 
    LONG            lVerb, 
    LPMSG           pMsg, 
    IOleClientSite *pActiveSite, 
    LONG            lIndex, 
    HWND            hwndParent, 
    LPCRECT         prcPosRect 
) 
{ 
    HRESULT hr; 
 
    switch (lVerb) { 
      case OLEIVERB_SHOW: 
      case OLEIVERB_INPLACEACTIVATE: 
      case OLEIVERB_UIACTIVATE: 
        hr = InPlaceActivate(lVerb); 
        OnVerb(lVerb); 
        return (hr); 
 
      case OLEIVERB_HIDE: 
        UIDeactivate(); 
        if (m_fInPlaceVisible) SetInPlaceVisible(FALSE); 
        OnVerb(lVerb); 
        return S_OK; 
 
      // we used to have OLEIVERB_PRIMARY InPlaceActivate Ourselves, but it 
      // turns out that the CDK and certain hosts expect this to show the 
      // properties instead.  Users can change what this verb does at will. 
      // 
      case OLEIVERB_PRIMARY: 
      case CTLIVERB_PROPERTIES: 
      case OLEIVERB_PROPERTIES: 
        { 
        // show the frame ourselves if the hose can't. 
        // 
        if (m_pControlSite) { 
            hr = m_pControlSite->ShowPropertyFrame(); 
            if (hr != E_NOTIMPL) 
                return hr; 
        } 
        IUnknown *pUnk = (IUnknown *)(IOleObject *)this; 
        MAKE_WIDEPTR_FROMANSI(pwsz, NAMEOFOBJECT(m_ObjectType)); 
 
        ModalDialog(TRUE); 
        hr = OleCreatePropertyFrame(GetActiveWindow(), 
                            GetSystemMetrics(SM_CXSCREEN) / 2, 
                            GetSystemMetrics(SM_CYSCREEN) / 2, 
                            pwsz, 
                            1, 
                            &pUnk, 
                            CPROPPAGESOFCONTROL(m_ObjectType), 
                            (LPCLSID)*(PPROPPAGESOFCONTROL(m_ObjectType)), 
                            g_lcidLocale, 
                            NULL, NULL); 
        ModalDialog(FALSE); 
        return hr; 
        } 
 
      default: 
        // if it's a derived-control defined verb, pass it on to them 
        // 
        if (lVerb > 0) { 
            hr = DoCustomVerb(lVerb); 
 
            if (hr == OLEOBJ_S_INVALIDVERB) { 
                // unrecognised verb -- just do the primary verb and 
                // activate the sucker. 
                // 
                hr = InPlaceActivate(OLEIVERB_PRIMARY); 
                return (FAILED(hr)) ? hr : OLEOBJ_S_INVALIDVERB; 
            } else 
                return hr; 
        } else { 
            FAIL("Unrecognized Negative verb in DoVerb().  bad."); 
            return E_NOTIMPL; 
        } 
        break; 
    } 
 
    // dead code 
    FAIL("this should be dead code!"); 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::EnumVerbs    [IOleObject] 
//=--------------------------------------------------------------------------= 
// create an enumerator object for the verbs this object supports. 
// 
// Parameters: 
//    IEnumOleVERB **    - [out] new enumerator. 
// 
// Output: 
//    HRESULT            - S_OK, E_OUTOFMEMORY 
// 
// Notes: 
// 
STDMETHODIMP COleControl::EnumVerbs 
( 
    IEnumOLEVERB **ppEnumVerbs 
) 
{ 
    int cVerbs; 
    OLEVERB *rgVerbs, *pVerb; 
 
    DWORD dw = OLEMISCFLAGSOFCONTROL(m_ObjectType); 
    BOOL fCanInPlace = !(dw & OLEMISC_INVISIBLEATRUNTIME) || (dw & OLEMISC_ACTIVATEWHENVISIBLE); 
    BOOL fCanUIActivate = !(dw & OLEMISC_NOUIACTIVATE); 
    BOOL fHasProperties = (CPROPPAGESOFCONTROL(m_ObjectType) != 0); 
 
    int cVerbExtra = CCUSTOMVERBSOFCONTROL(m_ObjectType); 
 
    // count up all the verbs 
    // 
    cVerbs = (fCanInPlace ? CINPLACEVERBS : 0) + (fCanUIActivate ? 1 : 0) 
             + (fHasProperties ? 1 : 0) + cVerbExtra; 
 
    // if there aren't any, this suddenly gets really easy ! 
    // 
    if (cVerbs == 0) 
        return OLEOBJ_E_NOVERBS; 
 
    // HeapAlloc some storage for these dudes so that we can pass them on to 
    // the standard enumerator! 
    // 
    if (! (rgVerbs = (OLEVERB *)HeapAlloc(g_hHeap, 0, cVerbs * sizeof(OLEVERB)))) 
        return E_OUTOFMEMORY; 
   
    // start copying over verbs.  first, the in-place guys 
    // 
    pVerb = rgVerbs; 
    if (fCanInPlace) { 
        memcpy(pVerb, rgInPlaceVerbs, CINPLACEVERBS * sizeof(OLEVERB)); 
        pVerb += CINPLACEVERBS; 
      } 
 
    if (fCanUIActivate) 
        memcpy(pVerb++, &ovUIActivate, sizeof(OLEVERB)); 
 
    // if their control has properties, copy that over now. 
    // 
    if (fHasProperties) { 
        memcpy(pVerb, &ovProperties, sizeof(OLEVERB)); 
        pVerb++; 
    } 
 
    // finally, any custom verbs! 
    // 
    if (cVerbExtra) { 
        memcpy(pVerb, CUSTOMVERBSOFCONTROL(m_ObjectType), sizeof(OLEVERB) * cVerbExtra); 
    } 
 
    *ppEnumVerbs = (IEnumOLEVERB *) (IEnumGeneric *) new CStandardEnum(IID_IEnumOLEVERB, 
                                     cVerbs, sizeof(OLEVERB), rgVerbs, CopyOleVerb); 
    if (!*ppEnumVerbs) 
        return E_OUTOFMEMORY; 
 
    // this forces us to go and look for the Localized DLLs.  This is necessary here 
    // because the CopyOleVerb will get information from localized resources, but 
    // will only use the global GetResourceHandle, which only uses the global value 
    // for the LCID.  This turns out to not be a big performance hit, since this 
    // function is typically only called in design mode, and we stash this value. 
    // 
    GetResourceHandle(); 
    return S_OK; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::Update    [IOleObject] 
//=--------------------------------------------------------------------------= 
// Updates an object handler's or link object's data or view caches. 
// 
// Output: 
//    HRESULT            - S_OK 
// 
// Notes: 
// 
STDMETHODIMP COleControl::Update 
( 
    void 
) 
{ 
    // nothing to do!!! 
    // 
    return S_OK; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::IsUpToDate    [IOleObject] 
//=--------------------------------------------------------------------------= 
// Checks recursively whether or not an object is up to date. 
// 
// Output: 
//    HRESULT        - S_OK, S_FALSE, OLE_E_UNVAILABLE 
// 
// Notes: 
// 
STDMETHODIMP COleControl::IsUpToDate 
( 
    void 
) 
{ 
    // we're always up to date 
    // 
    return S_OK; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::GetUserClassID    [IOleObject] 
//=--------------------------------------------------------------------------= 
// Returns the controls class identifier, the CLSID corresponding to the 
// string identifying the object to an end user. 
// 
// Parameters: 
//    CLSID *      - [in] where to put the CLSID 
// 
// Output: 
//    HRESULT      - S_OK, E_FAIL 
// 
// Notes: 
// 
STDMETHODIMP COleControl::GetUserClassID 
( 
    CLSID *pclsid 
) 
{ 
    // this is the same as IPersist::GetClassID 
    // 
    return GetClassID(pclsid); 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::GetUserType    [IOleObject] 
//=--------------------------------------------------------------------------= 
// Retrieves the user-type name of the control for display in user-interface 
// elements such as menus, list boxes, and dialog boxes. 
// 
// Parameters: 
//    DWORD        - [in]  specifies the form of the type name. 
//    LPOLESTR *   - [out] where to put user type 
// 
// Output: 
//    HRESULT      - S_OK, OLE_S_USEREG, E_OUTOFMEMORY 
// 
// Notes: 
// 
STDMETHODIMP COleControl::GetUserType 
( 
    DWORD     dwFormOfType, 
    LPOLESTR *ppszUserType 
) 
{ 
    *ppszUserType = OLESTRFROMANSI(NAMEOFOBJECT(m_ObjectType)); 
    return (*ppszUserType) ? S_OK : E_OUTOFMEMORY; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::SetExtent    [IOleObject] 
//=--------------------------------------------------------------------------= 
// Informs the control of how much display space its container has assigned it. 
// 
// Parameters: 
//    DWORD            - [in] which form or 'aspect'  is to be displayed. 
//    SIZEL *          - [in] size limit for the control. 
// 
// Output: 
//    HRESULT          - S_OK, E_FAIL, OLE_E_NOTRUNNING 
// 
// Notes: 
// 
STDMETHODIMP COleControl::SetExtent 
( 
    DWORD  dwDrawAspect, 
    SIZEL *psizel 
) 
{ 
    SIZEL sl; 
    RECT  rect; 
    BOOL  f; 
 
    if (dwDrawAspect & DVASPECT_CONTENT) { 
 
        // change the units to pixels, and resize the control. 
        // 
        HiMetricToPixel(psizel, &sl); 
 
        // first call the user version.  if they return FALSE, they want 
        // to keep their current size 
        // 
        f = OnSetExtent(&sl); 
        if (f) 
            HiMetricToPixel(psizel, &m_Size); 
 
        // set things up with our HWND if we've got one. 
        // 
        if (!m_pInPlaceSiteWndless) { 
            if (m_fInPlaceActive) { 
     
                // theoretically, one should not need to call OnPosRectChange 
                // here, but there appear to be a few host related issues that 
                // will make us keep it here.  we won't, however, both with 
                // windowless ole controls, since they are all new hosts who 
                // should know better 
                // 
                GetWindowRect(m_hwnd, &rect); 
                MapWindowPoints(NULL, m_hwndParent, (LPPOINT)&rect, 2); 
                rect.right = rect.left + m_Size.cx; 
                rect.bottom = rect.top + m_Size.cy; 
                m_pInPlaceSite->OnPosRectChange(&rect); 
     
                if (m_hwnd) { 
                    // just go and resize 
                    // 
                    if (m_hwndReflect) 
                        SetWindowPos(m_hwndReflect, 0, 0, 0, m_Size.cx, m_Size.cy, 
                                     SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); 
                    SetWindowPos(m_hwnd, 0, 0, 0, m_Size.cx, m_Size.cy, 
                                 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); 
                } 
            } else if (m_hwnd) { 
                SetWindowPos(m_hwnd, NULL, 0, 0, m_Size.cx, m_Size.cy, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); 
            } else { 
                ViewChanged(); 
            } 
        } else 
            if (m_pInPlaceSite) m_pInPlaceSite->OnPosRectChange(&rect); 
 
        // return code depending on whether or not user accepted given 
        // size 
        // 
        return (f) ? S_OK : E_FAIL; 
 
    } else { 
        // we don't support any other aspects. 
        // 
        return DV_E_DVASPECT; 
    } 
 
    // dead code 
    FAIL("This should be dead code"); 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::GetExtent    [IOleObject] 
//=--------------------------------------------------------------------------= 
// Retrieves the control's current display size. 
// 
// Parameters: 
//    DWORD            - [in] aspect 
//    SIZEL *          - [in] where to put results 
// 
// Output: 
//    S_OK, E_INVALIDARG 
// 
// Notes: 
// 
STDMETHODIMP COleControl::GetExtent 
( 
    DWORD  dwDrawAspect, 
    SIZEL *pSizeLOut 
) 
{ 
 
    if (dwDrawAspect & DVASPECT_CONTENT) { 
        PixelToHiMetric((const SIZEL *)&m_Size, pSizeLOut); 
        return S_OK; 
    } else { 
        return DV_E_DVASPECT; 
    } 
 
    // dead code 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::Advise    [IOleObject] 
//=--------------------------------------------------------------------------= 
// establishes and advisory connection between the control and the container, 
// in which the control will notify the container of certain events. 
// 
// Parameters: 
//    IAdviseSink *     - [in]  advise sink of calling object 
//    DWORD             - [out] cookie 
// 
// Output: 
//    HRESULT           - S_OK, E_OUTOFMEMORY 
// 
// Notes: 
// 
STDMETHODIMP COleControl::Advise 
( 
    IAdviseSink *pAdviseSink, 
    DWORD       *pdwConnection 
) 
{ 
    HRESULT hr; 
 
    // if we haven't yet created a standard advise holder object, do so 
    // now 
    // 
    if (!m_pOleAdviseHolder) { 
        hr = CreateOleAdviseHolder(&m_pOleAdviseHolder); 
        RETURN_ON_FAILURE(hr); 
    } 
 
    // just get it to do the work for us! 
    // 
    return m_pOleAdviseHolder->Advise(pAdviseSink, pdwConnection); 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::Unadvise    [IOleObject] 
//=--------------------------------------------------------------------------= 
// Deletes a previously established advisory connection. 
// 
// Parameters: 
//    DWORD         - [in] connection cookie 
// 
// Output: 
//    HRESULT       - S_OK, E_FAIL, OLE_E_NOCONNECTION 
// 
// Notes: 
// 
STDMETHODIMP COleControl::Unadvise 
( 
    DWORD dwConnection 
) 
{ 
    if (!m_pOleAdviseHolder) { 
        FAIL("Somebody called Unadvise on IOleObject without calling Advise!"); 
        CONNECT_E_NOCONNECTION; 
    } 
 
    return m_pOleAdviseHolder->Unadvise(dwConnection); 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::EnumAdvise    [IOleObject] 
//=--------------------------------------------------------------------------= 
// Enumerates the advisory connections registered for an object, so a container 
// can know what to release prior to closing down. 
// 
// Parameters: 
//    IEnumSTATDATA **    - [out] where to put enumerator 
// 
// Output: 
//    HRESULT             - S_OK, E_FAIL, E_NOTIMPL 
// 
// Notes: 
// 
STDMETHODIMP COleControl::EnumAdvise 
( 
    IEnumSTATDATA **ppEnumOut 
) 
{ 
    if (!m_pOleAdviseHolder) { 
        FAIL("Somebody Called EnumAdvise without setting up any connections"); 
        *ppEnumOut = NULL; 
        return E_FAIL; 
    } 
 
    return m_pOleAdviseHolder->EnumAdvise(ppEnumOut); 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::GetMiscStatus    [IOleObject] 
//=--------------------------------------------------------------------------= 
// Returns a value indicating the status of an object at creation and loading. 
// 
// Parameters: 
//    DWORD         - [in]  aspect desired 
//    DWORD *       - [out] where to put the bits. 
// 
// Output: 
//    HRESULT       - S_OK, OLE_S_USEREG, CO_E_CLASSNOTREG, CO_E_READREGDB 
// 
// Notes: 
// 
STDMETHODIMP COleControl::GetMiscStatus 
( 
    DWORD  dwAspect, 
    DWORD *pdwStatus 
) 
{ 
    CHECK_POINTER(pdwStatus); 
 
    if (dwAspect == DVASPECT_CONTENT) { 
        *pdwStatus = OLEMISCFLAGSOFCONTROL(m_ObjectType); 
        return S_OK; 
    } else { 
        return DV_E_DVASPECT; 
    } 
 
    // dead code 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::SetColorScheme    [IOleObject] 
//=--------------------------------------------------------------------------= 
// Specifies the color palette that the object application should use when it 
// edits the specified object. 
// 
// Parameters: 
//    LOGPALETTE *     - [in] new palette 
// 
// Output: 
//    HRESULT          - S_OK, E_NOTIMPL, OLE_E_PALETTE, OLE_E_NOTRUNNING 
// 
// Notes: 
//    - we don't care. 
// 
STDMETHODIMP COleControl::SetColorScheme 
( 
    LOGPALETTE *pLogpal 
) 
{ 
    // OVERRIDE: control writers can use this if they want to 
    // 
    return S_OK; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::GetWindow    [IOleWindow/IOleInPlaceObject] 
//=--------------------------------------------------------------------------= 
// Returns the window handle to one of the windows participating in in-place 
// activation (frame, document, parent, or in-place object window). 
// 
// Parameters: 
//    HWND *        - [out] where to return window handle. 
// 
// Output: 
//    HRESULT       - S_OK, E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, E_FAIL 
// 
// Notes: 
//    - this routine has slightly different semantics for windowless controls 
// 
STDMETHODIMP COleControl::GetWindow 
( 
    HWND *phwnd 
) 
{ 
    // if we're windowles, then we want to return E_FAIL for this so hosts 
    // know we're windowless 
    // 
    if (m_pInPlaceSiteWndless) 
        return E_FAIL; 
 
    // otherwise, just return our outer window. 
    // 
    *phwnd = GetOuterWindow(); 
 
    return (*phwnd) ? S_OK : E_UNEXPECTED; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::ContextSensitiveHelp    [IOleWindow/IOleInPlaceObject] 
//=--------------------------------------------------------------------------= 
// Determines whether context-sensitive help mode should be entered during an 
// in-place activation session. 
// 
// Parameters: 
//    BOOL            - [in] whether or not to enter help mode. 
// 
// Output: 
//    HRESULT         - S_OK, E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED 
// 
// Notes: 
// 
STDMETHODIMP COleControl::ContextSensitiveHelp 
( 
    BOOL fEnterMode 
) 
{ 
    return E_NOTIMPL; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::InPlaceActivate 
//=--------------------------------------------------------------------------= 
// activates the control, and depending on the verb, optionally ui activates 
// it as well. 
// 
// Parameters: 
//    LONG         - [in] the verb that caused us to activate 
// 
// Output: 
//    HRESULT 
// 
// Notes: 
//    - this is spaghetti code at it's worst.  effectively, we have to 
//      be able to handle three types of site pointers -- IOleInPlaceSIte, 
//      IOleInPlaceSiteEx, and IOleInPlaceSiteWindowless.  not terribly 
//      pretty. 
// 
HRESULT COleControl::InPlaceActivate 
( 
    LONG lVerb 
) 
{ 
    BOOL f; 
    SIZEL sizel; 
    IOleInPlaceSiteEx *pIPSEx = NULL; 
    HRESULT hr; 
    BOOL    fNoRedraw = FALSE; 
 
    // if we don't have a client site, then there's not much to do. 
    // 
    if (!m_pClientSite) 
        return S_OK; 
 
    // get an InPlace site pointer. 
    // 
    if (!GetInPlaceSite()) { 
 
        // if they want windowless support, then we want IOleInPlaceSiteWindowless 
        // 
        if (FCONTROLISWINDOWLESS(m_ObjectType)) 
            m_pClientSite->QueryInterface(IID_IOleInPlaceSiteWindowless, (void **)&m_pInPlaceSiteWndless); 
 
        // if we're not able to do windowless siting, then we'll just get an 
        // IOleInPlaceSite pointer. 
        // 
        if (!m_pInPlaceSiteWndless) { 
            hr = m_pClientSite->QueryInterface(IID_IOleInPlaceSite, (void **)&m_pInPlaceSite); 
            RETURN_ON_FAILURE(hr); 
        } 
    } 
 
    // now, we want an IOleInPlaceSiteEx pointer for windowless and flicker free 
    // activation.  if we're windowless, we've already got it, else we need to 
    // try and get it 
    // 
    if (m_pInPlaceSiteWndless) { 
        pIPSEx = (IOleInPlaceSiteEx *)m_pInPlaceSiteWndless; 
        pIPSEx->AddRef(); 
    } else 
        m_pClientSite->QueryInterface(IID_IOleInPlaceSiteEx, (void **)&pIPSEx); 
 
    // if we're not already active, go and do it. 
    // 
    if (!m_fInPlaceActive) { 
        OLEINPLACEFRAMEINFO InPlaceFrameInfo; 
        RECT rcPos, rcClip; 
 
        // if we have a windowless site, see if we can go in-place windowless 
        // active 
        // 
        hr = S_FALSE; 
        if (m_pInPlaceSiteWndless) { 
            hr = m_pInPlaceSiteWndless->CanWindowlessActivate(); 
            CLEANUP_ON_FAILURE(hr); 
 
            // if they refused windowless, we'll try windowed 
            // 
            if (S_OK != hr) { 
                RELEASE_OBJECT(m_pInPlaceSiteWndless); 
                hr = m_pClientSite->QueryInterface(IID_IOleInPlaceSite, (void **)&m_pInPlaceSite); 
                CLEANUP_ON_FAILURE(hr); 
            } 
        } 
 
        // just try regular windowed in-place activation 
        // 
        if (hr != S_OK) { 
            hr = m_pInPlaceSite->CanInPlaceActivate(); 
            if (hr != S_OK) { 
                hr = (FAILED(hr)) ? E_FAIL : hr; 
                goto CleanUp; 
            } 
        } 
 
        // if we are here, then we have permission to go in-place active. 
        // now, announce our intentions to actually go ahead and do this. 
        // 
        hr = (pIPSEx) ? pIPSEx->OnInPlaceActivateEx(&fNoRedraw, (m_pInPlaceSiteWndless) ? ACTIVATE_WINDOWLESS : 0) 
                       : m_pInPlaceSite->OnInPlaceActivate(); 
        CLEANUP_ON_FAILURE(hr); 
 
        // if we're here, we're ready to go in-place active.  we just need 
        // to set up some flags, and then create the window [if we have 
        // one] 
        // 
        m_fInPlaceActive = TRUE; 
 
        // we need to get some information about our location in the parent 
        // window, as well as some information about the parent 
        // 
        InPlaceFrameInfo.cb = sizeof(OLEINPLACEFRAMEINFO); 
        hr = GetInPlaceSite()->GetWindow(&m_hwndParent); 
        if (SUCCEEDED(hr)) 
            hr = GetInPlaceSite()->GetWindowContext(&m_pInPlaceFrame, &m_pInPlaceUIWindow, &rcPos, &rcClip, &InPlaceFrameInfo); 
        CLEANUP_ON_FAILURE(hr); 
 
        // make sure we'll display ourselves in the correct location with the correct size 
        // 
        sizel.cx = rcPos.right - rcPos.left; 
        sizel.cy = rcPos.bottom - rcPos.top; 
        f = OnSetExtent(&sizel); 
        if (f) m_Size = sizel; 
        SetObjectRects(&rcPos, &rcClip); 
 
        // finally, create our window if we have to! 
        // 
        if (!m_pInPlaceSiteWndless) { 
     
            SetInPlaceParent(m_hwndParent); 
 
            // create the window, and display it.  die horribly if we couldnt' 
            // 
            if (!CreateInPlaceWindow(rcPos.left, rcPos.top, fNoRedraw)) { 
                hr = E_FAIL; 
                goto CleanUp; 
            } 
        } 
    } 
 
    // don't need this any more 
    // 
    RELEASE_OBJECT(pIPSEx); 
 
    // if we're not inplace visible yet, do so now. 
    // 
    if (!m_fInPlaceVisible) 
        SetInPlaceVisible(TRUE); 
 
    // if we weren't asked to UIActivate, then we're done. 
    // 
    if (lVerb != OLEIVERB_PRIMARY && lVerb != OLEIVERB_UIACTIVATE) 
        return S_OK; 
 
    // if we're not already UI active, do sow now. 
    // 
    if (!m_fUIActive) { 
        m_fUIActive = TRUE; 
 
        // inform the container of our intent 
        // 
        GetInPlaceSite()->OnUIActivate(); 
 
        // take the focus  [which is what UI Activation is all about !] 
        // 
        SetFocus(TRUE); 
 
        // set ourselves up in the host. 
        // 
        m_pInPlaceFrame->SetActiveObject((IOleInPlaceActiveObject *)this, NULL); 
        if (m_pInPlaceUIWindow) 
            m_pInPlaceUIWindow->SetActiveObject((IOleInPlaceActiveObject *)this, NULL); 
 
        // we have to explicitly say we don't wany any border space. 
        // 
        m_pInPlaceFrame->SetBorderSpace(NULL); 
        if (m_pInPlaceUIWindow) 
            m_pInPlaceUIWindow->SetBorderSpace(NULL); 
    } 
 
    // be-de-be-de-be-de that's all folks! 
    // 
    return S_OK; 
 
  CleanUp: 
    // something catastrophic happened [or, at least something bad]. 
    // die a horrible fiery mangled painful death. 
    // 
    QUICK_RELEASE(pIPSEx); 
    m_fInPlaceActive = FALSE; 
    return hr; 
 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::InPlaceDeactivate    [IOleInPlaceObject] 
//=--------------------------------------------------------------------------= 
// Deactivates an active in-place object and discards the object's undo state. 
// 
// Output: 
//    HRESULT        - S_OK, E_UNEXPECTED 
// 
// Notes: 
// 
STDMETHODIMP COleControl::InPlaceDeactivate 
( 
    void 
) 
{ 
    // if we're not in-place active yet, then this is easy. 
    // 
    if (!m_fInPlaceActive) 
        return S_OK; 
 
    // transition from UIActive back to active 
    // 
    if (m_fUIActive) 
        UIDeactivate(); 
 
    m_fInPlaceActive = FALSE; 
    m_fInPlaceVisible = FALSE; 
 
    // if we have a window, tell it to go away. 
    // 
    if (m_hwnd) { 
        ASSERT(!m_pInPlaceSiteWndless, "internal state really messed up"); 
 
        // so our window proc doesn't crash. 
        // 
        BeforeDestroyWindow(); 
        SetWindowLong(m_hwnd, GWL_USERDATA, 0xFFFFFFFF); 
        DestroyWindow(m_hwnd); 
        m_hwnd = NULL; 
 
        if (m_hwndReflect) { 
            SetWindowLong(m_hwndReflect, GWL_USERDATA, 0); 
            DestroyWindow(m_hwndReflect); 
            m_hwndReflect = NULL; 
        } 
    } 
 
    RELEASE_OBJECT(m_pInPlaceFrame); 
    RELEASE_OBJECT(m_pInPlaceUIWindow); 
    GetInPlaceSite()->OnInPlaceDeactivate(); 
    return S_OK; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::UIDeactivate    [IOleInPlaceObject] 
//=--------------------------------------------------------------------------= 
// transitions us from UI Active to merely being active [visible]  for 
// a control, this doesn't mean all that much. 
// 
// Output: 
//    HRESULT         - S_OK, E_UNEXPECTED 
// 
// Notes: 
// 
STDMETHODIMP COleControl::UIDeactivate 
( 
    void 
) 
{ 
    // if we're not UIActive, not much to do. 
    // 
    if (!m_fUIActive) 
        return S_OK; 
 
    m_fUIActive = FALSE; 
 
    // notify frame windows, if appropriate, that we're no longer ui-active. 
    // 
    if (m_pInPlaceUIWindow) m_pInPlaceUIWindow->SetActiveObject(NULL, NULL); 
    m_pInPlaceFrame->SetActiveObject(NULL, NULL); 
 
    // we don't need to explicitly release the focus here since somebody 
    // else grabbing the focus is what is likely to cause us to get lose it 
    // 
    GetInPlaceSite()->OnUIDeactivate(FALSE); 
 
    return S_OK; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::SetObjectRects    [IOleInPlaceObject] 
//=--------------------------------------------------------------------------= 
// Indicates how much of the control is visible. 
// 
// Parameters: 
//    LPCRECT        - [in] position of the control. 
//    LPCRECT        - [in] clipping rectangle for the control. 
// 
// Output: 
//    HRESULT        - S_OK, E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED 
// 
// Notes: 
// 
STDMETHODIMP COleControl::SetObjectRects 
( 
    LPCRECT prcPos, 
    LPCRECT prcClip 
) 
{ 
    BOOL fRemoveWindowRgn; 
 
    // move our window to the new location and handle clipping. not applicable 
    // for windowless controls, since the container will be responsible for all 
    // clipping. 
    // 
    if (m_hwnd) { 
        fRemoveWindowRgn = m_fUsingWindowRgn; 
        if (prcClip) { 
            // the container wants us to clip, so figure out if we really 
            // need to 
            // 
            RECT rcIXect; 
            if ( IntersectRect(&rcIXect, prcPos, prcClip) ) { 
                if (!EqualRect(&rcIXect, prcPos)) { 
                    OffsetRect(&rcIXect, -(prcPos->left), -(prcPos->top)); 
 
                    HRGN tempRgn = CreateRectRgnIndirect(&rcIXect); 
                    SetWindowRgn(GetOuterWindow(), tempRgn, TRUE); 
 
                    if (m_hRgn != NULL) 
                       DeleteObject(m_hRgn); 
                    m_hRgn = tempRgn; 
 
                    m_fUsingWindowRgn = TRUE; 
                    fRemoveWindowRgn  = FALSE; 
                } 
            } 
        } 
 
        if (fRemoveWindowRgn) { 
            SetWindowRgn(GetOuterWindow(), NULL, TRUE); 
            if (m_hRgn != NULL) 
            { 
               DeleteObject(m_hRgn); 
               m_hRgn = NULL; 
            } 
            m_fUsingWindowRgn = FALSE; 
        } 
 
        // set our control's location, but don't change it's size at all 
        // [people for whom zooming is important should set that up here] 
        // 
        DWORD dwFlag; 
        OnSetObjectRectsChangingWindowPos(&dwFlag); 
 
        int cx, cy; 
        cx = prcPos->right - prcPos->left; 
        cy = prcPos->bottom - prcPos->top; 
        SetWindowPos(GetOuterWindow(), NULL, prcPos->left, prcPos->top, cx, cy, dwFlag | SWP_NOZORDER | SWP_NOACTIVATE); 
    } 
 
    // save out our current location.  windowless controls want this more 
    // that windowed ones do, but everybody can have it just in case 
    // 
    m_rcLocation = *prcPos; 
 
    return S_OK; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::ReactivateAndUndo    [IOleInPlaceObject] 
//=--------------------------------------------------------------------------= 
// Reactivates a previously deactivated object, undoing the last state of the object. 
// 
// Output: 
//    HRESULT        - S_OK, E_NOTUNDOABLE 
// 
// Notes: 
// 
STDMETHODIMP COleControl::ReactivateAndUndo 
( 
    void 
) 
{ 
    return E_NOTIMPL; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::OnWindowMessage    [IOleInPlaceObjectWindowless] 
//=--------------------------------------------------------------------------= 
// this method lets the container dispatch a message to a windowless OLE 
// object. 
// 
// Parameters: 
//    UINT                - [in]  the message 
//    WPARAM              - [in]  the messages wparam 
//    LPARAM              - [in]  duh. 
//    LRESULT *           - [out] the output value 
// 
// Output: 
//    HRESULT             - S_OK 
// 
// Notes: 
//    - people should call m_pInPlaceSiteWndless->OnDefWindowMessage [control 
//      writers should just call OcxDefWindowProc(msg, wparam, lparam)]; 
// 
STDMETHODIMP COleControl::OnWindowMessage 
( 
    UINT     msg, 
    WPARAM   wParam, 
    LPARAM   lParam, 
    LRESULT *plResult 
) 
{ 
    // little bit of pre-processing -- we need to handle some cases here 
    // before passing the messages on 
    // 
    switch (msg) { 
        // make sure our UI Activation correctly matches the focus 
        // 
        case WM_KILLFOCUS: 
        case WM_SETFOCUS: 
            // give the control site focus notification 
            // 
            if (m_fInPlaceActive && m_pControlSite) 
                m_pControlSite->OnFocus(msg == WM_SETFOCUS); 
            break; 
    } 
 
    // just pass it to the control's window proc. 
    // 
    *plResult = WindowProc(msg, wParam, lParam); 
    return S_OK; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::GetDropTarget    [IOleInPlaceObjectWindowless] 
//=--------------------------------------------------------------------------= 
// this method returns a pointer to the objects IDropTarget interface.  since 
// they do not have a window, windowless objects cannot register an IDropTarget 
// interface. 
// 
// Parameters: 
//    IDropTarget **        - [out] 
// 
// Output: 
//    HRESULT               - S_OK, E_NOTIMPL 
// 
// Notes: 
// 
STDMETHODIMP COleControl::GetDropTarget 
( 
    IDropTarget **ppDropTarget 
) 
{ 
    // OVERRIDE: if you want to do drag and drop and you're windowless, 
    // override me. 
    // 
    return E_NOTIMPL; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::TranslateAccelerator    [IOleInPlaceActiveObject] 
//=--------------------------------------------------------------------------= 
// Processes menu accelerator-key messages from the container's message queue. 
// 
// Parameters: 
//    LPMSG            - [in] the message that has the special key in it. 
// 
// Output: 
//    HRESULT          - S_OK, S_FALSE, E_UNEXPECTED 
// 
// Notes: 
// 
STDMETHODIMP COleControl::TranslateAccelerator 
( 
    LPMSG    pmsg 
) 
{ 
    // see if we want it or not. 
    // 
    if (OnSpecialKey(pmsg)) 
        return S_OK; 
 
    // if not, then we want to forward it back to the site for further processing 
    // 
    if (m_pControlSite) 
        return m_pControlSite->TranslateAccelerator(pmsg, _SpecialKeyState()); 
 
    // we didn't want it. 
    // 
    return S_FALSE; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::OnFrameWindowActivate    [IOleInPlaceActiveObject] 
//=--------------------------------------------------------------------------= 
// Notifies the control when the container's top-level frame window is 
// activated or deactivated. 
// 
// Parameters: 
//    BOOL        - [in] state of containers top level window. 
// 
// Output: 
//    HRESULT     - S_OK 
// 
// Notes: 
// 
STDMETHODIMP COleControl::OnFrameWindowActivate 
( 
    BOOL fActivate 
) 
{ 
    // we're supposed to go UI active in this case 
    // 
    return InPlaceActivate(OLEIVERB_UIACTIVATE); 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::OnDocWindowActivate    [IOleInPlaceActiveObject] 
//=--------------------------------------------------------------------------= 
// Notifies the active control when the container's document window is 
// activated or deactivated. 
// 
// Parameters: 
//    BOOL            - state of mdi child window. 
// 
// Output: 
//    HRESULT         - S_OK 
// 
// Notes: 
// 
STDMETHODIMP COleControl::OnDocWindowActivate 
( 
    BOOL fActivate 
) 
{ 
    // we're supposed to go UI active in this case 
    // 
    return InPlaceActivate(OLEIVERB_UIACTIVATE); 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::ResizeBorder    [IOleInPlaceActiveObject] 
//=--------------------------------------------------------------------------= 
// Alerts the control that it needs to resize its border space. 
// 
// Parameters: 
//    LPCRECT               - [in] new outer rectangle for border space 
//    IOleInPlaceUIWindow * - [in] the document or frame who's border has changed 
//    BOOL                  - [in] true if it was the fram window taht called. 
// 
// Output: 
//    HRESULT               - S_OK 
// 
// Notes: 
// 
STDMETHODIMP COleControl::ResizeBorder 
( 
    LPCRECT              prcBorder, 
    IOleInPlaceUIWindow *pInPlaceUIWindow, 
    BOOL                 fFrame 
) 
{ 
    // this is largely uninteresting to us, since we have no border. 
    // 
    return S_OK; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::EnableModeless    [IOleInPlaceActiveObject] 
//=--------------------------------------------------------------------------= 
// Enables or disables modeless dialog boxes when the container creates or 
// destroys a modal dialog box. 
// 
// Parameters: 
//    BOOL            - [in] enable or disable modeless dialogs. 
// 
// Output: 
//    HRESULT         - S_OK 
// 
// Notes: 
// 
STDMETHODIMP COleControl::EnableModeless 
( 
    BOOL fEnable 
) 
{ 
    // phenomenally uninteresting 
    // 
    return S_OK; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::GetClassInfo    [IProvideClassInfo] 
//=--------------------------------------------------------------------------= 
// returns the TypeInfo for the control's coclass. 
// 
// Parameters: 
//    ITypeInfo **        - [out] 
// 
// Output: 
//    HRESULT 
// 
// Notes: 
// 
STDMETHODIMP COleControl::GetClassInfo 
( 
    ITypeInfo **ppTypeInfo 
) 
{ 
    ITypeLib *pTypeLib; 
    HRESULT hr; 
 
    CHECK_POINTER(ppTypeInfo); 
    *ppTypeInfo = NULL; 
 
    // go and get our type library. 
    // CONSIDER: - go to the same sorta scheme that we use for TypeInfo caching. 
    // CONSIDER: - consider trying to register our typelib if this fails. 
    // 
    hr = LoadRegTypeLib(*g_pLibid, (USHORT)VERSIONOFOBJECT(m_ObjectType), 0, 
                        LANGIDFROMLCID(g_lcidLocale), &pTypeLib); 
    RETURN_ON_FAILURE(hr); 
 
    // got the typelib.  get typeinfo for our coclass. 
    // 
    hr = pTypeLib->GetTypeInfoOfGuid((REFIID)CLSIDOFOBJECT(m_ObjectType), ppTypeInfo); 
    pTypeLib->Release(); 
    RETURN_ON_FAILURE(hr); 
 
    return S_OK; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::ViewChange    [callable] 
//=--------------------------------------------------------------------------= 
// called whenever the view of the object has changed. 
// 
// Notes: 
// 
void COleControl::ViewChanged 
( 
    void 
) 
{ 
    // send the view change notification to anybody listening. 
    // 
    if (m_pViewAdviseSink) { 
        m_pViewAdviseSink->OnViewChange(DVASPECT_CONTENT, -1); 
 
        // if they only asked to be advised once, kill the connection 
        // 
        if (m_fViewAdviseOnlyOnce) 
            SetAdvise(DVASPECT_CONTENT, 0, NULL); 
    } 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::SetInPlaceVisible    [helper] 
//=--------------------------------------------------------------------------= 
// controls the visibility of the control window. 
// 
// Parameters: 
//    BOOL        - TRUE shows FALSE hides. 
// 
// Notes: 
// 
void COleControl::SetInPlaceVisible 
( 
    BOOL fShow 
) 
{ 
    BOOL fVisible; 
 
    m_fInPlaceVisible = fShow; 
 
    // don't do anything if we don't have a window.  otherwise, set it 
    // 
    if (m_hwnd) { 
        fVisible = ((GetWindowLong(GetOuterWindow(), GWL_STYLE) & WS_VISIBLE) != 0); 
 
        if (fVisible && !fShow) 
            ShowWindow(GetOuterWindow(), SW_HIDE); 
        else if (!fVisible && fShow) 
            ShowWindow(GetOuterWindow(), SW_SHOWNA); 
    } 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::AmbientPropertyChanged    [overridable] 
//=--------------------------------------------------------------------------= 
// a method that derived controls can override to do whatever they want. 
// we don't particularily care about this event. 
// 
// Parameters: 
//    DISPID            - [in] dispid of prop that changed. 
// 
// Notes: 
// 
void COleControl::AmbientPropertyChanged 
( 
    DISPID dispid 
) 
{ 
    // do nothing 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::DoCustomVerb    [overridable] 
//=--------------------------------------------------------------------------= 
// we were asked to execute a verb we don't know about right away.  see if 
// it's a verb that the dervied-control defined. 
// 
// Parameters: 
//    LONG            - [in] the verb. 
// 
// Output: 
//    HRESULT         - S_OK, OLEOBJ_S_INVALIDVERB 
// 
// Notes: 
// 
HRESULT COleControl::DoCustomVerb 
( 
    LONG    lVerb 
) 
{ 
    return OLEOBJ_S_INVALIDVERB; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::OnSetExtent    [overridable] 
//=--------------------------------------------------------------------------= 
// let the user do something in the resize, if they care. 
// 
// Parameters: 
//    SIZEL *        - [in] new values. 
// 
// Output: 
//    BOOL           - FALSE means keep current size 
// 
// Notes: 
// 
BOOL COleControl::OnSetExtent 
( 
    const SIZEL *pSizeL 
) 
{ 
    return TRUE; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::OnSpecialKey    [overridable] 
//=--------------------------------------------------------------------------= 
// allows controls to handle special keys such as arrows, CTRL+, etc ... 
// 
// Parameters: 
//    LPMSG        - [in] the special key msg. 
// 
// Output: 
//    BOOL         - TRUE we processed it, FALSE we didn't. 
// 
// Notes: 
// 
BOOL COleControl::OnSpecialKey 
( 
    LPMSG pmsg 
) 
{ 
    // do nothing. 
    // 
    return FALSE; 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::ModalDialog    [callable, utility] 
//=--------------------------------------------------------------------------= 
// should be called when the control is about to show and hide a modal dialog. 
// 
// Parameters: 
//    BOOL        - [in] true means showing a modal dialog, false means done 
// 
// Notes: 
// 
void COleControl::ModalDialog 
( 
    BOOL fShow 
) 
{ 
    // notify the container of our intention to show a modal dialog... 
    // 
    if (m_pInPlaceFrame) 
        m_pInPlaceFrame->EnableModeless(!fShow); 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::BeforeDestroyWindow    [overridable] 
//=--------------------------------------------------------------------------= 
// called just before we destroy a window.  gives the user the opportunity to 
// save information out, especially if they're a subclassed control, and this 
// is an interesting thing to do. 
// 
// Notes: 
// 
void COleControl::BeforeDestroyWindow 
( 
    void 
) 
{ 
    // fweeee 
} 
 
//=--------------------------------------------------------------------------= 
// COleControl::OnSetObjectRectsChangingWIndowPos    [overridable] 
//=--------------------------------------------------------------------------= 
// called just before we perform a SetWindowPos in the SetObjectRects 
// function. gives a control the opportunity to change the flags. 
// 
// Notes: 
// 
void COleControl::OnSetObjectRectsChangingWindowPos(DWORD *dwFlag) 
{ 
    *dwFlag = 0; 
} 
 
void COleControl::OnVerb(LONG lVerb) 
{ 
}