]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/ole/activex.cpp
Ensure there is valid context for DrawRectangle
[wxWidgets.git] / src / msw / ole / activex.cpp
index d1722eeb64bca85879a42e643b4533a6da9a6b5b..8baad0bf012bcab308717ca737bbd20810d29271 100644 (file)
     #pragma hdrstop
 #endif
 
     #pragma hdrstop
 #endif
 
-#include "wx/dcclient.h"
-#include "wx/math.h"
+#if wxUSE_ACTIVEX
+
+#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/ole/activex.h"
+#include "wx/msw/private.h" // for wxCopyRectToRECT
 
 
+// autointerfaces that we only use here
+typedef wxAutoOleInterface<IOleInPlaceSite> wxAutoIOleInPlaceSite;
+typedef wxAutoOleInterface<IOleDocument> wxAutoIOleDocument;
+typedef wxAutoOleInterface<IPersistStreamInit> wxAutoIPersistStreamInit;
+typedef wxAutoOleInterface<IAdviseSink> wxAutoIAdviseSink;
+typedef wxAutoOleInterface<IProvideClassInfo> wxAutoIProvideClassInfo;
+typedef wxAutoOleInterface<ITypeInfo> wxAutoITypeInfo;
+typedef wxAutoOleInterface<IConnectionPoint> wxAutoIConnectionPoint;
+typedef wxAutoOleInterface<IConnectionPointContainer> wxAutoIConnectionPointContainer;
 
 
-//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-//
-// wxActiveXContainer
-//
-//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+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;\
 #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);\
     };\
     TAutoInitInt refCount, lockCount;\
     static void _GetInterface(cls *self, REFIID iid, void **_interface, const char *&desc);\
 #define END_OLE_TABLE\
     }
 
 #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,
 class FrameSite :
     public IOleClientSite,
     public IOleInPlaceSiteEx,
@@ -207,7 +266,7 @@ public:
             case DISPID_AMBIENT_SILENT:
                 V_BOOL(pVarResult)= TRUE;
                 return S_OK;
             case DISPID_AMBIENT_SILENT:
                 V_BOOL(pVarResult)= TRUE;
                 return S_OK;
-#ifndef __WINE__
+
             case DISPID_AMBIENT_APPEARANCE:
                 pVarResult->vt = VT_BOOL;
                 pVarResult->boolVal = m_bAmbientAppearance;
             case DISPID_AMBIENT_APPEARANCE:
                 pVarResult->vt = VT_BOOL;
                 pVarResult->boolVal = m_bAmbientAppearance;
@@ -242,7 +301,7 @@ public:
                 pVarResult->vt = VT_BOOL;
                 pVarResult->boolVal = m_bAmbientShowHatching;
                 break;
                 pVarResult->vt = VT_BOOL;
                 pVarResult->boolVal = m_bAmbientShowHatching;
                 break;
-#endif
+
             default:
                 return DISP_E_MEMBERNOTFOUND;
         }
             default:
                 return DISP_E_MEMBERNOTFOUND;
         }
@@ -295,7 +354,7 @@ public:
     HRESULT STDMETHODCALLTYPE TranslateAccelerator(LPMSG lpmsg, WORD)
     {
         // TODO: send an event with this id
     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;
     }
             m_window->m_oleInPlaceActiveObject->TranslateAccelerator(lpmsg);
         return S_FALSE;
     }
@@ -366,17 +425,37 @@ public:
     HRESULT STDMETHODCALLTYPE DeactivateAndUndo(){return S_OK; }
     HRESULT STDMETHODCALLTYPE OnPosRectChange(LPCRECT lprcPosRect)
     {
     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(
             m_window->m_oleInPlaceObject->SetObjectRects(
-                lprcPosRect, lprcPosRect);
+                &rcClient, &rcClient);
         }
         return S_OK;
     }
     //*************************IOleInPlaceSiteEx***********************
     HRESULT STDMETHODCALLTYPE OnInPlaceActivateEx(BOOL * pfNoRedraw, DWORD)
     {
         }
         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);
         OleLockRunning(m_window->m_ActiveX, TRUE, FALSE);
+#endif
         if (pfNoRedraw)
             (*pfNoRedraw) = FALSE;
         return S_OK;
         if (pfNoRedraw)
             (*pfNoRedraw) = FALSE;
         return S_OK;
@@ -384,7 +463,17 @@ public:
 
     HRESULT STDMETHODCALLTYPE OnInPlaceDeactivateEx(BOOL)
     {
 
     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);
         OleLockRunning(m_window->m_ActiveX, FALSE, FALSE);
+#endif
         return S_OK;
     }
     STDMETHOD(RequestUIActivate)(){ return S_OK;}
         return S_OK;
     }
     STDMETHOD(RequestUIActivate)(){ return S_OK;}
@@ -438,7 +527,7 @@ public:
     HRESULT STDMETHODCALLTYPE LockContainer(BOOL){return S_OK;}
     //********************IOleItemContainer***************************
     HRESULT STDMETHODCALLTYPE
     HRESULT STDMETHODCALLTYPE LockContainer(BOOL){return S_OK;}
     //********************IOleItemContainer***************************
     HRESULT STDMETHODCALLTYPE
-    #if defined(__WXWINCE__)
+    #if 0 // defined(__WXWINCE__) && __VISUALC__ < 1400
     GetObject
     #elif defined(_UNICODE)
     GetObjectW
     GetObject
     #elif defined(_UNICODE)
     GetObjectW
@@ -517,7 +606,7 @@ public:
     {
         wxAutoIOleInPlaceSite inPlaceSite(
             IID_IOleInPlaceSite, (IDispatch *) this);
     {
         wxAutoIOleInPlaceSite inPlaceSite(
             IID_IOleInPlaceSite, (IDispatch *) this);
-        if (!inPlaceSite.Ok())
+        if (!inPlaceSite.IsOk())
             return E_FAIL;
 
         if (pViewToActivate)
             return E_FAIL;
 
         if (pViewToActivate)
@@ -529,7 +618,7 @@ public:
         {
             wxAutoIOleDocument oleDoc(
                 IID_IOleDocument, m_window->m_oleObject);
         {
             wxAutoIOleDocument oleDoc(
                 IID_IOleDocument, m_window->m_oleObject);
-            if (! oleDoc.Ok())
+            if (! oleDoc.IsOk())
                 return E_FAIL;
 
             HRESULT hr = oleDoc->CreateView(inPlaceSite, NULL,
                 return E_FAIL;
 
             HRESULT hr = oleDoc->CreateView(inPlaceSite, NULL,
@@ -544,6 +633,10 @@ public:
         return S_OK;
     }
 
         return S_OK;
     }
 
+    friend bool QueryClientSiteInterface(FrameSite *self, REFIID iid, void **_interface, const char *&desc)
+    {
+        return self->m_window->QueryClientSiteInterface(iid,_interface,desc);
+    }
 
 protected:
     wxActiveXContainer * m_window;
 
 protected:
     wxActiveXContainer * m_window;
@@ -581,10 +674,199 @@ DEFINE_OLE_TABLE(FrameSite)
     OLE_IINTERFACE(IOleDocumentSite)
     OLE_IINTERFACE(IAdviseSink)
     OLE_IINTERFACE(IOleControlSite)
     OLE_IINTERFACE(IOleDocumentSite)
     OLE_IINTERFACE(IAdviseSink)
     OLE_IINTERFACE(IOleControlSite)
+    OLE_INTERFACE_CUSTOM(QueryClientSiteInterface)
+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);
+
+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
 
 END_OLE_TABLE
 
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// wxActiveXContainer
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
 
-wxActiveXContainer::wxActiveXContainer(wxWindow * parent, REFIID iid, IUnknown* pUnk)
+//---------------------------------------------------------------------------
+// wxActiveXContainer Constructor
+//
+// Initializes members and creates the native ActiveX container
+//---------------------------------------------------------------------------
+wxActiveXContainer::wxActiveXContainer(wxWindow * parent,
+                                       REFIID iid, IUnknown* pUnk)
     : m_realparent(parent)
 {
     m_bAmbientUserMode = true;
     : m_realparent(parent)
 {
     m_bAmbientUserMode = true;
@@ -592,16 +874,22 @@ wxActiveXContainer::wxActiveXContainer(wxWindow * parent, REFIID iid, IUnknown*
     CreateActiveX(iid, pUnk);
 }
 
     CreateActiveX(iid, pUnk);
 }
 
+//---------------------------------------------------------------------------
+// wxActiveXContainer Destructor
+//
+// Destroys members (the FrameSite et al. are destroyed implicitly
+// through COM ref counting)
+//---------------------------------------------------------------------------
 wxActiveXContainer::~wxActiveXContainer()
 {
     // disconnect connection points
 wxActiveXContainer::~wxActiveXContainer()
 {
     // disconnect connection points
-    if (m_oleInPlaceObject.Ok())
+    if (m_oleInPlaceObject.IsOk())
     {
         m_oleInPlaceObject->InPlaceDeactivate();
         m_oleInPlaceObject->UIDeactivate();
     }
 
     {
         m_oleInPlaceObject->InPlaceDeactivate();
         m_oleInPlaceObject->UIDeactivate();
     }
 
-    if (m_oleObject.Ok())
+    if (m_oleObject.IsOk())
     {
         if (m_docAdviseCookie != 0)
             m_oleObject->Unadvise(m_docAdviseCookie);
     {
         if (m_docAdviseCookie != 0)
             m_oleObject->Unadvise(m_docAdviseCookie);
@@ -611,38 +899,181 @@ wxActiveXContainer::~wxActiveXContainer()
         m_oleObject->Close(OLECLOSE_NOSAVE);
         m_oleObject->SetClientSite(NULL);
     }
         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);
 void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk)
 {
     HRESULT hret;
     hret = m_ActiveX.QueryInterface(iid, pUnk);
-    wxASSERT(SUCCEEDED(hret));
+    CHECK_HR(hret);
 
     // FrameSite
 
     // FrameSite
-    FrameSite *frame = new FrameSite(m_realparent, this);
+    m_frameSite = new FrameSite(m_realparent, this);
     // oleClientSite
     hret = m_clientSite.QueryInterface(
     // oleClientSite
     hret = m_clientSite.QueryInterface(
-        IID_IOleClientSite, (IDispatch *) frame);
-    wxASSERT(SUCCEEDED(hret));
+        IID_IOleClientSite, (IDispatch *) m_frameSite);
+    CHECK_HR(hret);
     // adviseSink
     // 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);
 
     // 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);
 
     // 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);
 
     // 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);
 
     // 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);
     m_oleObject->SetHostNames(L"wxActiveXContainer", NULL);
     OleSetContainedObject(m_oleObject, TRUE);
     OleRun(m_oleObject);
@@ -651,12 +1082,12 @@ void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk)
     // Get IOleInPlaceObject interface
     hret = m_oleInPlaceObject.QueryInterface(
         IID_IOleInPlaceObject, m_ActiveX);
     // 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);
 
     // status
     DWORD dwMiscStatus;
     m_oleObject->GetMiscStatus(DVASPECT_CONTENT, &dwMiscStatus);
-    wxASSERT(SUCCEEDED(hret));
+    CHECK_HR(hret);
 
     // set client site first ?
     if (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)
 
     // set client site first ?
     if (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)
@@ -667,43 +1098,50 @@ void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk)
     wxAutoIPersistStreamInit
         pPersistStreamInit(IID_IPersistStreamInit, m_oleObject);
 
     wxAutoIPersistStreamInit
         pPersistStreamInit(IID_IPersistStreamInit, m_oleObject);
 
-    if (pPersistStreamInit.Ok())
+    if (pPersistStreamInit.IsOk())
     {
         hret = pPersistStreamInit->InitNew();
     {
         hret = pPersistStreamInit->InitNew();
+        CHECK_HR(hret);
     }
 
     if (! (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST))
         m_oleObject->SetClientSite(m_clientSite);
 
 
     }
 
     if (! (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST))
         m_oleObject->SetClientSite(m_clientSite);
 
 
-    RECT posRect;
-    ::GetClientRect((HWND)m_realparent->GetHWND(), &posRect);
-
     m_oleObjectHWND = 0;
 
     m_oleObjectHWND = 0;
 
-    if (m_oleInPlaceObject.Ok())
-    {
-        hret = m_oleInPlaceObject->GetWindow(&m_oleObjectHWND);
-        if (SUCCEEDED(hret))
-            ::SetActiveWindow(m_oleObjectHWND);
-    }
-
 
     if (! (dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME))
     {
 
     if (! (dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME))
     {
-        if (posRect.right > 0 && posRect.bottom > 0 &&
-            m_oleInPlaceObject.Ok())
-                m_oleInPlaceObject->SetObjectRects(&posRect, &posRect);
+        RECT posRect;
+        wxCopyRectToRECT(m_realparent->GetClientSize(), posRect);
 
         hret = m_oleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL,
             m_clientSite, 0, (HWND)m_realparent->GetHWND(), &posRect);
 
         hret = m_oleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL,
             m_clientSite, 0, (HWND)m_realparent->GetHWND(), &posRect);
+        CHECK_HR(hret);
+
+        if (m_oleInPlaceObject.IsOk())
+        {
+            hret = m_oleInPlaceObject->GetWindow(&m_oleObjectHWND);
+            CHECK_HR(hret);
+            ::SetActiveWindow(m_oleObjectHWND);
+        }
+
+        if (posRect.right > 0 && posRect.bottom > 0 &&
+            m_oleInPlaceObject.IsOk())
+        {
+            m_oleInPlaceObject->SetObjectRects(&posRect, &posRect);
+        }
+
         hret = m_oleObject->DoVerb(OLEIVERB_SHOW, 0, m_clientSite, 0,
             (HWND)m_realparent->GetHWND(), &posRect);
         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);
     {
         hret = m_oleInPlaceObject->GetWindow(&m_oleObjectHWND);
+        CHECK_HR(hret);
     }
 
     if (m_oleObjectHWND)
     }
 
     if (m_oleObjectHWND)
@@ -719,6 +1157,8 @@ void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk)
 
         pWnd->Connect(id, wxEVT_SIZE,
             wxSizeEventHandler(wxActiveXContainer::OnSize), 0, this);
 
         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,
         pWnd->Connect(id, wxEVT_SET_FOCUS,
             wxFocusEventHandler(wxActiveXContainer::OnSetFocus), 0, this);
         pWnd->Connect(id, wxEVT_KILL_FOCUS,
@@ -726,34 +1166,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)   wxMulDivInt32(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;
 void wxActiveXContainer::OnSize(wxSizeEvent& event)
 {
     int w, h;
@@ -765,12 +1183,13 @@ void wxActiveXContainer::OnSize(wxSizeEvent& event)
     posRect.right = w;
     posRect.bottom = h;
 
     posRect.right = w;
     posRect.bottom = h;
 
-    if (w <= 0 && h <= 0)
+    if (w <= 0 || h <= 0)
         return;
 
     // extents are in HIMETRIC units
         return;
 
     // extents are in HIMETRIC units
-    if (m_oleObject.Ok())
+    if (m_oleObject.IsOk())
     {
     {
+
         SIZEL sz = {w, h};
         PixelsToHimetric(sz);
 
         SIZEL sz = {w, h};
         PixelsToHimetric(sz);
 
@@ -779,21 +1198,26 @@ 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);
         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())
+    }
+
+    if (m_oleInPlaceObject.IsOk())
         m_oleInPlaceObject->SetObjectRects(&posRect, &posRect);
 
     event.Skip();
 }
 
         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)
     {
 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;
         int w, h;
         GetParent()->GetSize(&w, &h);
         RECT posRect;
@@ -802,30 +1226,72 @@ void wxActiveXContainer::OnPaint(wxPaintEvent& WXUNUSED(event))
         posRect.right = w;
         posRect.bottom = h;
 
         posRect.right = w;
         posRect.bottom = h;
 
+#if !(defined(_WIN32_WCE) && _WIN32_WCE < 400)
         ::RedrawWindow(m_oleObjectHWND, NULL, NULL, RDW_INTERNALPAINT);
         ::RedrawWindow(m_oleObjectHWND, NULL, NULL, RDW_INTERNALPAINT);
+#else
+        ::InvalidateRect(m_oleObjectHWND, NULL, false);
+#endif
         RECTL *prcBounds = (RECTL *) &posRect;
         RECTL *prcBounds = (RECTL *) &posRect;
+        wxMSWDCImpl *msw = wxDynamicCast( dc.GetImpl() , wxMSWDCImpl );
         m_viewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL,
         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)
 {
 void wxActiveXContainer::OnSetFocus(wxFocusEvent& event)
 {
-    if (m_oleInPlaceActiveObject.Ok())
+    if (m_oleInPlaceActiveObject.IsOk())
         m_oleInPlaceActiveObject->OnFrameWindowActivate(TRUE);
 
     event.Skip();
 }
 
         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)
 {
 void wxActiveXContainer::OnKillFocus(wxFocusEvent& event)
 {
-    if (m_oleInPlaceActiveObject.Ok())
+    if (m_oleInPlaceActiveObject.IsOk())
         m_oleInPlaceActiveObject->OnFrameWindowActivate(FALSE);
 
     event.Skip();
 }
         m_oleInPlaceActiveObject->OnFrameWindowActivate(FALSE);
 
     event.Skip();
 }
+
+//---------------------------------------------------------------------------
+// wxActiveXContainer::MSWTranslateMessage
+//
+// Called for every message that needs to be translated.
+// Some controls might need more keyboard keys to process (CTRL-C, CTRL-A etc),
+// In that case TranslateAccelerator should always be called first.
+//---------------------------------------------------------------------------
+bool wxActiveXContainer::MSWTranslateMessage(WXMSG* pMsg)
+{
+    if(m_oleInPlaceActiveObject.IsOk() && m_oleInPlaceActiveObject->TranslateAccelerator(pMsg) == S_OK)
+    {
+        return true;
+    }
+    return wxWindow::MSWTranslateMessage(pMsg);
+}
+
+//---------------------------------------------------------------------------
+// wxActiveXContainer::QueryClientSiteInterface
+//
+// Called in the host's site's query method for other interfaces.
+//---------------------------------------------------------------------------
+bool wxActiveXContainer::QueryClientSiteInterface(REFIID iid, void **_interface, const char *&desc)
+{
+    wxUnusedVar(iid);
+    wxUnusedVar(_interface);
+    wxUnusedVar(desc);
+    return false;
+}
+
+#endif // wxUSE_ACTIVEX