Source

wxPython / contrib / activex / wxie / wxactivex.h

Full commit
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
/*
                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;

    unsigned long m_pdwRegister;
        
    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;

    virtual bool MSWTranslateMessage(WXMSG* pMsg);
    WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam);

    DECLARE_CLASS(wxActiveX)
};

// 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 wxString& 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_ */