X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/bf354396f61a2e1bd5544b67ecde341b6ff9bf35..eea4d01c65f9b29baa1193db762b4c6b8144af24:/src/msw/ole/activex.cpp diff --git a/src/msw/ole/activex.cpp b/src/msw/ole/activex.cpp index 8dea8ef980..8a08625124 100644 --- a/src/msw/ole/activex.cpp +++ b/src/msw/ole/activex.cpp @@ -1,41 +1,60 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: msw/ole/activex.cpp +// Name: src/msw/ole/activex.cpp // Purpose: wxActiveXContainer implementation // Author: Ryan Norton , Lindsay Mathieson -// Modified by: +// Modified by: // Created: 11/07/04 // RCS-ID: $Id$ // Copyright: (c) 2003 Lindsay Mathieson, (c) 2005 Ryan Norton // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -//=========================================================================== -// DECLARATIONS -//=========================================================================== +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- -//--------------------------------------------------------------------------- -// WX include -//--------------------------------------------------------------------------- #include "wx/wxprec.h" -#include "wx/msw/ole/activex.h" +#ifdef __BORLANDC__ + #pragma hdrstop +#endif +#if wxUSE_ACTIVEX +#ifndef WX_PRECOMP + #include "wx/dcclient.h" + #include "wx/math.h" +#endif +#include "wx/msw/dc.h" -//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -// -// wxActiveXContainer -// -//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +#include "wx/msw/ole/activex.h" +#include "wx/msw/private.h" // for wxCopyRectToRECT + +// autointerfaces that we only use here +typedef wxAutoOleInterface wxAutoIOleInPlaceSite; +typedef wxAutoOleInterface wxAutoIOleDocument; +typedef wxAutoOleInterface wxAutoIPersistStreamInit; +typedef wxAutoOleInterface wxAutoIAdviseSink; +typedef wxAutoOleInterface wxAutoIProvideClassInfo; +typedef wxAutoOleInterface wxAutoITypeInfo; +typedef wxAutoOleInterface wxAutoIConnectionPoint; +typedef wxAutoOleInterface wxAutoIConnectionPointContainer; + +wxDEFINE_EVENT( wxEVT_ACTIVEX, wxActiveXEvent ); +// Ole class helpers (sort of MFC-like) from wxActiveX #define DECLARE_OLE_UNKNOWN(cls)\ private:\ class TAutoInitInt\ {\ public:\ LONG l;\ - TAutoInitInt() : l(0) {}\ + TAutoInitInt() : l(1) {}\ };\ TAutoInitInt refCount, lockCount;\ static void _GetInterface(cls *self, REFIID iid, void **_interface, const char *&desc);\ @@ -54,21 +73,21 @@ 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)\ @@ -78,7 +97,7 @@ {\ delete this;\ return 0;\ - };\ + }\ return refCount.l;\ }\ else\ @@ -88,7 +107,7 @@ {\ InterlockedIncrement(&lockCount.l);\ return lockCount.l;\ - };\ + }\ ULONG STDMETHODCALLTYPE cls::ReleaseLock()\ {\ if (lockCount.l > 0)\ @@ -126,7 +145,52 @@ #define END_OLE_TABLE\ } +// ============================================================================ +// implementation +// ============================================================================ + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// PixelsToHimetric +// +// Utility to convert from pixels to the himetric values in some COM methods +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + +#define HIMETRIC_PER_INCH 2540 +#define MAP_PIX_TO_LOGHIM(x,ppli) MulDiv(HIMETRIC_PER_INCH, (x), (ppli)) + +static void PixelsToHimetric(SIZEL &sz) +{ + static int logX = 0; + static int logY = 0; + + if (logY == 0) + { + // initaliase + HDC dc = GetDC(NULL); + logX = GetDeviceCaps(dc, LOGPIXELSX); + logY = GetDeviceCaps(dc, LOGPIXELSY); + ReleaseDC(NULL, dc); + }; + +#define HIMETRIC_INCH 2540 +#define CONVERT(x, logpixels) wxMulDivInt32(HIMETRIC_INCH, (x), (logpixels)) + + sz.cx = CONVERT(sz.cx, logX); + sz.cy = CONVERT(sz.cy, logY); + +#undef CONVERT +#undef HIMETRIC_INCH +} + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// FrameSite +// +// Handles the actual wxActiveX container implementation +// +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ class FrameSite : public IOleClientSite, public IOleInPlaceSiteEx, @@ -290,7 +354,7 @@ public: HRESULT STDMETHODCALLTYPE TranslateAccelerator(LPMSG lpmsg, WORD) { // TODO: send an event with this id - if (m_window->m_oleInPlaceActiveObject.Ok()) + if (m_window->m_oleInPlaceActiveObject.IsOk()) m_window->m_oleInPlaceActiveObject->TranslateAccelerator(lpmsg); return S_FALSE; } @@ -321,7 +385,7 @@ public: if (! SUCCEEDED(hr)) { return E_UNEXPECTED; - }; + } hr = QueryInterface(IID_IOleInPlaceUIWindow, (void **) ppDoc); if (! SUCCEEDED(hr)) @@ -329,7 +393,7 @@ public: (*ppFrame)->Release(); *ppFrame = NULL; return E_UNEXPECTED; - }; + } RECT rect; ::GetClientRect(m_hWndParent, &rect); @@ -338,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); @@ -361,17 +425,37 @@ public: HRESULT STDMETHODCALLTYPE DeactivateAndUndo(){return S_OK; } HRESULT STDMETHODCALLTYPE OnPosRectChange(LPCRECT lprcPosRect) { - if (m_window->m_oleInPlaceObject.Ok() && lprcPosRect) + if (m_window->m_oleInPlaceObject.IsOk() && lprcPosRect) { + // + // Result of several hours and days of bug hunting - + // this is called by an object when it wants to resize + // itself to something different then our parent window - + // don't let it :) + // +// m_window->m_oleInPlaceObject->SetObjectRects( +// lprcPosRect, lprcPosRect); + RECT rcClient; + ::GetClientRect(m_hWndParent, &rcClient); m_window->m_oleInPlaceObject->SetObjectRects( - lprcPosRect, lprcPosRect); + &rcClient, &rcClient); } return S_OK; } //*************************IOleInPlaceSiteEx*********************** HRESULT STDMETHODCALLTYPE OnInPlaceActivateEx(BOOL * pfNoRedraw, DWORD) { +#ifdef __WXWINCE__ + IRunnableObject* runnable = NULL; + HRESULT hr = QueryInterface( + IID_IRunnableObject, (void**)(& runnable)); + if (SUCCEEDED(hr)) + { + runnable->LockRunning(TRUE, FALSE); + } +#else OleLockRunning(m_window->m_ActiveX, TRUE, FALSE); +#endif if (pfNoRedraw) (*pfNoRedraw) = FALSE; return S_OK; @@ -379,7 +463,17 @@ public: HRESULT STDMETHODCALLTYPE OnInPlaceDeactivateEx(BOOL) { +#ifdef __WXWINCE__ + IRunnableObject* runnable = NULL; + HRESULT hr = QueryInterface( + IID_IRunnableObject, (void**)(& runnable)); + if (SUCCEEDED(hr)) + { + runnable->LockRunning(FALSE, FALSE); + } +#else OleLockRunning(m_window->m_ActiveX, FALSE, FALSE); +#endif return S_OK; } STDMETHOD(RequestUIActivate)(){ return S_OK;} @@ -394,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) { @@ -405,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) { @@ -433,7 +527,9 @@ public: HRESULT STDMETHODCALLTYPE LockContainer(BOOL){return S_OK;} //********************IOleItemContainer*************************** HRESULT STDMETHODCALLTYPE - #ifdef _UNICODE + #if 0 // defined(__WXWINCE__) && __VISUALC__ < 1400 + GetObject + #elif defined(_UNICODE) GetObjectW #else GetObjectA @@ -510,7 +606,7 @@ public: { wxAutoIOleInPlaceSite inPlaceSite( IID_IOleInPlaceSite, (IDispatch *) this); - if (!inPlaceSite.Ok()) + if (!inPlaceSite.IsOk()) return E_FAIL; if (pViewToActivate) @@ -522,7 +618,7 @@ public: { wxAutoIOleDocument oleDoc( IID_IOleDocument, m_window->m_oleObject); - if (! oleDoc.Ok()) + if (! oleDoc.IsOk()) return E_FAIL; HRESULT hr = oleDoc->CreateView(inPlaceSite, NULL, @@ -531,11 +627,11 @@ public: return E_FAIL; m_window->m_docView->SetInPlaceSite(inPlaceSite); - }; + } m_window->m_docView->UIActivate(TRUE); return S_OK; - }; + } protected: @@ -574,10 +670,198 @@ DEFINE_OLE_TABLE(FrameSite) OLE_IINTERFACE(IOleDocumentSite) OLE_IINTERFACE(IAdviseSink) OLE_IINTERFACE(IOleControlSite) -END_OLE_TABLE; +END_OLE_TABLE + + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// wxActiveXEvents +// +// Handles and sends activex events received from the ActiveX control +// to the appropriate wxEvtHandler +// +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +class wxActiveXEvents : public IDispatch +{ +private: + DECLARE_OLE_UNKNOWN(wxActiveXEvents); + + + wxActiveXContainer *m_activeX; + IID m_customId; + bool m_haveCustomId; + + 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_customId(iid), m_haveCustomId(true) {} + virtual ~wxActiveXEvents() + { + } + + // IDispatch + STDMETHODIMP GetIDsOfNames(REFIID, OLECHAR**, unsigned int, LCID, DISPID*) + { + return E_NOTIMPL; + } + + STDMETHODIMP GetTypeInfo(unsigned int, LCID, ITypeInfo**) + { + return E_NOTIMPL; + } + + STDMETHODIMP GetTypeInfoCount(unsigned int*) + { + return E_NOTIMPL; + } + + + STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, + LCID lcid, + WORD wFlags, DISPPARAMS * pDispParams, + VARIANT * pVarResult, EXCEPINFO * pExcepInfo, + unsigned int * puArgErr) + { + if (wFlags & (DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF)) + return E_NOTIMPL; + + wxASSERT(m_activeX); + + // ActiveX Event + + // 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; + + // 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); + + // 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); + for (DWORD i = 0; i < pDispParams->cArgs; i++) + { + 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()) + return DISP_E_MEMBERNOTFOUND; + + return S_OK; + } +}; + +namespace +{ +// just a unique global variable +const int invalid_entry_marker = 0; +} +wxVariant wxActiveXEvents::ms_invalidEntryMarker((void*)&invalid_entry_marker); -wxActiveXContainer::wxActiveXContainer(wxWindow * parent, REFIID iid, IUnknown* pUnk) +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)) + { + *_interface = (IUnknown *) (IDispatch *) self; + desc = "Custom Dispatch Interface"; + return true; + } + + return false; +} + +DEFINE_OLE_TABLE(wxActiveXEvents) + OLE_IINTERFACE(IUnknown) + OLE_INTERFACE(IID_IDispatch, IDispatch) + OLE_INTERFACE_CUSTOM(wxActiveXEventsInterface) +END_OLE_TABLE + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// wxActiveXContainer +// +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +//--------------------------------------------------------------------------- +// wxActiveXContainer Constructor +// +// Initializes members and creates the native ActiveX container +//--------------------------------------------------------------------------- +wxActiveXContainer::wxActiveXContainer(wxWindow * parent, + REFIID iid, IUnknown* pUnk) : m_realparent(parent) { m_bAmbientUserMode = true; @@ -585,16 +869,22 @@ wxActiveXContainer::wxActiveXContainer(wxWindow * parent, REFIID iid, IUnknown* CreateActiveX(iid, pUnk); } +//--------------------------------------------------------------------------- +// wxActiveXContainer Destructor +// +// Destroys members (the FrameSite et al. are destroyed implicitly +// through COM ref counting) +//--------------------------------------------------------------------------- wxActiveXContainer::~wxActiveXContainer() { // disconnect connection points - if (m_oleInPlaceObject.Ok()) + if (m_oleInPlaceObject.IsOk()) { m_oleInPlaceObject->InPlaceDeactivate(); m_oleInPlaceObject->UIDeactivate(); } - if (m_oleObject.Ok()) + if (m_oleObject.IsOk()) { if (m_docAdviseCookie != 0) m_oleObject->Unadvise(m_docAdviseCookie); @@ -604,38 +894,181 @@ 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 +// +// Actually creates the ActiveX container through the FrameSite +// and sets up ActiveX events +// +// TODO: Document this more +//--------------------------------------------------------------------------- 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); - wxASSERT(adviseSink.Ok()); + wxAutoIAdviseSink adviseSink(IID_IAdviseSink, (IDispatch *) m_frameSite); + wxASSERT(adviseSink.IsOk()); // Get Dispatch interface hret = m_Dispatch.QueryInterface(IID_IDispatch, m_ActiveX); + CHECK_HR(hret); + + // + // SETUP TYPEINFO AND ACTIVEX EVENTS + // + + // get type info via class info + wxAutoIProvideClassInfo classInfo(IID_IProvideClassInfo, m_ActiveX); + wxASSERT(classInfo.IsOk()); + + // type info + wxAutoITypeInfo typeInfo; + hret = classInfo->GetClassInfo(typeInfo.GetRef()); + CHECK_HR(hret); + wxASSERT(typeInfo.IsOk()); + + // TYPEATTR + TYPEATTR *ta = NULL; + hret = typeInfo->GetTypeAttr(&ta); + CHECK_HR(hret); + + // this should be a TKIND_COCLASS + wxASSERT(ta->typekind == TKIND_COCLASS); + + // iterate contained interfaces + for (int i = 0; i < ta->cImplTypes; i++) + { + HREFTYPE rt = 0; + + // get dispatch type info handle + hret = typeInfo->GetRefTypeOfImplType(i, &rt); + if (! SUCCEEDED(hret)) + continue; + + // get dispatch type info interface + wxAutoITypeInfo ti; + hret = typeInfo->GetRefTypeInfo(rt, ti.GetRef()); + if (! ti.IsOk()) + continue; + + CHECK_HR(hret); + + // check if default event sink + bool defEventSink = false; + int impTypeFlags = 0; + typeInfo->GetImplTypeFlags(i, &impTypeFlags); + + if (impTypeFlags & IMPLTYPEFLAG_FDEFAULT) + { + if (impTypeFlags & IMPLTYPEFLAG_FSOURCE) + { + // WXOLE_TRACEOUT("Default Event Sink"); + defEventSink = true; + if (impTypeFlags & IMPLTYPEFLAG_FDEFAULTVTABLE) + { + // WXOLE_TRACEOUT("*ERROR* - Default Event Sink is via vTable"); + defEventSink = false; + wxFAIL_MSG(wxT("Default event sink is in vtable!")); + } + } + } + + + // wxAutoOleInterface<> assumes a ref has already been added + // TYPEATTR + TYPEATTR *ta = NULL; + hret = ti->GetTypeAttr(&ta); + CHECK_HR(hret); + + if (ta->typekind == TKIND_DISPATCH) + { + // WXOLE_TRACEOUT("GUID = " << GetIIDName(ta->guid).c_str()); + if (defEventSink) + { + wxAutoIConnectionPoint cp; + DWORD adviseCookie = 0; + + wxAutoIConnectionPointContainer cpContainer(IID_IConnectionPointContainer, m_ActiveX); + wxASSERT( cpContainer.IsOk()); + + HRESULT hret = + cpContainer->FindConnectionPoint(ta->guid, cp.GetRef()); + + // Notice that the return value of CONNECT_E_NOCONNECTION is + // expected if the interface doesn't support connection points. + if ( hret != CONNECT_E_NOCONNECTION ) + { + CHECK_HR(hret); + } + + if ( cp ) + { + wxActiveXEvents * const + events = new wxActiveXEvents(this, ta->guid); + hret = cp->Advise(events, &adviseCookie); + + // We don't need this object any more and cp will keep a + // reference to it if it needs it, i.e. if Advise() + // succeeded. + events->Release(); + + CHECK_HR(hret); + } + } + } + + ti->ReleaseTypeAttr(ta); + } + + // free + typeInfo->ReleaseTypeAttr(ta); + + // + // END + // // 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); OleSetContainedObject(m_oleObject, TRUE); OleRun(m_oleObject); @@ -644,12 +1077,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) @@ -660,21 +1093,19 @@ void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk) wxAutoIPersistStreamInit pPersistStreamInit(IID_IPersistStreamInit, m_oleObject); - if (pPersistStreamInit.Ok()) + if (pPersistStreamInit.IsOk()) { 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()) + if (m_oleInPlaceObject.IsOk()) { hret = m_oleInPlaceObject->GetWindow(&m_oleObjectHWND); if (SUCCEEDED(hret)) @@ -684,19 +1115,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.IsOk()) + { + 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()) + if (! m_oleObjectHWND && m_oleInPlaceObject.IsOk()) { hret = m_oleInPlaceObject->GetWindow(&m_oleObjectHWND); + CHECK_HR(hret); } if (m_oleObjectHWND) @@ -712,6 +1152,8 @@ void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk) pWnd->Connect(id, wxEVT_SIZE, wxSizeEventHandler(wxActiveXContainer::OnSize), 0, this); +// this->Connect(GetId(), wxEVT_PAINT, +// wxPaintEventHandler(wxActiveXContainer::OnPaint), 0, this); pWnd->Connect(id, wxEVT_SET_FOCUS, wxFocusEventHandler(wxActiveXContainer::OnSetFocus), 0, this); pWnd->Connect(id, wxEVT_KILL_FOCUS, @@ -719,34 +1161,12 @@ void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk) } } -#define HIMETRIC_PER_INCH 2540 -#define MAP_PIX_TO_LOGHIM(x,ppli) MulDiv(HIMETRIC_PER_INCH, (x), (ppli)) - -static void PixelsToHimetric(SIZEL &sz) -{ - static int logX = 0; - static int logY = 0; - - if (logY == 0) - { - // initaliase - HDC dc = GetDC(NULL); - logX = GetDeviceCaps(dc, LOGPIXELSX); - logY = GetDeviceCaps(dc, LOGPIXELSY); - ReleaseDC(NULL, dc); - }; - -#define HIMETRIC_INCH 2540 -#define CONVERT(x, logpixels) MulDiv(HIMETRIC_INCH, (x), (logpixels)) - - sz.cx = CONVERT(sz.cx, logX); - sz.cy = CONVERT(sz.cy, logY); - -#undef CONVERT -#undef HIMETRIC_INCH -} - - +//--------------------------------------------------------------------------- +// wxActiveXContainer::OnSize +// +// Called when the parent is resized - we need to do this to actually +// move the ActiveX control to where the parent is +//--------------------------------------------------------------------------- void wxActiveXContainer::OnSize(wxSizeEvent& event) { int w, h; @@ -762,8 +1182,11 @@ void wxActiveXContainer::OnSize(wxSizeEvent& event) return; // extents are in HIMETRIC units - if (m_oleObject.Ok()) + if (m_oleObject.IsOk()) { + m_oleObject->DoVerb(OLEIVERB_HIDE, 0, m_clientSite, 0, + (HWND)m_realparent->GetHWND(), &posRect); + SIZEL sz = {w, h}; PixelsToHimetric(sz); @@ -772,21 +1195,28 @@ void wxActiveXContainer::OnSize(wxSizeEvent& event) m_oleObject->GetExtent(DVASPECT_CONTENT, &sz2); if (sz2.cx != sz.cx || sz.cy != sz2.cy) m_oleObject->SetExtent(DVASPECT_CONTENT, &sz); - }; - if (m_oleInPlaceObject.Ok()) + m_oleObject->DoVerb(OLEIVERB_SHOW, 0, m_clientSite, 0, + (HWND)m_realparent->GetHWND(), &posRect); + } + + if (m_oleInPlaceObject.IsOk()) m_oleInPlaceObject->SetObjectRects(&posRect, &posRect); event.Skip(); } +//--------------------------------------------------------------------------- +// wxActiveXContainer::OnPaint +// +// Called when the parent is resized - repaints the ActiveX control +//--------------------------------------------------------------------------- void wxActiveXContainer::OnPaint(wxPaintEvent& WXUNUSED(event)) { wxPaintDC dc(this); // Draw only when control is windowless or deactivated if (m_viewObject) { - dc.BeginDrawing(); int w, h; GetParent()->GetSize(&w, &h); RECT posRect; @@ -795,30 +1225,43 @@ 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); - - dc.EndDrawing(); + (HDC)msw->GetHDC(), prcBounds, NULL, NULL, 0); } - -// We've got this one I think -// event.Skip(); } +//--------------------------------------------------------------------------- +// wxActiveXContainer::OnSetFocus +// +// Called when the focus is set on the parent - activates the activex control +//--------------------------------------------------------------------------- void wxActiveXContainer::OnSetFocus(wxFocusEvent& event) { - if (m_oleInPlaceActiveObject.Ok()) + if (m_oleInPlaceActiveObject.IsOk()) m_oleInPlaceActiveObject->OnFrameWindowActivate(TRUE); event.Skip(); } +//--------------------------------------------------------------------------- +// wxActiveXContainer::OnKillFocus +// +// Called when the focus is killed on the parent - +// deactivates the activex control +//--------------------------------------------------------------------------- void wxActiveXContainer::OnKillFocus(wxFocusEvent& event) { - if (m_oleInPlaceActiveObject.Ok()) + if (m_oleInPlaceActiveObject.IsOk()) m_oleInPlaceActiveObject->OnFrameWindowActivate(FALSE); event.Skip(); } + +#endif // wxUSE_ACTIVEX