X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/6505ca85df415198d1686d48253545dcb93a22c6..69d31e313035d5e22d9400ec946f6007f710910c:/src/msw/ole/activex.cpp diff --git a/src/msw/ole/activex.cpp b/src/msw/ole/activex.cpp index 50a326a81d..73b51d3cac 100644 --- a/src/msw/ole/activex.cpp +++ b/src/msw/ole/activex.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: msw/ole/activex.cpp +// Name: src/msw/ole/activex.cpp // Purpose: wxActiveXContainer implementation // Author: Ryan Norton , Lindsay Mathieson // Modified by: @@ -23,14 +23,18 @@ #pragma hdrstop #endif -#include "wx/dcclient.h" -#include "wx/math.h" +#if wxUSE_ACTIVEX -// I don't know why members of tagVARIANT aren't found when compiling -// with Wine -#ifndef __WINE__ +#ifndef WX_PRECOMP + #include "wx/dcclient.h" + #include "wx/math.h" +#endif + +#include "wx/msw/dc.h" #include "wx/msw/ole/activex.h" +#include "wx/msw/private.h" // for wxCopyRectToRECT + // autointerfaces that we only use here WX_DECLARE_AUTOOLE(wxAutoIOleInPlaceSite, IOleInPlaceSite) WX_DECLARE_AUTOOLE(wxAutoIOleDocument, IOleDocument) @@ -41,7 +45,7 @@ WX_DECLARE_AUTOOLE(wxAutoITypeInfo, ITypeInfo) WX_DECLARE_AUTOOLE(wxAutoIConnectionPoint, IConnectionPoint) WX_DECLARE_AUTOOLE(wxAutoIConnectionPointContainer, IConnectionPointContainer) -DEFINE_EVENT_TYPE(wxEVT_ACTIVEX); +wxDEFINE_EVENT( wxEVT_ACTIVEX, wxActiveXEvent ); // Ole class helpers (sort of MFC-like) from wxActiveX #define DECLARE_OLE_UNKNOWN(cls)\ @@ -69,21 +73,21 @@ DEFINE_EVENT_TYPE(wxEVT_ACTIVEX); if (! ppvObject)\ {\ return E_FAIL;\ - };\ + }\ const char *desc = NULL;\ cls::_GetInterface(this, iid, ppvObject, desc);\ if (! *ppvObject)\ {\ return E_NOINTERFACE;\ - };\ + }\ ((IUnknown * )(*ppvObject))->AddRef();\ return S_OK;\ - };\ + }\ ULONG STDMETHODCALLTYPE cls::AddRef()\ {\ InterlockedIncrement(&refCount.l);\ return refCount.l;\ - };\ + }\ ULONG STDMETHODCALLTYPE cls::Release()\ {\ if (refCount.l > 0)\ @@ -93,7 +97,7 @@ DEFINE_EVENT_TYPE(wxEVT_ACTIVEX); {\ delete this;\ return 0;\ - };\ + }\ return refCount.l;\ }\ else\ @@ -103,7 +107,7 @@ DEFINE_EVENT_TYPE(wxEVT_ACTIVEX); {\ InterlockedIncrement(&lockCount.l);\ return lockCount.l;\ - };\ + }\ ULONG STDMETHODCALLTYPE cls::ReleaseLock()\ {\ if (lockCount.l > 0)\ @@ -381,7 +385,7 @@ public: if (! SUCCEEDED(hr)) { return E_UNEXPECTED; - }; + } hr = QueryInterface(IID_IOleInPlaceUIWindow, (void **) ppDoc); if (! SUCCEEDED(hr)) @@ -389,7 +393,7 @@ public: (*ppFrame)->Release(); *ppFrame = NULL; return E_UNEXPECTED; - }; + } RECT rect; ::GetClientRect(m_hWndParent, &rect); @@ -398,13 +402,13 @@ public: lprcPosRect->left = lprcPosRect->top = 0; lprcPosRect->right = rect.right; lprcPosRect->bottom = rect.bottom; - }; + } if (lprcClipRect) { lprcClipRect->left = lprcClipRect->top = 0; lprcClipRect->right = rect.right; lprcClipRect->bottom = rect.bottom; - }; + } memset(lpFrameInfo, 0, sizeof(OLEINPLACEFRAMEINFO)); lpFrameInfo->cb = sizeof(OLEINPLACEFRAMEINFO); @@ -484,8 +488,8 @@ public: case OLEGETMONIKER_UNASSIGN : return "OLEGETMONIKER_UNASSIGN"; case OLEGETMONIKER_TEMPFORUSER : return "OLEGETMONIKER_TEMPFORUSER"; default : return "Bad Enum"; - }; - }; + } + } const char *OleGetWhicMonikerStr(DWORD dwWhichMoniker) { @@ -495,8 +499,8 @@ public: case OLEWHICHMK_OBJREL : return "OLEWHICHMK_OBJREL"; case OLEWHICHMK_OBJFULL : return "OLEWHICHMK_OBJFULL"; default : return "Bad Enum"; - }; - }; + } + } STDMETHOD(GetMoniker)(DWORD, DWORD, IMoniker **){return E_FAIL;} HRESULT STDMETHODCALLTYPE GetContainer(LPOLECONTAINER * ppContainer) { @@ -523,7 +527,7 @@ public: HRESULT STDMETHODCALLTYPE LockContainer(BOOL){return S_OK;} //********************IOleItemContainer*************************** HRESULT STDMETHODCALLTYPE - #ifdef __WXWINCE__ + #if 0 // defined(__WXWINCE__) && __VISUALC__ < 1400 GetObject #elif defined(_UNICODE) GetObjectW @@ -623,11 +627,11 @@ public: return E_FAIL; m_window->m_docView->SetInPlaceSite(inPlaceSite); - }; + } m_window->m_docView->UIActivate(TRUE); return S_OK; - }; + } protected: @@ -666,7 +670,7 @@ DEFINE_OLE_TABLE(FrameSite) OLE_IINTERFACE(IOleDocumentSite) OLE_IINTERFACE(IAdviseSink) OLE_IINTERFACE(IOleControlSite) -END_OLE_TABLE; +END_OLE_TABLE //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -690,8 +694,15 @@ private: friend bool wxActiveXEventsInterface(wxActiveXEvents *self, REFIID iid, void **_interface, const char *&desc); public: + + // a pointer to this static variable is used as an 'invalid_entry_marker' + // wxVariants containing a void* to this variables are 'empty' in the sense + // that the actual ActiveX OLE parameter has not been converted and inserted + // into m_params. + static wxVariant ms_invalidEntryMarker; + wxActiveXEvents(wxActiveXContainer *ax) : m_activeX(ax), m_haveCustomId(false) {} - wxActiveXEvents(wxActiveXContainer *ax, REFIID iid) : m_activeX(ax), m_haveCustomId(true), m_customId(iid) {} + wxActiveXEvents(wxActiveXContainer *ax, REFIID iid) : m_activeX(ax), m_customId(iid), m_haveCustomId(true) {} virtual ~wxActiveXEvents() { } @@ -713,11 +724,11 @@ public: } - STDMETHODIMP Invoke(DISPID dispIdMember, REFIID WXUNUSED(riid), - LCID WXUNUSED(lcid), + STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, + LCID lcid, WORD wFlags, DISPPARAMS * pDispParams, - VARIANT * WXUNUSED(pVarResult), EXCEPINFO * WXUNUSED(pExcepInfo), - unsigned int * WXUNUSED(puArgErr)) + VARIANT * pVarResult, EXCEPINFO * pExcepInfo, + unsigned int * puArgErr) { if (wFlags & (DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF)) return E_NOTIMPL; @@ -729,31 +740,37 @@ public: // Dispatch Event wxActiveXEvent event; event.SetEventType(wxEVT_ACTIVEX); + // Create an empty list of Variants + // Note that the event parameters use lazy evaluation + // They are not actually created until wxActiveXEvent::operator[] is called event.m_params.NullList(); event.m_dispid = dispIdMember; - // arguments - if (pDispParams) - { - for (DWORD i = pDispParams->cArgs; i > 0; i--) - { - VARIANTARG& va = pDispParams->rgvarg[i-1]; - wxVariant vx; + // save the native (MSW) event parameters for event handlers that need to access them + // this can be done on the stack since wxActiveXEvent is also allocated on the stack + wxActiveXEventNativeMSW eventParameters(dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); + event.SetClientData(&eventParameters); -// vx.SetName(px.name); - wxConvertOleToVariant(va, vx); - event.m_params.Append(vx); - } - } + // The event parameters are not copied to event.m_params until they are actually + // referenced in wxActiveXEvent::operator[] + // This increases performance and avoids error messages and/or crashes + // when the event has parameters that are not (yet or never) supported + // by wxConvertOleToVariant // process the events from the activex method - m_activeX->ProcessEvent(event); + m_activeX->ProcessEvent(event); for (DWORD i = 0; i < pDispParams->cArgs; i++) { - VARIANTARG& va = pDispParams->rgvarg[i]; - wxVariant& vx = - event.m_params[pDispParams->cArgs - i - 1]; - wxConvertVariantToOle(vx, va); + size_t params_index = pDispParams->cArgs - i - 1; + if (params_index < event.m_params.GetCount()) { + wxVariant &vx = event.m_params[params_index]; + // copy the result back to pDispParams only if the event has been accessed + // i.e. if vx != ms_invalidEntryMarker + if (!vx.IsType(wxActiveXEvents::ms_invalidEntryMarker.GetType()) || vx!=ms_invalidEntryMarker) { + VARIANTARG& va = pDispParams->rgvarg[i]; + wxConvertVariantToOle(vx, va); + } + } } if(event.GetSkipped()) @@ -763,15 +780,65 @@ public: } }; +namespace +{ +// just a unique global variable +const int invalid_entry_marker = 0; +} + +wxVariant wxActiveXEvents::ms_invalidEntryMarker((void*)&invalid_entry_marker); + +size_t wxActiveXEvent::ParamCount() const +{ + wxActiveXEventNativeMSW *native=GetNativeParameters(); + // 'native' will always be != if the event has been created + // for an actual active X event. + // But it may be zero if the event has been created by wx program code. + if (native) + return native->pDispParams ? native->pDispParams->cArgs : 0; + + return m_params.GetCount(); +} + +wxVariant &wxActiveXEvent::operator [](size_t idx) +{ + wxASSERT(idx < ParamCount()); + wxActiveXEventNativeMSW *native=GetNativeParameters(); + // 'native' will always be != if the event has been created + // for an actual active X event. + // But it may be zero if the event has been created by wx program code. + if (native) + { + while ( m_params.GetCount()<=idx ) + { + m_params.Append(wxActiveXEvents::ms_invalidEntryMarker); + } + + wxVariant& vx = m_params[idx]; + if ( vx.IsType(wxActiveXEvents::ms_invalidEntryMarker.GetType()) && + vx == wxActiveXEvents::ms_invalidEntryMarker) + { + // copy the _real_ parameter into this one + // NOTE: m_params stores the parameters in *reverse* order. + // Whyever, but this was the case in the original implementation of + // wxActiveXEvents::Invoke + // Keep this convention. + VARIANTARG& va = native->pDispParams->rgvarg[ native->pDispParams->cArgs - idx - 1 ]; + wxConvertOleToVariant(va, vx); + } + return vx; + } + return m_params[idx]; +} + bool wxActiveXEventsInterface(wxActiveXEvents *self, REFIID iid, void **_interface, const char *&desc) { if (self->m_haveCustomId && IsEqualIID(iid, self->m_customId)) { -// WXOLE_TRACE("Found Custom Dispatch Interface"); *_interface = (IUnknown *) (IDispatch *) self; desc = "Custom Dispatch Interface"; return true; - }; + } return false; } @@ -780,7 +847,7 @@ DEFINE_OLE_TABLE(wxActiveXEvents) OLE_IINTERFACE(IUnknown) OLE_INTERFACE(IID_IDispatch, IDispatch) OLE_INTERFACE_CUSTOM(wxActiveXEventsInterface) -END_OLE_TABLE; +END_OLE_TABLE //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // @@ -827,8 +894,24 @@ wxActiveXContainer::~wxActiveXContainer() m_oleObject->Close(OLECLOSE_NOSAVE); m_oleObject->SetClientSite(NULL); } + + // m_clientSite uses m_frameSite so destroy it first + m_clientSite.Free(); + delete m_frameSite; + + // our window doesn't belong to us, don't destroy it + m_hWnd = NULL; } +// VZ: we might want to really report an error instead of just asserting here +#if wxDEBUG_LEVEL + #define CHECK_HR(hr) \ + wxASSERT_LEVEL_2_MSG( SUCCEEDED(hr), \ + wxString::Format("HRESULT = %X", (unsigned)(hr)) ) +#else + #define CHECK_HR(hr) wxUnusedVar(hr) +#endif + //--------------------------------------------------------------------------- // wxActiveXContainer::CreateActiveX // @@ -841,20 +924,21 @@ void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk) { HRESULT hret; hret = m_ActiveX.QueryInterface(iid, pUnk); - wxASSERT(SUCCEEDED(hret)); + CHECK_HR(hret); // FrameSite - FrameSite *frame = new FrameSite(m_realparent, this); + m_frameSite = new FrameSite(m_realparent, this); // oleClientSite hret = m_clientSite.QueryInterface( - IID_IOleClientSite, (IDispatch *) frame); - wxASSERT(SUCCEEDED(hret)); + IID_IOleClientSite, (IDispatch *) m_frameSite); + CHECK_HR(hret); // adviseSink - wxAutoIAdviseSink adviseSink(IID_IAdviseSink, (IDispatch *) frame); + wxAutoIAdviseSink adviseSink(IID_IAdviseSink, (IDispatch *) m_frameSite); wxASSERT(adviseSink.Ok()); // Get Dispatch interface hret = m_Dispatch.QueryInterface(IID_IDispatch, m_ActiveX); + CHECK_HR(hret); // // SETUP TYPEINFO AND ACTIVEX EVENTS @@ -867,12 +951,13 @@ void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk) // type info wxAutoITypeInfo typeInfo; hret = classInfo->GetClassInfo(typeInfo.GetRef()); + CHECK_HR(hret); wxASSERT(typeInfo.Ok()); // TYPEATTR TYPEATTR *ta = NULL; hret = typeInfo->GetTypeAttr(&ta); - wxASSERT(ta); + CHECK_HR(hret); // this should be a TKIND_COCLASS wxASSERT(ta->typekind == TKIND_COCLASS); @@ -893,8 +978,9 @@ void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk) if (! ti.Ok()) continue; + CHECK_HR(hret); + // check if default event sink - bool defInterface = false; bool defEventSink = false; int impTypeFlags = 0; typeInfo->GetImplTypeFlags(i, &impTypeFlags); @@ -912,11 +998,6 @@ void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk) wxFAIL_MSG(wxT("Default event sink is in vtable!")); } } - else - { - // WXOLE_TRACEOUT("Default Interface"); - defInterface = true; - } } @@ -924,7 +1005,7 @@ void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk) // TYPEATTR TYPEATTR *ta = NULL; hret = ti->GetTypeAttr(&ta); - wxASSERT(ta); + CHECK_HR(hret); if (ta->typekind == TKIND_DISPATCH) { @@ -939,15 +1020,13 @@ void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk) HRESULT hret = cpContainer->FindConnectionPoint(ta->guid, cp.GetRef()); - wxASSERT ( SUCCEEDED(hret)); + CHECK_HR(hret); IDispatch* disp; - frame->QueryInterface(IID_IDispatch, (void**)&disp); + m_frameSite->QueryInterface(IID_IDispatch, (void**)&disp); hret = cp->Advise(new wxActiveXEvents(this, ta->guid), &adviseCookie); - wxASSERT_MSG( SUCCEEDED(hret), - wxString::Format(wxT("Cannot connect!\nHRESULT:%X"), hret) - ); + CHECK_HR(hret); } } @@ -963,15 +1042,17 @@ void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk) // Get IOleObject interface hret = m_oleObject.QueryInterface(IID_IOleObject, m_ActiveX); - wxASSERT(SUCCEEDED(hret)); + CHECK_HR(hret); // get IViewObject Interface hret = m_viewObject.QueryInterface(IID_IViewObject, m_ActiveX); - wxASSERT(SUCCEEDED(hret)); + CHECK_HR(hret); // document advise m_docAdviseCookie = 0; hret = m_oleObject->Advise(adviseSink, &m_docAdviseCookie); + CHECK_HR(hret); + // TODO:Needed? // hret = m_viewObject->SetAdvise(DVASPECT_CONTENT, 0, adviseSink); m_oleObject->SetHostNames(L"wxActiveXContainer", NULL); @@ -982,12 +1063,12 @@ void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk) // Get IOleInPlaceObject interface hret = m_oleInPlaceObject.QueryInterface( IID_IOleInPlaceObject, m_ActiveX); - wxASSERT(SUCCEEDED(hret)); + CHECK_HR(hret); // status DWORD dwMiscStatus; m_oleObject->GetMiscStatus(DVASPECT_CONTENT, &dwMiscStatus); - wxASSERT(SUCCEEDED(hret)); + CHECK_HR(hret); // set client site first ? if (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST) @@ -1001,15 +1082,13 @@ void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk) if (pPersistStreamInit.Ok()) { hret = pPersistStreamInit->InitNew(); + CHECK_HR(hret); } if (! (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)) m_oleObject->SetClientSite(m_clientSite); - RECT posRect; - ::GetClientRect((HWND)m_realparent->GetHWND(), &posRect); - m_oleObjectHWND = 0; if (m_oleInPlaceObject.Ok()) @@ -1022,19 +1101,28 @@ void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk) if (! (dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME)) { + RECT posRect; + wxCopyRectToRECT(m_realparent->GetClientSize(), posRect); + if (posRect.right > 0 && posRect.bottom > 0 && m_oleInPlaceObject.Ok()) - m_oleInPlaceObject->SetObjectRects(&posRect, &posRect); + { + m_oleInPlaceObject->SetObjectRects(&posRect, &posRect); + } hret = m_oleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, m_clientSite, 0, (HWND)m_realparent->GetHWND(), &posRect); + CHECK_HR(hret); + hret = m_oleObject->DoVerb(OLEIVERB_SHOW, 0, m_clientSite, 0, (HWND)m_realparent->GetHWND(), &posRect); + CHECK_HR(hret); } if (! m_oleObjectHWND && m_oleInPlaceObject.Ok()) { hret = m_oleInPlaceObject->GetWindow(&m_oleObjectHWND); + CHECK_HR(hret); } if (m_oleObjectHWND) @@ -1123,10 +1211,15 @@ void wxActiveXContainer::OnPaint(wxPaintEvent& WXUNUSED(event)) posRect.right = w; posRect.bottom = h; +#if !(defined(_WIN32_WCE) && _WIN32_WCE < 400) ::RedrawWindow(m_oleObjectHWND, NULL, NULL, RDW_INTERNALPAINT); +#else + ::InvalidateRect(m_oleObjectHWND, NULL, false); +#endif RECTL *prcBounds = (RECTL *) &posRect; + wxMSWDCImpl *msw = wxDynamicCast( dc.GetImpl() , wxMSWDCImpl ); m_viewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL, - (HDC)dc.GetHDC(), prcBounds, NULL, NULL, 0); + (HDC)msw->GetHDC(), prcBounds, NULL, NULL, 0); } } @@ -1157,5 +1250,4 @@ void wxActiveXContainer::OnKillFocus(wxFocusEvent& event) event.Skip(); } -#endif -// __WINE__ +#endif // wxUSE_ACTIVEX