home *** CD-ROM | disk | FTP | other *** search
- //=--------------------------------------------------------------------------=
- // CtlMisc.Cpp
- //=--------------------------------------------------------------------------=
- // Copyright 1995-1997 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.
- //=--------------------------------------------------------------------------=
- //
- // things that aren't elsewhere, such as property pages, and connection
- // points.
-
- #include "IPServer.H"
- #include "CtrlObj.H"
- #include "CtlHelp.H"
- #include "Globals.H"
- #include "StdEnum.H"
- #include "Util.H"
-
- #include <stdarg.h>
-
- // for ASSERT and FAIL
- //
- SZTHISFILE
-
- // this is used in our window proc so that we can find out who was last created
- //
- static COleControl *s_pLastControlCreated;
-
- //=--------------------------------------------------------------------------=
- // COleControl::COleControl
- //=--------------------------------------------------------------------------=
- // constructor
- //
- // Parameters:
- // IUnknown * - [in] controlling Unknown
- // int - [in] type of primary dispatch interface OBJECT_TYPE_*
- // void * - [in] pointer to entire object
- // BOOL - [in] whether to enable IDispatchEx functionality
- // to allow dynamic adding of properties
- // Notes:
- //
- COleControl::COleControl
- (
- IUnknown *pUnkOuter,
- int iPrimaryDispatch,
- void *pMainInterface,
- BOOL fExpandoEnabled
- )
- : CAutomationObject(pUnkOuter, iPrimaryDispatch, pMainInterface, fExpandoEnabled),
- m_cpEvents(SINK_TYPE_EVENT),
- m_cpPropNotify(SINK_TYPE_PROPNOTIFY)
- {
- // initialize all our variables -- we decided against using a memory-zeroing
- // memory allocator, so we sort of have to do this work now ...
- //
- m_nFreezeEvents = 0;
-
- m_pClientSite = NULL;
- m_pControlSite = NULL;
- m_pInPlaceSite = NULL;
- m_pInPlaceFrame = NULL;
- m_pInPlaceUIWindow = NULL;
-
-
- m_pInPlaceSiteWndless = NULL;
-
- // certain hosts don't like 0,0 as your initial size, so we're going to set
- // our initial size to 100,50 [so it's at least sort of visible on the screen]
- //
- m_Size.cx = 0;
- m_Size.cy = 0;
- memset(&m_rcLocation, 0, sizeof(m_rcLocation));
-
- m_hRgn = NULL;
- m_hwnd = NULL;
- m_hwndParent = NULL;
- m_hwndReflect = NULL;
- m_fHostReflects = TRUE;
- m_fCheckedReflecting = FALSE;
-
- m_nFreezeEvents = 0;
- m_pSimpleFrameSite = NULL;
- m_pOleAdviseHolder = NULL;
- m_pViewAdviseSink = NULL;
- m_pDispAmbient = NULL;
-
- m_fDirty = FALSE;
- m_fModeFlagValid = FALSE;
- m_fInPlaceActive = FALSE;
- m_fInPlaceVisible = FALSE;
- m_fUIActive = FALSE;
- m_fSaveSucceeded = FALSE;
- m_fViewAdvisePrimeFirst = FALSE;
- m_fViewAdviseOnlyOnce = FALSE;
- m_fRunMode = FALSE;
- }
-
- //=--------------------------------------------------------------------------=
- // COleControl::~COleControl
- //=--------------------------------------------------------------------------=
- // "We are all of us resigned to death; it's life we aren't resigned to."
- // - Graham Greene (1904-91)
- //
- // Notes:
- //
- COleControl::~COleControl()
- {
- // if we've still got a window, go and kill it now.
- //
- if (m_hwnd) {
- // so our window proc doesn't crash.
- //
- SetWindowLong(m_hwnd, GWL_USERDATA, 0xFFFFFFFF);
- DestroyWindow(m_hwnd);
- }
-
- if (m_hwndReflect) {
- SetWindowLong(m_hwndReflect, GWL_USERDATA, 0);
- DestroyWindow(m_hwndReflect);
- }
-
- if (m_hRgn != NULL)
- {
- DeleteObject(m_hRgn);
- m_hRgn = NULL;
- }
-
- // clean up all the pointers we're holding around.
- //
- QUICK_RELEASE(m_pClientSite);
- QUICK_RELEASE(m_pControlSite);
- QUICK_RELEASE(m_pInPlaceSite);
- QUICK_RELEASE(m_pInPlaceFrame);
- QUICK_RELEASE(m_pInPlaceUIWindow);
- QUICK_RELEASE(m_pSimpleFrameSite);
- QUICK_RELEASE(m_pOleAdviseHolder);
- QUICK_RELEASE(m_pViewAdviseSink);
- QUICK_RELEASE(m_pDispAmbient);
-
- QUICK_RELEASE(m_pInPlaceSiteWndless);
- }
-
- #ifndef DEBUG
- #pragma optimize("t", on)
- #endif // DEBUG
-
- //=--------------------------------------------------------------------------=
- // COleControl::InternalQueryInterface
- //=--------------------------------------------------------------------------=
- // derived-controls should delegate back to this when they decide to support
- // additional interfaces
- //
- // Parameters:
- // REFIID - [in] interface they want
- // void ** - [out] where they want to put the resulting object ptr.
- //
- // Output:
- // HRESULT - S_OK, E_NOINTERFACE
- //
- // Notes:
- // - NOTE: this function is speed critical!!!!
- //
- HRESULT COleControl::InternalQueryInterface
- (
- REFIID riid,
- void **ppvObjOut
- )
- {
- switch (riid.Data1) {
- // private interface for prop page support
- case Data1_IControlPrv:
- if(DO_GUIDS_MATCH(riid, IID_IControlPrv)) {
- *ppvObjOut = (void *)this;
- ExternalAddRef();
- return S_OK;
- }
- goto NoInterface;
- QI_INHERITS(this, IOleControl);
- QI_INHERITS(this, IPointerInactive);
- QI_INHERITS(this, IQuickActivate);
- QI_INHERITS(this, IOleObject);
- QI_INHERITS((IPersistStorage *)this, IPersist);
- QI_INHERITS(this, IPersistStreamInit);
- QI_INHERITS(this, IOleInPlaceObject);
- QI_INHERITS(this, IOleInPlaceObjectWindowless);
- QI_INHERITS((IOleInPlaceActiveObject *)this, IOleWindow);
- QI_INHERITS(this, IOleInPlaceActiveObject);
- QI_INHERITS(this, IViewObject);
- QI_INHERITS(this, IViewObject2);
- QI_INHERITS(this, IViewObjectEx);
- QI_INHERITS(this, IConnectionPointContainer);
- QI_INHERITS(this, ISpecifyPropertyPages);
- QI_INHERITS(this, IPersistStorage);
- QI_INHERITS(this, IPersistPropertyBag);
- QI_INHERITS(this, IProvideClassInfo);
- default:
- goto NoInterface;
- }
-
- // we like the interface, so addref and return
- //
- ((IUnknown *)(*ppvObjOut))->AddRef();
- return S_OK;
-
- NoInterface:
- // delegate to super-class for automation interfaces, etc ...
- //
- return CAutomationObject::InternalQueryInterface(riid, ppvObjOut);
- }
-
- #ifndef DEBUG
- #pragma optimize("s", on)
- #endif // DEBUG
-
- //=--------------------------------------------------------------------------=
- // COleControl::FindConnectionPoint [IConnectionPointContainer]
- //=--------------------------------------------------------------------------=
- // given an IID, find a connection point sink for it.
- //
- // Parameters:
- // REFIID - [in] interfaces they want
- // IConnectionPoint ** - [out] where the cp should go
- //
- // Output:
- // HRESULT
- //
- // Notes:
- //
- STDMETHODIMP COleControl::FindConnectionPoint
- (
- REFIID riid,
- IConnectionPoint **ppConnectionPoint
- )
- {
- CHECK_POINTER(ppConnectionPoint);
-
- // we support the event interface, and IDispatch for it, and we also
- // support IPropertyNotifySink.
- //
- if (DO_GUIDS_MATCH(riid, EVENTIIDOFCONTROL(m_ObjectType)) || DO_GUIDS_MATCH(riid, IID_IDispatch))
- *ppConnectionPoint = &m_cpEvents;
- else if (DO_GUIDS_MATCH(riid, IID_IPropertyNotifySink))
- *ppConnectionPoint = &m_cpPropNotify;
- else
- return E_NOINTERFACE;
-
- // generic post-processing.
- //
- (*ppConnectionPoint)->AddRef();
- return S_OK;
- }
-
- //=--------------------------------------------------------------------------=
- // COleControl::EnumConnectionPoints [IConnectionPointContainer]
- //=--------------------------------------------------------------------------=
- // creates an enumerator for connection points.
- //
- // Parameters:
- // IEnumConnectionPoints ** - [out]
- //
- // Output:
- // HRESULT
- //
- // Notes:
- //
- STDMETHODIMP COleControl::EnumConnectionPoints
- (
- IEnumConnectionPoints **ppEnumConnectionPoints
- )
- {
- IConnectionPoint **rgConnectionPoints;
-
- CHECK_POINTER(ppEnumConnectionPoints);
-
- // HeapAlloc an array of connection points [since our standard enum
- // assumes this and HeapFree's it later ]
- //
- rgConnectionPoints = (IConnectionPoint **)HeapAlloc(g_hHeap, 0, sizeof(IConnectionPoint *) * 2);
- RETURN_ON_NULLALLOC(rgConnectionPoints);
-
- // we support the event interface for this dude as well as IPropertyNotifySink
- //
- rgConnectionPoints[0] = &m_cpEvents;
- rgConnectionPoints[1] = &m_cpPropNotify;
-
- *ppEnumConnectionPoints = (IEnumConnectionPoints *)(IEnumGeneric *) new CStandardEnum(IID_IEnumConnectionPoints,
- 2, sizeof(IConnectionPoint *), (void *)rgConnectionPoints,
- CopyAndAddRefObject);
- if (!*ppEnumConnectionPoints) {
- HeapFree(g_hHeap, 0, rgConnectionPoints);
- return E_OUTOFMEMORY;
- }
-
- return S_OK;
- }
-
- //=--------------------------------------------------------------------------=
- // COleControl::GetPages [ISpecifyPropertyPages]
- //=--------------------------------------------------------------------------=
- // returns a counted array with the guids for our property pages.
- //
- // parameters:
- // CAUUID * - [out] where to put the counted array.
- //
- // Output:
- // HRESULT
- //
- // NOtes:
- //
- STDMETHODIMP COleControl::GetPages
- (
- CAUUID *pPages
- )
- {
- const GUID **pElems;
- void *pv;
- WORD x;
-
- // if there are no property pages, this is actually pretty easy.
- //
- if (!CPROPPAGESOFCONTROL(m_ObjectType)) {
- pPages->cElems = 0;
- pPages->pElems = NULL;
- return S_OK;
- }
-
- // fill out the Counted array, using IMalloc'd memory.
- //
- pPages->cElems = CPROPPAGESOFCONTROL(m_ObjectType);
- pv = CoTaskMemAlloc(sizeof(GUID) * (pPages->cElems));
- RETURN_ON_NULLALLOC(pv);
- pPages->pElems = (GUID *)pv;
-
- // loop through our array of pages and get 'em.
- //
- pElems = PPROPPAGESOFCONTROL(m_ObjectType);
- for (x = 0; x < pPages->cElems; x++)
- pPages->pElems[x] = *(pElems[x]);
-
- return S_OK;
- }
-
- //=--------------------------------------------------------------------------=
- // COleControl::CConnectionPoint::m_pOleControl
- //=--------------------------------------------------------------------------=
- // returns a pointer to the control in which we are nested.
- //
- // Output:
- // COleControl *
- //
- // Notes:
- //
- inline COleControl *COleControl::CConnectionPoint::m_pOleControl
- (
- void
- )
- {
- return (COleControl *)((BYTE *)this - ((m_bType == SINK_TYPE_EVENT)
- ? offsetof(COleControl, m_cpEvents)
- : offsetof(COleControl, m_cpPropNotify)));
- }
-
- //=--------------------------------------------------------------------------=
- // COleControl::CConnectionPoint::QueryInterface
- //=--------------------------------------------------------------------------=
- // standard qi
- //
- // Parameters:
- // REFIID - [in] interface they want
- // void ** - [out] where they want to put the resulting object ptr.
- //
- // Output:
- // HRESULT - S_OK, E_NOINTERFACE
- //
- // Notes:
- //
- STDMETHODIMP COleControl::CConnectionPoint::QueryInterface
- (
- REFIID riid,
- void **ppvObjOut
- )
- {
- if (DO_GUIDS_MATCH(riid, IID_IConnectionPoint) || DO_GUIDS_MATCH(riid, IID_IUnknown)) {
- *ppvObjOut = (IConnectionPoint *)this;
- AddRef();
- return S_OK;
- }
-
- return E_NOINTERFACE;
- }
-
- //=--------------------------------------------------------------------------=
- // COleControl::CConnectionPoint::AddRef
- //=--------------------------------------------------------------------------=
- //
- // Output:
- // ULONG - the new reference count
- //
- // Notes:
- //
- ULONG COleControl::CConnectionPoint::AddRef
- (
- void
- )
- {
- return m_pOleControl()->ExternalAddRef();
- }
-
- //=--------------------------------------------------------------------------=
- // COleControl::CConnectionPoint::Release
- //=--------------------------------------------------------------------------=
- //
- // Output:
- // ULONG - remaining refs
- //
- // Notes:
- //
- ULONG COleControl::CConnectionPoint::Release
- (
- void
- )
- {
- return m_pOleControl()->ExternalRelease();
- }
-
- //=--------------------------------------------------------------------------=
- // COleControl::CConnectionPoint::GetConnectionInterface
- //=--------------------------------------------------------------------------=
- // returns the interface we support connections on.
- //
- // Parameters:
- // IID * - [out] interface we support.
- //
- // Output:
- // HRESULT
- //
- // Notes:
- //
- STDMETHODIMP COleControl::CConnectionPoint::GetConnectionInterface
- (
- IID *piid
- )
- {
- if (m_bType == SINK_TYPE_EVENT)
- *piid = EVENTIIDOFCONTROL(m_pOleControl()->m_ObjectType);
- else
- *piid = IID_IPropertyNotifySink;
-
- return S_OK;
- }
-
- //=--------------------------------------------------------------------------=
- // COleControl::CConnectionPoint::GetConnectionPointContainer
- //=--------------------------------------------------------------------------=
- // returns the connection point container
- //
- // Parameters:
- // IConnectionPointContainer **ppCPC
- //
- // Output:
- // HRESULT
- //
- // Notes:
- //
- STDMETHODIMP COleControl::CConnectionPoint::GetConnectionPointContainer
- (
- IConnectionPointContainer **ppCPC
- )
- {
- return m_pOleControl()->ExternalQueryInterface(IID_IConnectionPointContainer, (void **)ppCPC);
- }
-
-
- //=--------------------------------------------------------------------------=
- // COleControl::CConnectiontPoint::Advise
- //=--------------------------------------------------------------------------=
- // someboyd wants to be advised when something happens.
- //
- // Parameters:
- // IUnknown * - [in] guy who wants to be advised.
- // DWORD * - [out] cookie
- //
- // Output:
- // HRESULT
- //
- // Notes:
- //
- STDMETHODIMP COleControl::CConnectionPoint::Advise
- (
- IUnknown *pUnk,
- DWORD *pdwCookie
- )
- {
- HRESULT hr;
- void *pv;
-
- CHECK_POINTER(pdwCookie);
-
- // first, make sure everybody's got what they thinks they got
- //
- if (m_bType == SINK_TYPE_EVENT) {
-
- // CONSIDER: 12.95 -- this theoretically is broken -- if they do a find
- // connection point on IDispatch, and they just happened to also support
- // the Event IID, we'd advise on that. this is not awesome, but will
- // prove entirely acceptable short term.
- //
- hr = pUnk->QueryInterface(EVENTIIDOFCONTROL(m_pOleControl()->m_ObjectType), &pv);
- if (FAILED(hr))
- hr = pUnk->QueryInterface(IID_IDispatch, &pv);
- }
- else
- hr = pUnk->QueryInterface(IID_IPropertyNotifySink, &pv);
- RETURN_ON_FAILURE(hr);
-
- // finally, add the sink. it's now been cast to the correct type and has
- // been AddRef'd.
- //
- return AddSink(pv, pdwCookie);
- }
-
- //=--------------------------------------------------------------------------=
- // COleControl::CConnectionPoint::AddSink
- //=--------------------------------------------------------------------------=
- // in some cases, we'll already have done the QI, and won't need to do the
- // work that is done in the Advise routine above. thus, these people can
- // just call this instead. [this stems really from IQuickActivate]
- //
- // Parameters:
- // void * - [in] the sink to add. it's already been addref'd
- // DWORD * - [out] cookie
- //
- // Output:
- // HRESULT
- //
- // Notes:
- //
- HRESULT COleControl::CConnectionPoint::AddSink
- (
- void *pv,
- DWORD *pdwCookie
- )
- {
- IUnknown **rgUnkNew;
- int i = 0;
-
- // we optimize the case where there is only one sink to not allocate
- // any storage. turns out very rarely is there more than one.
- //
- switch (m_cSinks) {
-
- case 0:
- ASSERT(!m_rgSinks, "this should be null when there are no sinks");
- m_rgSinks = (IUnknown **)pv;
- break;
-
- case 1:
- // go ahead and do the initial allocation. we'll get 8 at a time
- //
- rgUnkNew = (IUnknown **)HeapAlloc(g_hHeap, 0, 8 * sizeof(IUnknown *));
- RETURN_ON_NULLALLOC(rgUnkNew);
- rgUnkNew[0] = (IUnknown *)m_rgSinks;
- rgUnkNew[1] = (IUnknown *)pv;
- m_rgSinks = rgUnkNew;
- break;
-
- default:
- // if we're out of sinks, then we have to increase the size
- // of the array
- //
- if (!(m_cSinks & 0x7)) {
- rgUnkNew = (IUnknown **)HeapReAlloc(g_hHeap, 0, m_rgSinks, (m_cSinks + 8) * sizeof(IUnknown *));
- RETURN_ON_NULLALLOC(rgUnkNew);
- m_rgSinks = rgUnkNew;
- } else
- rgUnkNew = m_rgSinks;
-
- rgUnkNew[m_cSinks] = (IUnknown *)pv;
- break;
- }
-
- *pdwCookie = (DWORD)pv;
- m_cSinks++;
- return S_OK;
- }
-
-
- //=--------------------------------------------------------------------------=
- // COleControl::CConnectionPoint::Unadvise
- //=--------------------------------------------------------------------------=
- // they don't want to be told any more.
- //
- // Parameters:
- // DWORD - [in] the cookie we gave 'em.
- //
- // Output:
- // HRESULT
- //
- // Notes:
- //
- STDMETHODIMP COleControl::CConnectionPoint::Unadvise
- (
- DWORD dwCookie
- )
- {
- IUnknown *pUnk;
- int x;
-
- if (!dwCookie)
- return S_OK;
-
- // see how many sinks we've currently got, and deal with things based
- // on that.
- //
- switch (m_cSinks) {
- case 1:
- // it's the only sink. make sure the ptrs are the same, and
- // then free things up
- //
- if ((DWORD)m_rgSinks != dwCookie)
- return CONNECT_E_NOCONNECTION;
- m_rgSinks = NULL;
- break;
-
- case 2:
- // there are two sinks. go back down to one sink scenario
- //
- if ((DWORD)m_rgSinks[0] != dwCookie && (DWORD)m_rgSinks[1] != dwCookie)
- return CONNECT_E_NOCONNECTION;
-
- pUnk = ((DWORD)m_rgSinks[0] == dwCookie)
- ? m_rgSinks[1]
- : ((DWORD)m_rgSinks[1] == dwCookie) ? m_rgSinks[0] : NULL;
-
- if (!pUnk) return CONNECT_E_NOCONNECTION;
-
- HeapFree(g_hHeap, 0, m_rgSinks);
- m_rgSinks = (IUnknown **)pUnk;
- break;
-
- default:
- // there are more than two sinks. just clean up the hole we've
- // got in our array now.
- //
- for (x = 0; x < m_cSinks; x++) {
- if ((DWORD)m_rgSinks[x] == dwCookie)
- break;
- }
- if (x == m_cSinks) return CONNECT_E_NOCONNECTION;
- if (x < m_cSinks - 1)
- memcpy(&(m_rgSinks[x]), &(m_rgSinks[x + 1]), (m_cSinks -1 - x) * sizeof(IUnknown *));
- else
- m_rgSinks[x] = NULL;
- break;
- }
-
-
- // we're happy
- //
- m_cSinks--;
- ((IUnknown *)dwCookie)->Release();
- return S_OK;
- }
-
- //=--------------------------------------------------------------------------=
- // COleControl::CConnectionPoint::EnumConnections
- //=--------------------------------------------------------------------------=
- // enumerates all current connections
- //
- // Paramters:
- // IEnumConnections ** - [out] new enumerator object
- //
- // Output:
- // HRESULT
- //
- // NOtes:
- //
- STDMETHODIMP COleControl::CConnectionPoint::EnumConnections
- (
- IEnumConnections **ppEnumOut
- )
- {
- CONNECTDATA *rgConnectData = NULL;
- int i;
-
- if (m_cSinks) {
- // allocate some memory big enough to hold all of the sinks.
- //
- rgConnectData = (CONNECTDATA *)HeapAlloc(g_hHeap, 0, m_cSinks * sizeof(CONNECTDATA));
- RETURN_ON_NULLALLOC(rgConnectData);
-
- // fill in the array
- //
- if (m_cSinks == 1) {
- rgConnectData[0].pUnk = (IUnknown *)m_rgSinks;
- rgConnectData[0].dwCookie = (DWORD)m_rgSinks;
- } else {
- // loop through all available sinks.
- //
- for (i = 0; i < m_cSinks; i++) {
- rgConnectData[i].pUnk = m_rgSinks[i];
- rgConnectData[i].dwCookie = (DWORD)m_rgSinks[i];
- }
- }
- }
-
- // create yon enumerator object.
- //
- *ppEnumOut = (IEnumConnections *)(IEnumGeneric *)new CStandardEnum(IID_IEnumConnections,
- m_cSinks, sizeof(CONNECTDATA), rgConnectData, CopyAndAddRefObject);
- if (!*ppEnumOut) {
- HeapFree(g_hHeap, 0, rgConnectData);
- return E_OUTOFMEMORY;
- }
-
- return S_OK;
- }
-
- //=--------------------------------------------------------------------------=
- // COleControl::CConnectionPoint::~CConnectionPoint
- //=--------------------------------------------------------------------------=
- // cleans up
- //
- // Notes:
- //
- COleControl::CConnectionPoint::~CConnectionPoint ()
- {
- int x;
-
- // clean up some memory stuff
- //
- if (!m_cSinks)
- return;
- else if (m_cSinks == 1)
- ((IUnknown *)m_rgSinks)->Release();
- else {
- for (x = 0; x < m_cSinks; x++)
- QUICK_RELEASE(m_rgSinks[x]);
- HeapFree(g_hHeap, 0, m_rgSinks);
- }
- }
-
- //=--------------------------------------------------------------------------=
- // COleControl::CConnectionPiont::DoInvoke
- //=--------------------------------------------------------------------------=
- // fires an event to all listening on our event interface.
- //
- // Parameters:
- // DISPID - [in] event to fire.
- // DISPPARAMS - [in]
- //
- // Notes:
- //
- void COleControl::CConnectionPoint::DoInvoke
- (
- DISPID dispid,
- DISPPARAMS *pdispparams
- )
- {
- int iConnection;
-
- // if we don't have any sinks, then there's nothing to do. we intentionally
- // ignore errors here.
- //
- if (m_cSinks == 0)
- return;
- else if (m_cSinks == 1)
- ((IDispatch *)m_rgSinks)->Invoke(dispid, IID_NULL, 0, DISPATCH_METHOD, pdispparams, NULL, NULL, NULL);
- else
- for (iConnection = 0; iConnection < m_cSinks; iConnection++)
- ((IDispatch *)m_rgSinks[iConnection])->Invoke(dispid, IID_NULL, 0, DISPATCH_METHOD, pdispparams, NULL, NULL, NULL);
- }
-
- //=--------------------------------------------------------------------------=
- // COleControl::CConnectionPoint::DoOnChanged
- //=--------------------------------------------------------------------------=
- // fires the OnChanged event for IPropertyNotifySink listeners.
- //
- // Parameters:
- // DISPID - [in] dude that changed.
- //
- // Output:
- // none
- //
- // Notes:
- //
- void COleControl::CConnectionPoint::DoOnChanged
- (
- DISPID dispid
- )
- {
- int iConnection;
-
- // if we don't have any sinks, then there's nothing to do.
- //
- if (m_cSinks == 0)
- return;
- else if (m_cSinks == 1)
- ((IPropertyNotifySink *)m_rgSinks)->OnChanged(dispid);
- else
- for (iConnection = 0; iConnection < m_cSinks; iConnection++)
- ((IPropertyNotifySink *)m_rgSinks[iConnection])->OnChanged(dispid);
- }
-
- //=--------------------------------------------------------------------------=
- // COleControl::CConnectionPoint::DoOnRequestEdit
- //=--------------------------------------------------------------------------=
- // fires the OnRequestEdit for IPropertyNotifySinkListeners
- //
- // Parameters:
- // DISPID - [in] dispid user wants to change.
- //
- // Output:
- // BOOL - false means you cant
- //
- // Notes:
- //
- BOOL COleControl::CConnectionPoint::DoOnRequestEdit
- (
- DISPID dispid
- )
- {
- HRESULT hr;
- int iConnection;
-
- // if we don't have any sinks, then there's nothing to do.
- //
- if (m_cSinks == 0)
- hr = S_OK;
- else if (m_cSinks == 1)
- hr =((IPropertyNotifySink *)m_rgSinks)->OnRequestEdit(dispid);
- else {
- for (iConnection = 0; iConnection < m_cSinks; iConnection++) {
- hr = ((IPropertyNotifySink *)m_rgSinks[iConnection])->OnRequestEdit(dispid);
- if (hr != S_OK) break;
- }
- }
-
- return (hr == S_OK) ? TRUE : FALSE;
- }
-
- //=--------------------------------------------------------------------------=
- // COleControl::CreateInPlaceWindow
- //=--------------------------------------------------------------------------=
- // creates the window with which we will be working.
- // yay.
- //
- // Parameters:
- // int - [in] left
- // int - [in] top
- // BOOL - [in] can we skip redrawing?
- //
- // Output:
- // HWND
- //
- // Notes:
- // - DANGER! DANGER! this function is protected so that anybody can call it
- // from their control. however, people should be extremely careful of when
- // and why they do this. preferably, this function would only need to be
- // called by an end-control writer in design mode to take care of some
- // hosting/painting issues. otherwise, the framework should be left to
- // call it when it wants.
- //
- HWND COleControl::CreateInPlaceWindow
- (
- int x,
- int y,
- BOOL fNoRedraw
- )
- {
- BOOL fVisible;
- HRESULT hr;
- DWORD dwWindowStyle, dwExWindowStyle;
- char szWindowTitle[128];
-
- // if we've already got a window, do nothing.
- //
- if (m_hwnd)
- return m_hwnd;
-
- // get the user to register the class if it's not already
- // been done. we have to critical section this since more than one thread
- // can be trying to create this control
- //
- EnterCriticalSection(&g_CriticalSection);
- if (!CTLWNDCLASSREGISTERED(m_ObjectType)) {
- if (!RegisterClassData()) {
- LeaveCriticalSection(&g_CriticalSection);
- return NULL;
- } else
- CTLWNDCLASSREGISTERED(m_ObjectType) = TRUE;
- }
- LeaveCriticalSection(&g_CriticalSection);
-
- // let the user set up things like the window title, the
- // style, and anything else they feel interested in fiddling
- // with.
- //
- dwWindowStyle = dwExWindowStyle = 0;
- szWindowTitle[0] = '\0';
- if (!BeforeCreateWindow(&dwWindowStyle, &dwExWindowStyle, szWindowTitle))
- return NULL;
-
- dwWindowStyle |= (WS_CHILD | WS_CLIPSIBLINGS);
-
- // create window visible if parent hidden (common case)
- // otherwise, create hidden, then shown. this is a little subtle, but
- // it makes sense eventually.
- //
- if (!m_hwndParent)
- m_hwndParent = GetParkingWindow();
-
- fVisible = IsWindowVisible(m_hwndParent);
-
- // This one kinda sucks -- if a control is subclassed, and we're in
- // a host that doesn't support Message Reflecting, we have to create
- // the user window in another window which will do all the reflecting.
- // VERY blech. [don't however, bother in design mode]
- //
- if (SUBCLASSWNDPROCOFCONTROL(m_ObjectType) && (m_hwndParent != GetParkingWindow())) {
- // determine if the host supports message reflecting.
- //
- if (!m_fCheckedReflecting) {
- VARIANT_BOOL f;
- hr = GetAmbientProperty(DISPID_AMBIENT_MESSAGEREFLECT, VT_BOOL, &f);
- if (FAILED(hr) || !f)
- m_fHostReflects = FALSE;
- m_fCheckedReflecting = TRUE;
- }
-
- // if the host doesn't support reflecting, then we have to create
- // an extra window around the control window, and then parent it
- // off that.
- //
- if (!m_fHostReflects) {
- ASSERT(m_hwndReflect == NULL, "Where'd this come from?");
- m_hwndReflect = CreateReflectWindow(!fVisible, m_hwndParent, x, y, &m_Size);
- if (!m_hwndReflect)
- return NULL;
- SetWindowLong(m_hwndReflect, GWL_USERDATA, (long)this);
- dwWindowStyle |= WS_VISIBLE;
- }
- } else {
- if (!fVisible)
- dwWindowStyle |= WS_VISIBLE;
- }
-
- // we have to mutex the entire create window process since we need to use
- // the s_pLastControlCreated to pass in the object pointer. nothing too
- // serious
- //
- EnterCriticalSection(&g_CriticalSection);
- s_pLastControlCreated = this;
- m_fCreatingWindow = TRUE;
-
- // finally, go create the window, parenting it as appropriate.
- //
- m_hwnd = CreateWindowEx(dwExWindowStyle,
- WNDCLASSNAMEOFCONTROL(m_ObjectType),
- szWindowTitle,
- dwWindowStyle,
- (m_hwndReflect) ? 0 : x,
- (m_hwndReflect) ? 0 : y,
- m_Size.cx, m_Size.cy,
- (m_hwndReflect) ? m_hwndReflect : m_hwndParent,
- NULL, g_hInstance, NULL);
-
- // clean up some variables, and leave the critical section
- //
- m_fCreatingWindow = FALSE;
- s_pLastControlCreated = NULL;
- LeaveCriticalSection(&g_CriticalSection);
-
- if (m_hwnd) {
- // let the derived-control do something if they so desire
- //
- if (!AfterCreateWindow()) {
- BeforeDestroyWindow();
- SetWindowLong(m_hwnd, GWL_USERDATA, 0xFFFFFFFF);
- DestroyWindow(m_hwnd);
- m_hwnd = NULL;
- return m_hwnd;
- }
-
- // if we didn't create the window visible, show it now.
- //
-
- if (fVisible)
- {
- if (GetParent(m_hwnd) != m_hwndParent)
- // SetWindowPos fails if parent hwnd is passed in so keep
- // this behaviour in those cases without ripping.
- SetWindowPos(m_hwnd, m_hwndParent, 0, 0, 0, 0,
- SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW | ((fNoRedraw) ? SWP_NOREDRAW : 0));
- }
- }
-
- // finally, tell the host of this
- //
- if (m_pClientSite)
- m_pClientSite->ShowObject();
-
- return m_hwnd;
- }
-
- //=--------------------------------------------------------------------------=
- // COleControl::SetInPlaceParent [helper]
- //=--------------------------------------------------------------------------=
- // sets up the parent window for our control.
- //
- // Parameters:
- // HWND - [in] new parent window
- //
- // Notes:
- //
- void COleControl::SetInPlaceParent
- (
- HWND hwndParent
- )
- {
- ASSERT(!m_pInPlaceSiteWndless, "This routine should only get called for windowed OLE controls");
-
- if (m_hwndParent == hwndParent)
- return;
-
- m_hwndParent = hwndParent;
- if (m_hwnd)
- SetParent(GetOuterWindow(), hwndParent);
- }
-
- //=--------------------------------------------------------------------------=
- // COleControl::ControlWindowProc
- //=--------------------------------------------------------------------------=
- // default window proc for an OLE Control. controls will have their own
- // window proc called from this one, after some processing is done.
- //
- // Parameters:
- // - see win32sdk docs.
- //
- // Notes:
- //
- LRESULT CALLBACK COleControl::ControlWindowProc
- (
- HWND hwnd,
- UINT msg,
- WPARAM wParam,
- LPARAM lParam
- )
- {
- COleControl *pCtl = ControlFromHwnd(hwnd);
- HRESULT hr;
- LRESULT lResult;
- DWORD dwCookie;
-
- // if the value isn't a positive value, then it's in some special
- // state [creation or destruction] this is safe because under win32,
- // the upper 2GB of an address space aren't available.
- //
- if ((LONG)pCtl == 0) {
- pCtl = s_pLastControlCreated;
- SetWindowLong(hwnd, GWL_USERDATA, (LONG)pCtl);
- pCtl->m_hwnd = hwnd;
- } else if ((ULONG)pCtl == 0xffffffff) {
- return DefWindowProc(hwnd, msg, wParam, lParam);
- }
-
- // message preprocessing
- //
- if (pCtl->m_pSimpleFrameSite) {
- hr = pCtl->m_pSimpleFrameSite->PreMessageFilter(hwnd, msg, wParam, lParam, &lResult, &dwCookie);
- if (hr == S_FALSE) return lResult;
- }
-
- // for certain messages, do not call the user window proc. instead,
- // we have something else we'd like to do.
- //
- switch (msg) {
- case WM_PAINT:
- {
- // call the user's OnDraw routine.
- //
- PAINTSTRUCT ps;
- RECT rc;
- HDC hdc;
-
- // if we're given an HDC, then use it
- //
- if (!wParam)
- hdc = BeginPaint(hwnd, &ps);
- else
- hdc = (HDC)wParam;
-
- GetClientRect(hwnd, &rc);
- pCtl->OnDraw(DVASPECT_CONTENT, hdc, (RECTL *)&rc, NULL, NULL, TRUE);
-
- if (!wParam)
- EndPaint(hwnd, &ps);
- }
- break;
-
- default:
- // call the derived-control's window proc
- //
- lResult = pCtl->WindowProc(msg, wParam, lParam);
- break;
- }
-
- // message postprocessing
- //
- switch (msg) {
-
- case WM_NCDESTROY:
- // after this point, the window doesn't exist any more
- //
- pCtl->m_hwnd = NULL;
- break;
-
- case WM_SETFOCUS:
- case WM_KILLFOCUS:
- // give the control site focus notification
- //
- if (pCtl->m_fInPlaceActive && pCtl->m_pControlSite)
- pCtl->m_pControlSite->OnFocus(msg == WM_SETFOCUS);
- break;
-
- case WM_SIZE:
- // a change in size is a change in view
- //
- if (!pCtl->m_fCreatingWindow)
- pCtl->ViewChanged();
- break;
- }
-
- // lastly, simple frame postmessage processing
- //
- if (pCtl->m_pSimpleFrameSite)
- pCtl->m_pSimpleFrameSite->PostMessageFilter(hwnd, msg, wParam, lParam, &lResult, dwCookie);
-
- return lResult;
- }
-
- //=--------------------------------------------------------------------------=
- // COleControl::SetFocus
- //=--------------------------------------------------------------------------=
- // we have to override this routine to get UI Activation correct.
- //
- // Parameters:
- // BOOL - [in] true means take, false release
- //
- // Output:
- // BOOL
- //
- // Notes:
- // - CONSIDER: this is pretty messy, and it's still not entirely clear
- // what the ole control/focus story is.
- //
- BOOL COleControl::SetFocus
- (
- BOOL fGrab
- )
- {
- HRESULT hr;
- HWND hwnd;
-
- // first thing to do is check out UI Activation state, and then set
- // focus [either with windows api, or via the host for windowless
- // controls]
- //
- if (m_pInPlaceSiteWndless) {
- if (!m_fUIActive && fGrab)
- if (FAILED(InPlaceActivate(OLEIVERB_UIACTIVATE))) return FALSE;
-
- hr = m_pInPlaceSiteWndless->SetFocus(fGrab);
- return (hr == S_OK) ? TRUE : FALSE;
- } else {
-
- // we've got a window.
- //
- if (m_fInPlaceActive) {
- hwnd = (fGrab) ? m_hwnd : m_hwndParent;
- if (!m_fUIActive && fGrab)
- return SUCCEEDED(InPlaceActivate(OLEIVERB_UIACTIVATE));
- else
- return SetGUIFocus(hwnd);
- } else
- return FALSE;
- }
-
- // dead code
- }
-
- //=--------------------------------------------------------------------------=
- // COleControl::SetGUIFocus
- //=--------------------------------------------------------------------------=
- // does the work of setting the Windows GUI focus to the specified window
- //
- // Parameters:
- // HWND - [in] window that should get focus
- //
- // Output:
- // BOOL - [out] whether setting focus succeeded
- //
- // Notes:
- // we do this because some controls host non-ole window hierarchies, like
- // the Netscape plugin ocx. in such cases, the control may need to be UIActive
- // to function properly in the document, but cannot take the windows focus
- // away from one of its child windows. such controls may override this method
- // and respond as appropriate.
- //
- BOOL COleControl::SetGUIFocus
- (
- HWND hwndSet
- )
- {
- return (::SetFocus(hwndSet) == hwndSet);
- }
-
-
- //=--------------------------------------------------------------------------=
- // COleControl::ReflectWindowProc
- //=--------------------------------------------------------------------------=
- // reflects window messages on to the child window. very lame.
- //
- // Parameters and Output:
- // - see win32 sdk docs
- //
- // Notes:
- //
- LRESULT CALLBACK COleControl::ReflectWindowProc
- (
- HWND hwnd,
- UINT msg,
- WPARAM wParam,
- LPARAM lParam
- )
- {
- COleControl *pCtl;
-
- switch (msg) {
- case WM_COMMAND:
- case WM_NOTIFY:
- case WM_CTLCOLORBTN:
- case WM_CTLCOLORDLG:
- case WM_CTLCOLOREDIT:
- case WM_CTLCOLORLISTBOX:
- case WM_CTLCOLORMSGBOX:
- case WM_CTLCOLORSCROLLBAR:
- case WM_CTLCOLORSTATIC:
- case WM_DRAWITEM:
- case WM_MEASUREITEM:
- case WM_DELETEITEM:
- case WM_VKEYTOITEM:
- case WM_CHARTOITEM:
- case WM_COMPAREITEM:
- case WM_HSCROLL:
- case WM_VSCROLL:
- case WM_PARENTNOTIFY:
- case WM_SETFOCUS:
- case WM_SIZE:
- pCtl = (COleControl *)GetWindowLong(hwnd, GWL_USERDATA);
- if (pCtl)
- return SendMessage(pCtl->m_hwnd, OCM__BASE + msg, wParam, lParam);
- break;
- }
-
- return DefWindowProc(hwnd, msg, wParam, lParam);
- }
-
- //=--------------------------------------------------------------------------=
- // COleControl::GetAmbientProperty [callable]
- //=--------------------------------------------------------------------------=
- // returns the value of an ambient property
- //
- // Parameters:
- // DISPID - [in] property to get
- // VARTYPE - [in] type of desired data
- // void * - [out] where to put the data
- //
- // Output:
- // BOOL - FALSE means didn't work.
- //
- // Notes:
- //
- BOOL COleControl::GetAmbientProperty
- (
- DISPID dispid,
- VARTYPE vt,
- void *pData
- )
- {
- DISPPARAMS dispparams;
- VARIANT v, v2;
- HRESULT hr;
-
- v.vt = VT_EMPTY;
- v.lVal = 0;
- v2.vt = VT_EMPTY;
- v2.lVal = 0;
-
- // get a pointer to the source of ambient properties.
- //
- if (!m_pDispAmbient) {
- if (m_pClientSite)
- m_pClientSite->QueryInterface(IID_IDispatch, (void **)&m_pDispAmbient);
-
- if (!m_pDispAmbient)
- return FALSE;
- }
-
- // now go and get the property into a variant.
- //
- memset(&dispparams, 0, sizeof(DISPPARAMS));
- hr = m_pDispAmbient->Invoke(dispid, IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams,
- &v, NULL, NULL);
- if (FAILED(hr)) return FALSE;
-
- // we've got the variant, so now go an coerce it to the type that the user
- // wants. if the types are the same, then this will copy the stuff to
- // do appropriate ref counting ...
- //
- hr = VariantChangeType(&v2, &v, 0, vt);
- if (FAILED(hr)) {
- VariantClear(&v);
- return FALSE;
- }
-
- // copy the data to where the user wants it
- //
- CopyMemory(pData, &(v2.lVal), g_rgcbDataTypeSize[vt]);
- VariantClear(&v);
- return TRUE;
- }
-
- //=--------------------------------------------------------------------------=
- // COleControl::GetAmbientFont [callable]
- //=--------------------------------------------------------------------------=
- // gets the current font for the user.
- //
- // Parameters:
- // IFont ** - [out] where to put the font.
- //
- // Output:
- // BOOL - FALSE means couldn't get it.
- //
- // Notes:
- //
- BOOL COleControl::GetAmbientFont
- (
- IFont **ppFont
- )
- {
- IDispatch *pFontDisp;
-
- // we don't have to do much here except get the ambient property and QI
- // it for the user.
- //
- *ppFont = NULL;
- if (!GetAmbientProperty(DISPID_AMBIENT_FONT, VT_DISPATCH, &pFontDisp))
- return FALSE;
-
- pFontDisp->QueryInterface(IID_IFont, (void **)ppFont);
- pFontDisp->Release();
- return (*ppFont) ? TRUE : FALSE;
- }
-
- //=--------------------------------------------------------------------------=
- // COleControl::DesignMode
- //=--------------------------------------------------------------------------=
- // returns TRUE if we're in Design mode.
- //
- // Output:
- // BOOL - true is design mode, false is run mode
- //
- // Notes:
- //
- BOOL COleControl::DesignMode
- (
- void
- )
- {
- VARIANT_BOOL f;
-
- // if we don't already know our run mode, go and get it. we'll assume
- // it's true unless told otherwise [or if the operation fails ...]
- //
- if (!m_fModeFlagValid) {
- f = TRUE;
- m_fModeFlagValid = TRUE;
- GetAmbientProperty(DISPID_AMBIENT_USERMODE, VT_BOOL, &f);
- m_fRunMode = f;
- }
-
- return !m_fRunMode;
- }
-
-
- //=--------------------------------------------------------------------------=
- // COleControl::FireEvent
- //=--------------------------------------------------------------------------=
- // fires an event. handles arbitrary number of arguments.
- //
- // Parameters:
- // EVENTINFO * - [in] struct that describes the event.
- // ... - arguments to the event
- //
- // Output:
- // none
- //
- // Notes:
- // - use stdarg's va_* macros.
- //
- void __cdecl COleControl::FireEvent
- (
- EVENTINFO *pEventInfo,
- ...
- )
- {
- va_list valist;
- DISPPARAMS dispparams;
- VARIANT rgvParameters[MAX_ARGS];
- VARIANT *pv;
- VARTYPE vt;
- int iParameter;
- int cbSize;
-
- ASSERT(pEventInfo->cParameters <= MAX_ARGS, "Don't support more than MAX_ARGS params. sorry.");
-
- va_start(valist, pEventInfo);
-
- // copy the Parameters into the rgvParameters array. make sure we reverse
- // them for automation
- //
- pv = &(rgvParameters[pEventInfo->cParameters - 1]);
- for (iParameter = 0; iParameter < pEventInfo->cParameters; iParameter++) {
-
- vt = pEventInfo->rgTypes[iParameter];
-
- // if it's a by value variant, then just copy the whole
- // dang thing
- //
- if (vt == VT_VARIANT)
- *pv = va_arg(valist, VARIANT);
- else {
- // copy the vt and the data value.
- //
- pv->vt = vt;
- if (vt & VT_BYREF)
- cbSize = sizeof(void *);
- else
- cbSize = g_rgcbDataTypeSize[vt];
-
- // small optimization -- we can copy 2/4 bytes over quite
- // quickly.
- //
- if (cbSize == sizeof(short))
- V_I2(pv) = va_arg(valist, short);
- else if (cbSize == 4)
- V_I4(pv) = va_arg(valist, long);
- else {
- // copy over 8 bytes
- //
- ASSERT(cbSize == 8, "don't recognize the type!!");
- V_CY(pv) = va_arg(valist, CURRENCY);
- }
- }
-
- pv--;
- }
-
- // fire the event
- //
- dispparams.rgvarg = rgvParameters;
- dispparams.cArgs = pEventInfo->cParameters;
- dispparams.rgdispidNamedArgs = NULL;
- dispparams.cNamedArgs = 0;
-
- m_cpEvents.DoInvoke(pEventInfo->dispid, &dispparams);
-
- va_end(valist);
- }
-
- //=--------------------------------------------------------------------------=
- // COleControl::AfterCreateWindow [overridable]
- //=--------------------------------------------------------------------------=
- // something the user can pay attention to
- //
- // Output:
- // BOOL - false means fatal error, can't continue
- // Notes:
- //
- BOOL COleControl::AfterCreateWindow
- (
- void
- )
- {
- return TRUE;
- }
-
- //=--------------------------------------------------------------------------=
- // COleControl::BeforeCreateWindow [overridable]
- //=--------------------------------------------------------------------------=
- // called just before we create a window. the user should register their
- // window class here, and set up any other things, such as the title of
- // the window, and/or sytle bits, etc ...
- //
- // Parameters:
- // DWORD * - [out] dwWindowFlags
- // DWORD * - [out] dwExWindowFlags
- // LPSTR - [out] name of window to create
- //
- // Output:
- // BOOL - false means fatal error, can't continue
- //
- // Notes:
- //
- BOOL COleControl::BeforeCreateWindow
- (
- DWORD *pdwWindowStyle,
- DWORD *pdwExWindowStyle,
- LPSTR pszWindowTitle
- )
- {
- return TRUE;
- }
-
- //=--------------------------------------------------------------------------=
- // COleControl::InvalidateControl [callable]
- //=--------------------------------------------------------------------------=
- void COleControl::InvalidateControl
- (
- LPCRECT lpRect
- )
- {
- if (m_fInPlaceActive)
- InvalidateRect(m_hwnd, lpRect, TRUE);
- else
- ViewChanged();
-
- // CONSIDER: one might want to call pOleAdviseHolder->OnDataChanged() here
- // if there was support for IDataObject
- }
-
- //=--------------------------------------------------------------------------=
- // COleControl::SetControlSize [callable]
- //=--------------------------------------------------------------------------=
- // sets the control size. they'll give us the size in pixels. we've got to
- // convert them back to HIMETRIC before passing them on!
- //
- // Parameters:
- // SIZEL * - [in] new size
- //
- // Output:
- // BOOL
- //
- // Notes:
- //
- BOOL COleControl::SetControlSize
- (
- SIZEL *pSize
- )
- {
- HRESULT hr;
- SIZEL slHiMetric;
-
- PixelToHiMetric(pSize, &slHiMetric);
- hr = SetExtent(DVASPECT_CONTENT, &slHiMetric);
- return (FAILED(hr)) ? FALSE : TRUE;
- }
-
- //=--------------------------------------------------------------------------=
- // COleControl::RecreateControlWindow [callable]
- //=--------------------------------------------------------------------------=
- // called by a [subclassed, typically] control to recreate it's control
- // window.
- //
- // Parameters:
- // none
- //
- // Output:
- // HRESULT
- //
- // Notes:
- // - NOTE: USE ME EXTREMELY SPARINGLY! THIS IS AN EXTREMELY EXPENSIVE
- // OPERATION!
- //
- HRESULT COleControl::RecreateControlWindow
- (
- void
- )
- {
- HRESULT hr;
- HWND hwndPrev;
-
- // we need to correctly preserve the control's position within the
- // z-order here.
- //
- if (m_hwnd)
- hwndPrev = ::GetWindow(m_hwnd, GW_HWNDPREV);
-
- // if we're in place active, then we have to deactivate, and reactivate
- // ourselves with the new window ...
- //
- if (m_fInPlaceActive) {
-
- hr = InPlaceDeactivate();
- RETURN_ON_FAILURE(hr);
- hr = InPlaceActivate((m_fUIActive) ? OLEIVERB_UIACTIVATE : OLEIVERB_INPLACEACTIVATE);
- RETURN_ON_FAILURE(hr);
-
- } else if (m_hwnd) {
- DestroyWindow(m_hwnd);
- m_hwnd = NULL;
- if (m_hwndReflect) {
- DestroyWindow(m_hwndReflect);
- m_hwndReflect = NULL;
- }
-
- CreateInPlaceWindow(0, 0, FALSE);
- }
-
- // restore z-order position
- //
- if (m_hwnd)
- SetWindowPos(m_hwnd, hwndPrev, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
-
- return m_hwnd ? S_OK : E_FAIL;
- }
-
- // from Globals.C. don't need to mutex it here since we only read it.
- //
- extern HINSTANCE g_hInstResources;
-
- //=--------------------------------------------------------------------------=
- // COleControl::GetResourceHandle [callable]
- //=--------------------------------------------------------------------------=
- // gets the HINSTANCE of the DLL where the control should get resources
- // from. implemented in such a way to support satellite DLLs.
- //
- // Output:
- // HINSTANCE
- //
- // Notes:
- //
- HINSTANCE COleControl::GetResourceHandle
- (
- void
- )
- {
- if (!g_fSatelliteLocalization)
- return g_hInstance;
-
- // if we've already got it, then there's not all that much to do.
- // don't need to crit sect this one right here since even if they do fall
- // into the ::GetResourceHandle call, it'll properly deal with things.
- //
- if (g_hInstResources)
- return g_hInstResources;
-
- // we'll get the ambient localeid from the host, and pass that on to the
- // automation object.
- //
- // crit sect this for apartment threading support.
- //
- EnterCriticalSection(&g_CriticalSection);
- if (!g_fHaveLocale)
- // if we can't get the ambient locale id, then we'll just continue
- // with the globally set up value.
- //
- if (!GetAmbientProperty(DISPID_AMBIENT_LOCALEID, VT_I4, &g_lcidLocale))
- goto Done;
-
- g_fHaveLocale = TRUE;
-
- Done:
- LeaveCriticalSection(&g_CriticalSection);
- return ::GetResourceHandle();
- }
-