+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;
+}