--- /dev/null
+/*
+ wxActiveX Library Licence, Version 3
+ ====================================
+
+ Copyright (C) 2003 Lindsay Mathieson [, ...]
+
+ Everyone is permitted to copy and distribute verbatim copies
+ of this licence document, but changing it is not allowed.
+
+ wxActiveX LIBRARY LICENCE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public Licence as published by
+ the Free Software Foundation; either version 2 of the Licence, or (at
+ your option) any later version.
+
+ This library is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
+ General Public Licence for more details.
+
+ You should have received a copy of the GNU Library General Public Licence
+ along with this software, usually in a file named COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ Boston, MA 02111-1307 USA.
+
+ EXCEPTION NOTICE
+
+ 1. As a special exception, the copyright holders of this library give
+ permission for additional uses of the text contained in this release of
+ the library as licenced under the wxActiveX Library Licence, applying
+ either version 3 of the Licence, or (at your option) any later version of
+ the Licence as published by the copyright holders of version 3 of the
+ Licence document.
+
+ 2. The exception is that you may use, copy, link, modify and distribute
+ under the user's own terms, binary object code versions of works based
+ on the Library.
+
+ 3. If you copy code from files distributed under the terms of the GNU
+ General Public Licence or the GNU Library General Public Licence into a
+ copy of this library, as this licence permits, the exception does not
+ apply to the code that you add in this way. To avoid misleading anyone as
+ to the status of such modified files, you must delete this exception
+ notice from such code and/or adjust the licensing conditions notice
+ accordingly.
+
+ 4. If you write modifications of your own for this library, it is your
+ choice whether to permit this exception to apply to your modifications.
+ If you do not wish that, you must delete the exception notice from such
+ code and/or adjust the licensing conditions notice accordingly.
+*/
+
+/*! \file wxactivex.h
+ \brief implements wxActiveX window class and OLE tools
+*/
+
+#ifndef WX_ACTIVE_X
+#define WX_ACTIVE_X
+#pragma warning( disable : 4101 4786)
+#pragma warning( disable : 4786)
+
+
+#include <wx/setup.h>
+#include <wx/wx.h>
+#include <wx/variant.h>
+#include <wx/datetime.h>
+#include <oleidl.h>
+#include <exdisp.h>
+#include <docobj.h>
+#include <iostream>
+#include <vector>
+#include <map>
+using namespace std;
+
+/// \brief wxActiveX Namespace for stuff I want to keep out of other tools way.
+namespace NS_wxActiveX
+{
+ /// STL utilty class.
+ /// specific to wxActiveX, for creating
+ /// case insenstive maps etc
+ struct less_wxStringI
+ {
+ bool operator()(const wxString& x, const wxString& y) const
+ {
+ return x.CmpNoCase(y) < 0;
+ };
+ };
+};
+
+
+//////////////////////////////////////////
+/// Template class for smart interface handling.
+/// - Automatically dereferences ole interfaces
+/// - Smart Copy Semantics
+/// - Can Create Interfaces
+/// - Can query for other interfaces
+template <class I> class wxAutoOleInterface
+{
+ protected:
+ I *m_interface;
+
+ public:
+ /// takes ownership of an existing interface
+ /// Assumed to already have a AddRef() applied
+ explicit wxAutoOleInterface(I *pInterface = NULL) : m_interface(pInterface) {}
+
+ /// queries for an interface
+ wxAutoOleInterface(REFIID riid, IUnknown *pUnk) : m_interface(NULL)
+ {
+ QueryInterface(riid, pUnk);
+ };
+ /// queries for an interface
+ wxAutoOleInterface(REFIID riid, IDispatch *pDispatch) : m_interface(NULL)
+ {
+ QueryInterface(riid, pDispatch);
+ };
+
+ /// Creates an Interface
+ wxAutoOleInterface(REFCLSID clsid, REFIID riid) : m_interface(NULL)
+ {
+ CreateInstance(clsid, riid);
+ };
+
+ /// copy constructor
+ wxAutoOleInterface(const wxAutoOleInterface<I>& ti) : m_interface(NULL)
+ {
+ operator = (ti);
+ }
+
+ /// assignment operator
+ wxAutoOleInterface<I>& operator = (const wxAutoOleInterface<I>& ti)
+ {
+ if (ti.m_interface)
+ ti.m_interface->AddRef();
+ Free();
+ m_interface = ti.m_interface;
+ return *this;
+ }
+
+ /// takes ownership of an existing interface
+ /// Assumed to already have a AddRef() applied
+ wxAutoOleInterface<I>& operator = (I *&ti)
+ {
+ Free();
+ m_interface = ti;
+ return *this;
+ }
+
+ /// invokes Free()
+ ~wxAutoOleInterface()
+ {
+ Free();
+ };
+
+
+ /// Releases interface (i.e decrements refCount)
+ inline void Free()
+ {
+ if (m_interface)
+ m_interface->Release();
+ m_interface = NULL;
+ };
+
+ /// queries for an interface
+ HRESULT QueryInterface(REFIID riid, IUnknown *pUnk)
+ {
+ Free();
+ wxCHECK(pUnk != NULL, -1);
+ return pUnk->QueryInterface(riid, (void **) &m_interface);
+ };
+
+ /// Create a Interface instance
+ HRESULT CreateInstance(REFCLSID clsid, REFIID riid)
+ {
+ Free();
+ return CoCreateInstance(clsid, NULL, CLSCTX_ALL, riid, (void **) &m_interface);
+ };
+
+
+ /// returns the interface pointer
+ inline operator I *() const {return m_interface;}
+
+ /// returns the dereferenced interface pointer
+ inline I* operator ->() {return m_interface;}
+ /// returns a pointer to the interface pointer
+ inline I** GetRef() {return &m_interface;}
+ /// returns true if we have a valid interface pointer
+ inline bool Ok() const {return m_interface != NULL;}
+};
+
+
+/// \brief Converts a std HRESULT to its error code.
+/// Hardcoded, by no means a definitive list.
+wxString OLEHResultToString(HRESULT hr);
+/// \brief Returns the string description of a IID.
+/// Hardcoded, by no means a definitive list.
+wxString GetIIDName(REFIID riid);
+
+//#define __WXOLEDEBUG
+
+
+#ifdef __WXOLEDEBUG
+ #define WXOLE_TRACE(str) {OutputDebugString(str);OutputDebugString("\r\n");}
+ #define WXOLE_TRACEOUT(stuff)\
+ {\
+ wxString os;\
+ os << stuff << "\r\n";\
+ WXOLE_TRACE(os.mb_str());\
+ }
+
+ #define WXOLE_WARN(__hr,msg)\
+ {\
+ if (__hr != S_OK)\
+ {\
+ wxString s = "*** ";\
+ s += msg;\
+ s += " : "+ OLEHResultToString(__hr);\
+ WXOLE_TRACE(s.c_str());\
+ }\
+ }
+#else
+ #define WXOLE_TRACE(str)
+ #define WXOLE_TRACEOUT(stuff)
+ #define WXOLE_WARN(_proc,msg) {_proc;}
+#endif
+
+class wxOleInit
+{
+ public:
+ static IMalloc *GetIMalloc();
+
+ wxOleInit();
+ ~wxOleInit();
+};
+
+#define DECLARE_OLE_UNKNOWN(cls)\
+ private:\
+ class TAutoInitInt\
+ {\
+ public:\
+ LONG l;\
+ TAutoInitInt() : l(0) {}\
+ };\
+ TAutoInitInt refCount, lockCount;\
+ wxOleInit oleInit;\
+ static void _GetInterface(cls *self, REFIID iid, void **_interface, const char *&desc);\
+ public:\
+ LONG GetRefCount();\
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void ** ppvObject);\
+ ULONG STDMETHODCALLTYPE AddRef();\
+ ULONG STDMETHODCALLTYPE Release();\
+ ULONG STDMETHODCALLTYPE AddLock();\
+ ULONG STDMETHODCALLTYPE ReleaseLock()
+
+#define DEFINE_OLE_TABLE(cls)\
+ LONG cls::GetRefCount() {return refCount.l;}\
+ HRESULT STDMETHODCALLTYPE cls::QueryInterface(REFIID iid, void ** ppvObject)\
+ {\
+ if (! ppvObject)\
+ {\
+ WXOLE_TRACE("*** NULL POINTER ***");\
+ return E_FAIL;\
+ };\
+ const char *desc = NULL;\
+ cls::_GetInterface(this, iid, ppvObject, desc);\
+ if (! *ppvObject)\
+ {\
+ WXOLE_TRACEOUT("<" << GetIIDName(iid).c_str() << "> Not Found");\
+ return E_NOINTERFACE;\
+ };\
+ WXOLE_TRACEOUT("QI : <" << desc <<">");\
+ ((IUnknown * )(*ppvObject))->AddRef();\
+ return S_OK;\
+ };\
+ ULONG STDMETHODCALLTYPE cls::AddRef()\
+ {\
+ WXOLE_TRACEOUT(# cls << "::Add ref(" << refCount.l << ")");\
+ InterlockedIncrement(&refCount.l);\
+ return refCount.l;\
+ };\
+ ULONG STDMETHODCALLTYPE cls::Release()\
+ {\
+ if (refCount.l > 0)\
+ {\
+ InterlockedDecrement(&refCount.l);\
+ WXOLE_TRACEOUT(# cls << "::Del ref(" << refCount.l << ")");\
+ if (refCount.l == 0)\
+ {\
+ delete this;\
+ return 0;\
+ };\
+ return refCount.l;\
+ }\
+ else\
+ return 0;\
+ }\
+ ULONG STDMETHODCALLTYPE cls::AddLock()\
+ {\
+ WXOLE_TRACEOUT(# cls << "::Add Lock(" << lockCount.l << ")");\
+ InterlockedIncrement(&lockCount.l);\
+ return lockCount.l;\
+ };\
+ ULONG STDMETHODCALLTYPE cls::ReleaseLock()\
+ {\
+ if (lockCount.l > 0)\
+ {\
+ InterlockedDecrement(&lockCount.l);\
+ WXOLE_TRACEOUT(# cls << "::Del Lock(" << lockCount.l << ")");\
+ return lockCount.l;\
+ }\
+ else\
+ return 0;\
+ }\
+ DEFINE_OLE_BASE(cls)
+
+#define DEFINE_OLE_BASE(cls)\
+ void cls::_GetInterface(cls *self, REFIID iid, void **_interface, const char *&desc)\
+ {\
+ *_interface = NULL;\
+ desc = NULL;
+
+#define OLE_INTERFACE(_iid, _type)\
+ if (IsEqualIID(iid, _iid))\
+ {\
+ WXOLE_TRACE("Found Interface <" # _type ">");\
+ *_interface = (IUnknown *) (_type *) self;\
+ desc = # _iid;\
+ return;\
+ }
+
+#define OLE_IINTERFACE(_face) OLE_INTERFACE(IID_##_face, _face)
+
+#define OLE_INTERFACE_CUSTOM(func)\
+ if (func(self, iid, _interface, desc))\
+ {\
+ return;\
+ }
+
+#define END_OLE_TABLE\
+ }
+
+
+/// Main class for embedding a ActiveX control.
+/// Use by itself or derive from it
+/// \note The utility program (wxie) can generate a list of events, methods & properties
+/// for a control.
+/// First display the control (File|Display),
+/// then get the type info (ActiveX|Get Type Info) - these are copied to the clipboard.
+/// Eventually this will be expanded to autogenerate
+/// wxWindows source files for a control with all methods etc encapsulated.
+/// \par Usage:
+/// construct using a ProgId or class id
+/// \code new wxActiveX(parent, CLSID_WebBrowser, id, pos, size, style, name)\endcode
+/// \code new wxActiveX(parent, "ShockwaveFlash.ShockwaveFlash", id, pos, size, style, name)\endcode
+/// \par Properties
+/// Properties can be set using \c SetProp() and set/retrieved using \c Prop()
+/// \code SetProp(name, wxVariant(x)) \endcode or
+/// \code wxString Prop("<name>") = x\endcode
+/// \code wxString result = Prop("<name>")\endcode
+/// \code flash_ctl.Prop("movie") = "file:///movies/test.swf";\endcode
+/// \code flash_ctl.Prop("Playing") = false;\endcode
+/// \code wxString current_movie = flash_ctl.Prop("movie");\endcode
+/// \par Methods
+/// Methods are invoked with \c CallMethod()
+/// \code wxVariant result = CallMethod("<name>", args, nargs = -1)\endcode
+/// \code wxVariant args[] = {0L, "file:///e:/dev/wxie/bug-zap.swf"};
+/// wxVariant result = X->CallMethod("LoadMovie", args);\endcode
+/// \par events
+/// respond to events with the
+/// \c EVT_ACTIVEX(controlId, eventName, handler) &
+/// \c EVT_ACTIVEX_DISPID(controlId, eventDispId, handler) macros
+/// \code
+/// BEGIN_EVENT_TABLE(wxIEFrame, wxFrame)
+/// EVT_ACTIVEX_DISPID(ID_MSHTML, DISPID_STATUSTEXTCHANGE, OnMSHTMLStatusTextChangeX)
+/// EVT_ACTIVEX(ID_MSHTML, "BeforeNavigate2", OnMSHTMLBeforeNavigate2X)
+/// EVT_ACTIVEX(ID_MSHTML, "TitleChange", OnMSHTMLTitleChangeX)
+/// EVT_ACTIVEX(ID_MSHTML, "NewWindow2", OnMSHTMLNewWindow2X)
+/// EVT_ACTIVEX(ID_MSHTML, "ProgressChange", OnMSHTMLProgressChangeX)
+/// END_EVENT_TABLE()\endcode
+class wxActiveX : public wxWindow {
+public:
+ /// General parameter and return type infoformation for Events, Properties and Methods.
+ /// refer to ELEMDESC, IDLDESC in MSDN
+ class ParamX
+ {
+ public:
+ USHORT flags;
+ bool isPtr;
+ bool isSafeArray;
+ bool isOptional;
+ VARTYPE vt;
+ wxString name;
+
+ ParamX() : isOptional(false), vt(VT_EMPTY) {}
+ inline bool IsIn() const {return (flags & IDLFLAG_FIN) != 0;}
+ inline bool IsOut() const {return (flags & IDLFLAG_FOUT) != 0;}
+ inline bool IsRetVal() const {return (flags & IDLFLAG_FRETVAL) != 0;}
+ };
+ typedef vector<ParamX> ParamXArray;
+
+
+ /// Type & Parameter info for Events and Methods.
+ /// refer to FUNCDESC in MSDN
+ class FuncX
+ {
+ public:
+ wxString name;
+ MEMBERID memid;
+ bool hasOut;
+
+ ParamX retType;
+ ParamXArray params;
+ };
+ typedef vector<FuncX> FuncXArray;
+
+
+ /// Type info for properties.
+ class PropX
+ {
+ public:
+ wxString name;
+ MEMBERID memid;
+ ParamX type;
+ ParamX arg;
+ bool putByRef;
+
+ PropX() : putByRef (false) {}
+ inline bool CanGet() const {return type.vt != VT_EMPTY;}
+ inline bool CanSet() const {return arg.vt != VT_EMPTY;}
+ };
+ typedef vector<PropX> PropXArray;
+
+
+ /// Create using clsid.
+ wxActiveX(wxWindow * parent, REFCLSID clsid, wxWindowID id = -1,
+ const wxPoint& pos = wxDefaultPosition,
+ const wxSize& size = wxDefaultSize,
+ long style = 0,
+ const wxString& name = wxPanelNameStr);
+ /// create using progid.
+ wxActiveX(wxWindow * parent, const wxString& progId, wxWindowID id = -1,
+ const wxPoint& pos = wxDefaultPosition,
+ const wxSize& size = wxDefaultSize,
+ long style = 0,
+ const wxString& name = wxPanelNameStr);
+ virtual ~wxActiveX();
+
+ /// Number of events defined for this control.
+ inline int GetEventCount() const {return m_events.size();}
+ /// returns event description by index.
+ /// throws exception for invalid index
+ const FuncX& GetEventDesc(int idx) const;
+
+ /// Number of properties defined for this control.
+ inline int GetPropCount() const {return m_props.size();}
+ /// returns property description by index.
+ /// throws exception for invalid index
+ const PropX& GetPropDesc(int idx) const;
+ /// returns property description by name.
+ /// throws exception for invalid name
+ const PropX& GetPropDesc(const wxString& name) const;
+
+ /// Number of methods defined for this control.
+ inline int GetMethodCount() const {return m_methods.size();}
+ /// returns method description by name.
+ /// throws exception for invalid index
+ const FuncX& GetMethodDesc(int idx) const;
+ /// returns method description by name.
+ /// throws exception for invalid name
+ const FuncX& GetMethodDesc(const wxString& name) const;
+
+ /// Set property VARIANTARG value by MEMBERID.
+ void SetProp(MEMBERID name, VARIANTARG& value);
+ /// Set property using wxVariant by name.
+ void SetProp(const wxString &name, const wxVariant &value);
+
+ class wxPropertySetter
+ {
+ public:
+ wxActiveX *m_ctl;
+ wxString m_propName;
+
+ wxPropertySetter(wxActiveX *ctl, const wxString& propName) :
+ m_ctl(ctl), m_propName(propName) {}
+
+ inline const wxPropertySetter& operator = (wxVariant v) const
+ {
+ m_ctl->SetProp(m_propName, v);
+ return *this;
+ };
+
+ inline operator wxVariant() const {return m_ctl->GetPropAsWxVariant(m_propName);};
+ inline operator wxString() const {return m_ctl->GetPropAsString(m_propName);};
+ inline operator char() const {return m_ctl->GetPropAsChar(m_propName);};
+ inline operator long() const {return m_ctl->GetPropAsLong(m_propName);};
+ inline operator bool() const {return m_ctl->GetPropAsBool(m_propName);};
+ inline operator double() const {return m_ctl->GetPropAsDouble(m_propName);};
+ inline operator wxDateTime() const {return m_ctl->GetPropAsDateTime(m_propName);};
+ inline operator void *() const {return m_ctl->GetPropAsPointer(m_propName);};
+ };
+
+ /// \fn inline wxPropertySetter Prop(wxString name) {return wxPropertySetter(this, name);}
+ /// \param name Property name to read/set
+ /// \return wxPropertySetter, which has overloads for setting/getting the property
+ /// \brief Generic Get/Set Property by name.
+ /// Automatically handles most types
+ /// \par Usage:
+ /// - Prop("\<name\>") = \<value\>
+ /// - var = Prop("\<name\>")
+ /// - e.g:
+ /// - \code flash_ctl.Prop("movie") = "file:///movies/test.swf";\endcode
+ /// - \code flash_ctl.Prop("Playing") = false;\endcode
+ /// - \code wxString current_movie = flash_ctl.Prop("movie");\endcode
+ /// \exception raises exception if \<name\> is invalid
+ /// \note Have to add a few more type conversions yet ...
+ inline wxPropertySetter Prop(wxString name) {return wxPropertySetter(this, name);}
+
+ VARIANT GetPropAsVariant(MEMBERID name);
+ VARIANT GetPropAsVariant(const wxString& name);
+ wxVariant GetPropAsWxVariant(const wxString& name);
+ wxString GetPropAsString(const wxString& name);
+ char GetPropAsChar(const wxString& name);
+ long GetPropAsLong(const wxString& name);
+ bool GetPropAsBool(const wxString& name);
+ double GetPropAsDouble(const wxString& name);
+ wxDateTime GetPropAsDateTime(const wxString& name);
+ void *GetPropAsPointer(const wxString& name);
+
+ // methods
+ // VARIANTARG form is passed straight to Invoke,
+ // so args in *REVERSE* order
+ VARIANT CallMethod(MEMBERID name, VARIANTARG args[], int argc);
+ VARIANT CallMethod(const wxString& name, VARIANTARG args[] = NULL, int argc = -1);
+ // args are in *NORMAL* order
+ // args can be a single wxVariant or an array
+ /// \fn wxVariant CallMethod(wxString name, wxVariant args[], int nargs = -1);
+ /// \param name name of method to call
+ /// \param args array of wxVariant's, defaults to NULL (no args)
+ /// \param nargs number of arguments passed via args. Defaults to actual number of args for the method
+ /// \return wxVariant
+ /// \brief Call a method of the ActiveX control.
+ /// Automatically handles most types
+ /// \par Usage:
+ /// - result = CallMethod("\<name\>", args, nargs)
+ /// - e.g.
+ /// - \code
+ /// wxVariant args[] = {0L, "file:///e:/dev/wxie/bug-zap.swf"};
+ /// wxVariant result = X->CallMethod("LoadMovie", args);\endcode
+ /// \exception raises exception if \<name\> is invalid
+ /// \note Since wxVariant has built in type conversion, most the std types can be passed easily
+ wxVariant CallMethod(const wxString& name, wxVariant args[], int nargs = -1);
+
+ HRESULT ConnectAdvise(REFIID riid, IUnknown *eventSink);
+
+ void OnSize(wxSizeEvent&);
+ void OnPaint(wxPaintEvent& event);
+ void OnMouse(wxMouseEvent& event);
+ void OnSetFocus(wxFocusEvent&);
+ void OnKillFocus(wxFocusEvent&);
+
+ DECLARE_EVENT_TABLE();
+
+protected:
+ friend class FrameSite;
+ friend class wxActiveXEvents;
+
+
+ typedef map<MEMBERID, int> MemberIdMap;
+ typedef map<wxString, int, NS_wxActiveX::less_wxStringI> NameMap;
+
+ typedef wxAutoOleInterface<IConnectionPoint> wxOleConnectionPoint;
+ typedef pair<wxOleConnectionPoint, DWORD> wxOleConnection;
+ typedef vector<wxOleConnection> wxOleConnectionArray;
+
+ wxAutoOleInterface<IDispatch> m_Dispatch;
+ wxAutoOleInterface<IOleClientSite> m_clientSite;
+ wxAutoOleInterface<IUnknown> m_ActiveX;
+ wxAutoOleInterface<IOleObject> m_oleObject;
+ wxAutoOleInterface<IOleInPlaceObject> m_oleInPlaceObject;
+ wxAutoOleInterface<IOleInPlaceActiveObject>
+
+ m_oleInPlaceActiveObject;
+ wxAutoOleInterface<IOleDocumentView> m_docView;
+ wxAutoOleInterface<IViewObject> m_viewObject;
+ HWND m_oleObjectHWND;
+ bool m_bAmbientUserMode;
+ DWORD m_docAdviseCookie;
+ wxOleConnectionArray m_connections;
+
+ void CreateActiveX(REFCLSID clsid);
+ void CreateActiveX(LPOLESTR progId);
+ HRESULT AmbientPropertyChanged(DISPID dispid);
+
+ void GetTypeInfo();
+ void GetTypeInfo(ITypeInfo *ti, bool defInterface, bool defEventSink);
+
+
+ // events
+ FuncXArray m_events;
+ MemberIdMap m_eventMemberIds;
+
+ // properties
+ PropXArray m_props;
+ NameMap m_propNames;
+
+ // Methods
+ FuncXArray m_methods;
+ NameMap m_methodNames;
+
+ long MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam);
+};
+
+// events
+class wxActiveXEvent : public wxCommandEvent
+{
+private:
+ friend class wxActiveXEvents;
+
+ wxVariant m_params;
+
+public:
+
+ virtual wxEvent *Clone() const { return new wxActiveXEvent(*this); }
+
+ wxString EventName();
+ int ParamCount() const;
+ wxString ParamType(int idx);
+ wxString ParamName(int idx);
+ wxVariant& operator[] (int idx);
+ wxVariant& operator[] (wxString name);
+
+private:
+ DECLARE_CLASS(wxActiveXEvent)
+};
+
+const wxEventType& RegisterActiveXEvent(const wxChar *eventName);
+const wxEventType& RegisterActiveXEvent(DISPID event);
+
+typedef void (wxEvtHandler::*wxActiveXEventFunction)(wxActiveXEvent&);
+
+/// \def EVT_ACTIVEX(id, eventName, fn)
+/// \brief Event handle for events by name
+#define EVT_ACTIVEX(id, eventName, fn) DECLARE_EVENT_TABLE_ENTRY(RegisterActiveXEvent(wxT(eventName)), id, -1, (wxObjectEventFunction) (wxEventFunction) (wxActiveXEventFunction) & fn, (wxObject *) NULL ),
+/// \def EVT_ACTIVEX_DISPID(id, eventDispId, fn)
+/// \brief Event handle for events by DISPID (dispath id)
+#define EVT_ACTIVEX_DISPID(id, eventDispId, fn) DECLARE_EVENT_TABLE_ENTRY(RegisterActiveXEvent(eventDispId), id, -1, (wxObjectEventFunction) (wxEventFunction) (wxActiveXEventFunction) & fn, (wxObject *) NULL ),
+
+//util
+bool wxDateTimeToVariant(wxDateTime dt, VARIANTARG& va);
+bool VariantToWxDateTime(VARIANTARG va, wxDateTime& dt);
+/// \relates wxActiveX
+/// \fn bool MSWVariantToVariant(VARIANTARG& va, wxVariant& vx);
+/// \param va VARAIANTARG to convert from
+/// \param vx Destination wxVariant
+/// \return success/failure (true/false)
+/// \brief Convert MSW VARIANTARG to wxVariant.
+/// Handles basic types, need to add:
+/// - VT_ARRAY | VT_*
+/// - better support for VT_UNKNOWN (currently treated as void *)
+/// - better support for VT_DISPATCH (currently treated as void *)
+bool MSWVariantToVariant(VARIANTARG& va, wxVariant& vx);
+/// \relates wxActiveX
+/// \fn bool VariantToMSWVariant(const wxVariant& vx, VARIANTARG& va);
+/// \param vx wxVariant to convert from
+/// \param va Destination VARIANTARG
+/// \return success/failure (true/false)
+/// \brief Convert wxVariant to MSW VARIANTARG.
+/// Handles basic types, need to add:
+/// - VT_ARRAY | VT_*
+/// - better support for VT_UNKNOWN (currently treated as void *)
+/// - better support for VT_DISPATCH (currently treated as void *)
+bool VariantToMSWVariant(const wxVariant& vx, VARIANTARG& va);
+
+#endif /* _IEHTMLWIN_H_ */