1 /////////////////////////////////////////////////////////////////////////////
 
   3 // Purpose:     ActiveX controls (such as Internet Explorer) in a wxWindow
 
   7 // Created:     18-Mar-2004
 
   9 // Copyright:   (c) 2004 by Total Control Software
 
  10 // Licence:     wxWindows license
 
  11 /////////////////////////////////////////////////////////////////////////////
 
  14 %module(package="wx") activex
 
  17 #include "wx/wxPython/wxPython.h"
 
  18 #include "wx/wxPython/pyclasses.h"
 
  19 #include "wx/wxPython/pyistream.h"
 
  21 #include "wxactivex.h"
 
  24 //---------------------------------------------------------------------------
 
  27 %pythoncode { wx = _core }
 
  28 %pythoncode { __docfilter__ = wx.__DocFilter(globals()) }
 
  30 MAKE_CONST_WXSTRING_NOSWIG(PanelNameStr);
 
  32 %include _activex_rename.i
 
  35 //---------------------------------------------------------------------------
 
  37 typedef unsigned short  USHORT;
 
  39 typedef long            MEMBERID;
 
  40 typedef unsigned short  VARTYPE;
 
  44 // Since SWIG doesn't support nested classes, we need to fool it a bit
 
  45 // and make them look like global classes.  These defines make the C++ code
 
  46 // know what we are doing.
 
  47 #define wxParamX        wxActiveX::ParamX
 
  48 #define wxFuncX         wxActiveX::FuncX
 
  49 #define wxPropX         wxActiveX::PropX
 
  50 #define wxParamXArray   wxActiveX::ParamXArray
 
  51 #define wxFuncXArray    wxActiveX::FuncXArray
 
  52 #define wxPropXArray    wxActiveX::PropXArray
 
  57 // Some conversion helpers
 
  58 static wxVariant _PyObj2Variant(PyObject* value);
 
  59 static bool  _PyObj2Variant(PyObject* value, wxVariant& wv);
 
  60 static PyObject* _Variant2PyObj(wxVariant& value, bool useNone=false);
 
  61 static wxString  _VARTYPEname(VARTYPE vt);
 
  63 // Check if an exception has been raised  (blocking threads)
 
  64 inline bool wxPyErr_Occurred()
 
  67     wxPyBlock_t blocked = wxPyBeginBlockThreads();
 
  68     rval = PyErr_Occurred() != NULL;
 
  69     wxPyEndBlockThreads(blocked);
 
  75 //---------------------------------------------------------------------------
 
  79 "This class wraps the Windows CLSID structure and is used to
 
  80 specify the class of the ActiveX object that is to be created.  A
 
  81 CLSID can be constructed from either a ProgID string, (such as
 
  82 'WordPad.Document.1') or a classID string, (such as
 
  83 '{CA8A9783-280D-11CF-A24D-444553540000}').", "");
 
  88         CLSID(const wxString& id)
 
  91             CLSID* self = new CLSID;
 
  92             memset(self, 0, sizeof(CLSID));
 
  94             if (id[0] == _T('{')) {
 
  95                 // Looks like a classID string
 
  98                         (LPOLESTR)(const wchar_t *)id.wc_str(wxConvUTF8),
 
 104                         (LPOLESTR)(const wchar_t *)id.wc_str(wxConvUTF8),
 
 107             if (result != NOERROR) {
 
 108                 wxPyErr_SetString(PyExc_ValueError, "Not a recognized classID or progID");
 
 115         ~CLSID() { delete self; }
 
 117         wxString GetCLSIDString()
 
 121             if (StringFromCLSID(*self, &s) == S_OK) {
 
 126                 str = _T("Error!");  // TODO: raise exception?
 
 130         wxString GetProgIDString()
 
 134             if (ProgIDFromCLSID(*self, &s) == S_OK) {
 
 139                 str = _T("Error!"); // TODO: raise exception?
 
 144     %pythoncode { def __str__(self):   return self.GetCLSIDString() }
 
 148 //---------------------------------------------------------------------------
 
 151 %define MAKE_ARRAY_WRAPPER(basetype, arrayname)
 
 156         bool __nonzero__()          { return self->size() > 0; }
 
 157         int  __len__()              { return self->size(); }
 
 159         const basetype& __getitem__(int idx) {
 
 160             if ( idx >= 0 && idx < self->size() )
 
 163                 static basetype BadVal;
 
 164                 wxPyErr_SetString(PyExc_IndexError, "Index out of range");
 
 173 //---------------------------------------------------------------------------
 
 187     %feature("shadow") vt_type_get "vt_type = property(_activex.ParamX_vt_type_get)";
 
 188     %extend { wxString vt_type_get() { return _VARTYPEname(self->vt); } }
 
 190     %feature("shadow") IsIn     "isIn = property(_activex.ParamX_IsIn)";
 
 191     %feature("shadow") IsOut    "isOut = property(_activex.ParamX_IsOut)";
 
 192     %feature("shadow") IsRetVal "isRetVal = property(_activex.ParamX_IsRetVal)";
 
 195     bool IsRetVal() const;
 
 208     wxParamXArray params;
 
 221     %feature("shadow") CanGet "canGet = property(_activex.PropX_CanGet)";
 
 222     %feature("shadow") CanSet "canSet = property(_activex.PropX_CanSet)";
 
 229 MAKE_ARRAY_WRAPPER(wxParamX, wxParamXArray);
 
 230 MAKE_ARRAY_WRAPPER(wxFuncX, wxFuncXArray);
 
 231 MAKE_ARRAY_WRAPPER(wxPropX, wxPropXArray);
 
 234 //---------------------------------------------------------------------------
 
 238 // C++ version of a Python-aware wxActiveX    
 
 239 class wxActiveXWindow : public wxActiveX
 
 244     DECLARE_ABSTRACT_CLASS(wxActiveXWindow);
 
 247     wxActiveXWindow( wxWindow* parent, const CLSID& clsId, wxWindowID id = -1,
 
 248                      const wxPoint& pos = wxDefaultPosition,
 
 249                      const wxSize& size = wxDefaultSize,
 
 251                      const wxString& name = wxPyPanelNameStr)
 
 252         : wxActiveX(parent, clsId, id, pos, size, style, name)
 
 257     const CLSID& GetCLSID() const { return m_CLSID; }
 
 260     // Renamed versions of some base class methods that delegate
 
 261     // to the base where appropriate, and raise Python exceptions
 
 263     int GetAXEventCount() const  { return wxActiveX::GetEventCount(); }
 
 264     int GetAXPropCount() const   { return wxActiveX::GetPropCount(); }
 
 265     int GetAXMethodCount() const { return wxActiveX::GetMethodCount(); }
 
 267     const wxFuncX& GetAXEventDesc(int idx) const
 
 269         static wxFuncX BadVal;
 
 270         if (idx < 0 || idx >= GetAXEventCount()) {
 
 271             wxPyErr_SetString(PyExc_IndexError, "Index out of range");
 
 274         return m_events[idx];
 
 276     const wxFuncX& GetAXMethodDesc(int idx) const
 
 278         static wxFuncX BadVal;
 
 279         if (idx < 0 || idx >= GetAXMethodCount()) {
 
 280             wxPyErr_SetString(PyExc_IndexError, "Index out of range");
 
 283         return m_methods[idx];
 
 285     const wxPropX& GetAXPropDesc(int idx) const
 
 287         static wxPropX BadVal;
 
 288         if (idx < 0 || idx >= GetAXPropCount()) {
 
 289             wxPyErr_SetString(PyExc_IndexError, "Index out of range");
 
 295     const wxFuncX& GetAXMethodDesc(const wxString& name) const
 
 297         NameMap::const_iterator it = m_methodNames.find(name);
 
 298         if (it == m_methodNames.end())     {
 
 300             msg << _T("method <") << name << _T("> not found");
 
 301             wxPyErr_SetString(PyExc_KeyError, msg.mb_str());
 
 302             static wxFuncX BadVal;
 
 305         return GetAXMethodDesc(it->second);
 
 307     const wxPropX& GetAXPropDesc(const wxString& name) const
 
 309         NameMap::const_iterator it = m_propNames.find(name);
 
 310         if (it == m_propNames.end())     {
 
 312             msg << _T("property <") << name << _T("> not found");
 
 313             wxPyErr_SetString(PyExc_KeyError, msg.mb_str());
 
 314             static wxPropX BadVal;
 
 317         return GetAXPropDesc(it->second);
 
 320     // Accessors for the internal vectors of events, methods and
 
 321     // proprties.  Can be used as sequence like objects from
 
 323     const wxFuncXArray& GetAXEvents()      { return m_events; }
 
 324     const wxFuncXArray& GetAXMethods()     { return m_methods; }
 
 325     const wxPropXArray& GetAXProperties()  { return m_props; }
 
 328     // Set a property from a Python object
 
 329     void SetAXProp(const wxString& name, PyObject* value)
 
 331         const wxPropX& prop = GetAXPropDesc(name);
 
 332         wxPyBlock_t blocked = wxPyBeginBlockThreads();
 
 333         if (! PyErr_Occurred() ) {
 
 334             if (! prop.CanSet()) {
 
 336                 msg << _T("property <") << name << _T("> is readonly");
 
 337                 PyErr_SetString(PyExc_TypeError, msg.mb_str());
 
 340                 wxVariant wxV = _PyObj2Variant(value);
 
 341                 if (PyErr_Occurred())
 
 343                 VARIANT v = {prop.arg.vt};
 
 344                 if (!VariantToMSWVariant(wxV, v) || PyErr_Occurred()) {
 
 346                     msg << _T("Unable to convert value to expected type: (")
 
 347                         << _VARTYPEname(prop.arg.vt) << _T(") for property <")
 
 349                     PyErr_SetString(PyExc_TypeError, msg.mb_str());
 
 352                 PyThreadState* tstate = wxPyBeginAllowThreads();
 
 353                 SetProp(prop.memid, v);
 
 355                 wxPyEndAllowThreads(tstate);
 
 359         wxPyEndBlockThreads(blocked);
 
 363     // Get a property and convert it to a Python object
 
 364     PyObject* GetAXProp(const wxString& name)
 
 366         PyObject* rval = NULL;
 
 367         const wxPropX& prop = GetAXPropDesc(name);
 
 368         wxPyBlock_t blocked = wxPyBeginBlockThreads();
 
 369         if (! PyErr_Occurred() ) {
 
 370             if (! prop.CanGet()) {
 
 372                 msg << _T("property <") << name << _T("> is writeonly");
 
 373                 PyErr_SetString(PyExc_TypeError, msg.mb_str());
 
 376                 PyThreadState* tstate = wxPyBeginAllowThreads();
 
 377                 VARIANT v = GetPropAsVariant(prop.memid);
 
 378                 wxPyEndAllowThreads(tstate);
 
 380                 if (!MSWVariantToVariant(v, wv) || PyErr_Occurred()) {
 
 382                     msg << _T("Unable to convert value to expected type: (")
 
 383                         << _VARTYPEname(prop.arg.vt) << _T(") for property <")
 
 385                     PyErr_SetString(PyExc_TypeError, msg.mb_str());
 
 388                 rval = _Variant2PyObj(wv);
 
 393         wxPyEndBlockThreads(blocked);
 
 398     // If both IsIn and isOut are false, assume it is actually an
 
 400     bool paramIsIn(const wxParamX& p)
 
 402         return p.IsIn() || (!p.IsIn() && !p.IsOut());
 
 406     // Call a method of the ActiveX object
 
 407     PyObject* _CallAXMethod(const wxString& name, PyObject* args)
 
 409         VARIANTARG *vargs = NULL;
 
 411         PyObject* rval = NULL;
 
 412         const wxFuncX& func = GetAXMethodDesc(name);
 
 414         wxPyBlock_t blocked = wxPyBeginBlockThreads();
 
 415         if (! PyErr_Occurred() ) {
 
 416             nargs = func.params.size();
 
 418                 vargs = new VARIANTARG[nargs];
 
 421                 // init type of vargs, in reverse order
 
 423                 for (i = 0; i < nargs; i++)
 
 424                     vargs[nargs - i - 1].vt = func.params[i].vt;
 
 426                 // Map the args coming from Python to the input parameters in vargs
 
 429                 while ( i<nargs && pi<PyTuple_Size(args) ) {
 
 430                     // Move to the next input param. 
 
 431                     if (! paramIsIn(func.params[i])) {
 
 435                     // convert the python object
 
 436                     PyObject* obj = PyTuple_GetItem(args, pi);
 
 437                     if (obj == Py_None) // special-case None?
 
 438                         vargs[nargs - i - 1].vt = VT_EMPTY;
 
 440                         wxVariant wxV = _PyObj2Variant(obj);
 
 441                         if (PyErr_Occurred())
 
 443                         if (!VariantToMSWVariant(wxV, vargs[nargs - i - 1]) || PyErr_Occurred()) {
 
 445                             msg << _T("Unable to convert value to expected type: (")
 
 446                                 << _VARTYPEname(vargs[nargs - i - 1].vt)
 
 447                                 << _T(") for parameter ") << i;
 
 448                             PyErr_SetString(PyExc_TypeError, msg.mb_str());
 
 458             PyThreadState* tstate = wxPyBeginAllowThreads();
 
 459             VARIANT rv = CallMethod(func.memid, vargs, nargs);
 
 460             wxPyEndAllowThreads(tstate);
 
 462             // Convert the return value and any out-params, ignoring
 
 463             // conversion errors for now
 
 465             MSWVariantToVariant(rv, wv);
 
 466             rval = _Variant2PyObj(wv, true);
 
 470                 // make a list and put the rval in it if it is not None
 
 471                 PyObject* lst = PyList_New(0);
 
 473                     PyList_Append(lst, rval);
 
 477                 // find the out params and convert them
 
 478                 for (int i = 0; i < nargs; i++) {
 
 479                     VARIANTARG& va = vargs[nargs - i - 1];
 
 480                     const wxParamX &px = func.params[i];
 
 482                         MSWVariantToVariant(va, wv);
 
 483                         PyObject* obj = _Variant2PyObj(wv, true);
 
 484                         PyList_Append(lst, obj);
 
 487                 rval = PyList_AsTuple(lst);
 
 490             if (PyErr_Occurred())
 
 494         wxPyEndBlockThreads(blocked);
 
 496             for (int i = 0; i < nargs; i++)
 
 497                 VariantClear(&vargs[i]);
 
 504 IMPLEMENT_ABSTRACT_CLASS( wxActiveXWindow, wxWindow );
 
 509 // Now tell SWIG about this new class that is implemented above.
 
 511 DocStr(wxActiveXWindow,
 
 512 "ActiveXWindow derives from wxWindow and the constructor accepts a
 
 513 CLSID for the ActiveX Control that should be created.  The
 
 514 ActiveXWindow class simply adds methods that allow you to query
 
 515 some of the TypeInfo exposed by the ActiveX object, and also to
 
 516 get/set properties or call methods by name.  The Python
 
 517 implementation automatically handles converting parameters and
 
 518 return values to/from the types expected by the ActiveX code as
 
 519 specified by the TypeInfo.
 
 523 MustHaveApp(wxActiveXWindow);
 
 525 class wxActiveXWindow : public wxWindow
 
 528     %pythonAppend wxActiveXWindow      "self._setOORInfo(self)"
 
 531         wxActiveXWindow( wxWindow* parent, const CLSID& clsId, wxWindowID id = -1,
 
 532                          const wxPoint& pos = wxDefaultPosition,
 
 533                          const wxSize& size = wxDefaultSize,
 
 535                          const wxString& name = wxPyPanelNameStr),
 
 536         "Creates an ActiveX control from the clsID given and makes it act
 
 537 as much like a regular wx.Window as possible.", "");
 
 540         const CLSID& , GetCLSID() const,
 
 541         "Return the CLSID used to construct this ActiveX window", "");
 
 545         int , GetAXEventCount() const,
 
 546         "Number of events defined for this control", "");
 
 549         const wxFuncX& , GetAXEventDesc(int idx) const,
 
 550         "Returns event description by index", "");
 
 554         int , GetAXPropCount() const,
 
 555         "Number of properties defined for this control", "");
 
 557     %nokwargs GetAXPropDesc;
 
 558     DocStr(GetPropDesc, "Returns property description by index or by name", "");
 
 559     const wxPropX& GetAXPropDesc(int idx) const;
 
 560     const wxPropX& GetAXPropDesc(const wxString& name) const;
 
 565         int , GetAXMethodCount() const,
 
 566         "Number of methods defined for this control", "");
 
 568     %nokwargs GetAXMethodDesc;
 
 569     DocStr(GetMethodDesc, "Returns method description by index or name", "");
 
 570     const wxFuncX& GetAXMethodDesc(int idx) const;
 
 571     const wxFuncX& GetAXMethodDesc(const wxString& name) const;
 
 575         const wxFuncXArray& , GetAXEvents(),
 
 576         "Returns a sequence of FuncX objects describing the events
 
 577 available for this ActiveX object.", "");
 
 580         const wxFuncXArray& , GetAXMethods(),
 
 581         "Returns a sequence of FuncX objects describing the methods
 
 582 available for this ActiveX object.", "");
 
 585         const wxPropXArray& , GetAXProperties(),
 
 586         "Returns a sequence of PropX objects describing the properties
 
 587 available for this ActiveX object.", "");
 
 592         void , SetAXProp(const wxString& name, PyObject* value),
 
 593         "Set a property of the ActiveX object by name.", "");
 
 597         PyObject* , GetAXProp(const wxString& name),
 
 598         "Get the value of an ActiveX property by name.", "");
 
 601     %nokwargs _CallAXMethod;
 
 603         PyObject* , _CallAXMethod(const wxString& name, PyObject* args),
 
 604         "The implementation for CallMethod.  Calls an ActiveX method, by
 
 605 name passing the parameters given in args.", "");
 
 607         def CallAXMethod(self, name, *args):
 
 609             Front-end for _CallMethod.  Simply passes all positional args
 
 610             after the name as a single tuple to _CallMethod.
 
 612             return self._CallAXMethod(name, args)
 
 616 //---------------------------------------------------------------------------
 
 620     wxEventType , RegisterActiveXEvent(const wxString& eventName),
 
 621     "Creates a standard wx event ID for the given eventName.", "");
 
 625 DocStr(wxActiveXEvent,
 
 626 "An instance of ActiveXEvent is sent to the handler for all bound
 
 627 ActiveX events.  Any event parameters from the ActiveX cntrol are
 
 628 turned into attributes of the Python proxy for this event object.
 
 629 Additionally, there is a property called eventName that will
 
 630 return (surprisingly <wink>) the name of the ActiveX event.", "");
 
 632 class wxActiveXEvent : public wxCommandEvent
 
 635     %feature("shadow") EventName "eventName = property(_activex.ActiveXEvent_EventName)";
 
 636     wxString EventName();
 
 640         // This is called by the EventThunker before calling the
 
 641         // handler. We'll convert and load the ActiveX event parameters into
 
 642         // attributes of the Python event object.
 
 643         void _preCallInit(PyObject* pyself) {
 
 644             wxPyBlock_t blocked = wxPyBeginBlockThreads();
 
 645             PyObject* pList = PyList_New(0);
 
 646             PyObject_SetAttrString(pyself, "paramList", pList);
 
 648             for (int i=0; i<self->ParamCount(); i+=1) {
 
 649                 PyObject* name = PyString_FromString((char*)(const char*)self->ParamName(i).mb_str());
 
 650                 PyObject* val = _Variant2PyObj((*self)[i], true);
 
 651                 PyObject_SetAttr(pyself, name, val);
 
 652                 PyList_Append(pList, name);
 
 656             wxPyEndBlockThreads(blocked);
 
 659         // This one is called by the EventThunker after calling the
 
 660         // handler. It reloads any "out" parameters from the python attributes
 
 661         // back into the wxVariant they came from.        
 
 662         void _postCallCleanup(PyObject* pyself) {
 
 663             wxPyBlock_t blocked = wxPyBeginBlockThreads();
 
 664             for (int i=0; i<self->ParamCount(); i+=1) {
 
 665                 PyObject* val = PyObject_GetAttrString(
 
 666                     pyself, (char*)(const char*)self->ParamName(i).mb_str());
 
 667                 _PyObj2Variant(val, (*self)[i]);
 
 670             wxPyEndBlockThreads(blocked);
 
 677 //---------------------------------------------------------------------------
 
 681 // Caller should already have the GIL!
 
 682 wxVariant _PyObj2Variant(PyObject* value)
 
 686     if (value == Py_None)
 
 689 #if PYTHON_API_VERSION >= 1012  // Python 2.3+
 
 690     else if (PyBool_Check(value))
 
 691         rval = (value == Py_True) ? true : false;
 
 694     else if (PyInt_Check(value))
 
 695         rval = PyInt_AS_LONG(value);
 
 697     else if (PyFloat_Check(value))
 
 698         rval = PyFloat_AS_DOUBLE(value);
 
 700     else if (PyString_Check(value) || PyUnicode_Check(value))
 
 701         rval = Py2wxString(value);
 
 703     // TODO:    PyList of strings --> wxArrayString
 
 709         PyErr_SetString(PyExc_TypeError, "Unsupported object type in _PyObj2Variant");
 
 716 // This one uses the type of the variant to try and force the conversion
 
 717 bool  _PyObj2Variant(PyObject* value, wxVariant& wv)
 
 719     wxString type = wv.GetType();
 
 721     if ( type == _T("long") || type == _T("bool") || type == _T("char") )
 
 722         wv = PyInt_AsLong(value);
 
 724     else if ( type == _T("string") )
 
 725         wv = Py2wxString(value);
 
 727     else if ( type == _T("double") )
 
 728         wv  = PyFloat_AsDouble(value);
 
 731         // it's some other type that we dont' handle yet.  Log it?
 
 737 // Caller should already have the GIL!
 
 738 PyObject* _Variant2PyObj(wxVariant& value, bool useNone)
 
 740     PyObject* rval = NULL;
 
 742     if (value.IsNull()) {
 
 747     // should "char" be treated as an int or as a string?
 
 748     else if (value.IsType(_T("char")) || value.IsType(_T("long")))
 
 749         rval = PyInt_FromLong(value);
 
 751     else if (value.IsType(_T("double")))
 
 752         rval = PyFloat_FromDouble(value);
 
 754     else if (value.IsType(_T("bool"))) {
 
 755         rval = (bool)value ? Py_True : Py_False;
 
 759     else if (value.IsType(_T("string")))
 
 760         rval = wx2PyString(value);
 
 768             PyErr_SetString(PyExc_TypeError, "Unsupported object type in _Variant2PyObj");
 
 775 wxString _VARTYPEname(VARTYPE vt)
 
 782         return _T("VT_VARIANT");
 
 802     // decimals are converted from doubles too
 
 810         return _T("wx.DateTime");
 
 816         return _T("VT_UNKNOWN");
 
 819         return _T("VT_DISPATCH");
 
 822         return _T("VT_EMPTY");
 
 825         return _T("VT_NULL");
 
 828         return _T("VT_VOID");
 
 832         msg << _T("unsupported type ") << vt;
 
 839 //---------------------------------------------------------------------------
 
 840 //---------------------------------------------------------------------------
 
 845 // A class derived from our wxActiveXWindow for the IE WebBrowser
 
 846 // control that will serve as a base class for a Python
 
 847 // implementation.  This is done so we can "eat our own dog food"
 
 848 // and use a class at least mostly generated by genaxmodule, but
 
 849 // also get some of the extra stuff like loading a document from
 
 850 // a string or a stream, getting text contents, etc. that
 
 851 // Lindsay's version gives us.
 
 854 #include <wx/mstream.h>
 
 856 #include <winerror.h>
 
 857 #include <exdispid.h>
 
 863 #include "IEHtmlStream.h"
 
 865 class wxIEHtmlWindowBase : public wxActiveXWindow {
 
 867     wxAutoOleInterface<IWebBrowser2>  m_webBrowser;
 
 869     DECLARE_ABSTRACT_CLASS(wxIEHtmlWindowBase);
 
 873     wxIEHtmlWindowBase ( wxWindow* parent, const CLSID& clsId, wxWindowID id = -1,
 
 874                          const wxPoint& pos = wxDefaultPosition,
 
 875                          const wxSize& size = wxDefaultSize,
 
 877                          const wxString& name = wxPyPanelNameStr)
 
 878         : wxActiveXWindow(parent, clsId, id, pos, size, style, name)
 
 882         // Get IWebBrowser2 Interface
 
 883         hret = m_webBrowser.QueryInterface(IID_IWebBrowser2, m_ActiveX);
 
 884         wxASSERT(SUCCEEDED(hret));
 
 887         m_webBrowser->put_MenuBar(VARIANT_FALSE);
 
 888         m_webBrowser->put_AddressBar(VARIANT_FALSE);
 
 889         m_webBrowser->put_StatusBar(VARIANT_FALSE);
 
 890         m_webBrowser->put_ToolBar(VARIANT_FALSE);
 
 892         m_webBrowser->put_RegisterAsBrowser(VARIANT_TRUE);
 
 893         m_webBrowser->put_RegisterAsDropTarget(VARIANT_TRUE);
 
 895         m_webBrowser->Navigate( L"about:blank", NULL, NULL, NULL, NULL );
 
 899     void SetCharset(const wxString& charset)
 
 904         IDispatch *pDisp = NULL;
 
 905         hret = m_webBrowser->get_Document(&pDisp);
 
 906         wxAutoOleInterface<IDispatch> disp(pDisp);
 
 910             wxAutoOleInterface<IHTMLDocument2> doc(IID_IHTMLDocument2, disp);
 
 912                 doc->put_charset((BSTR) (const wchar_t *) charset.wc_str(wxConvUTF8));
 
 913             //doc->put_charset((BSTR) wxConvUTF8.cMB2WC(charset).data());
 
 918     bool LoadString(const wxString& html)
 
 921         size_t len = html.length();
 
 922         len *= sizeof(wxChar);
 
 923         data = (char *) malloc(len);
 
 924         memcpy(data, html.c_str(), len);
 
 925         return LoadStream(new wxOwnedMemInputStream(data, len));
 
 929     bool LoadStream(IStreamAdaptorBase *pstrm)
 
 931         // need to prepend this as poxy MSHTML will not recognise a HTML comment
 
 932         // as starting a html document and treats it as plain text
 
 933         // Does nayone know how to force it to html mode ?
 
 935         // TODO: What to do in this case???
 
 937         pstrm->prepend = _T("<html>");
 
 940         // strip leading whitespace as it can confuse MSHTML
 
 941         wxAutoOleInterface<IStream> strm(pstrm);
 
 943         // Document Interface
 
 944         IDispatch *pDisp = NULL;
 
 945         HRESULT hret = m_webBrowser->get_Document(&pDisp);
 
 948         wxAutoOleInterface<IDispatch> disp(pDisp);
 
 951         // get IPersistStreamInit
 
 952         wxAutoOleInterface<IPersistStreamInit>
 
 953             pPersistStreamInit(IID_IPersistStreamInit, disp);
 
 955         if (pPersistStreamInit.Ok())
 
 957             HRESULT hr = pPersistStreamInit->InitNew();
 
 959                 hr = pPersistStreamInit->Load(strm);
 
 961             return SUCCEEDED(hr);
 
 967     bool LoadStream(wxInputStream *is)
 
 969         // wrap reference around stream
 
 970         IwxStreamAdaptor *pstrm = new IwxStreamAdaptor(is);
 
 973         return LoadStream(pstrm);
 
 977     wxString GetStringSelection(bool asHTML)
 
 979         wxAutoOleInterface<IHTMLTxtRange> tr(wxieGetSelRange(m_oleObject));
 
 981             return wxEmptyString;
 
 987             hr = tr->get_htmlText(&text);
 
 989             hr = tr->get_text(&text);
 
 991             return wxEmptyString;
 
 999     wxString GetText(bool asHTML)
 
1001         if (! m_webBrowser.Ok())
 
1002             return wxEmptyString;
 
1004         // get document dispatch interface
 
1005         IDispatch *iDisp = NULL;
 
1006         HRESULT hr = m_webBrowser->get_Document(&iDisp);
 
1008             return wxEmptyString;
 
1010         // Query for Document Interface
 
1011         wxAutoOleInterface<IHTMLDocument2> hd(IID_IHTMLDocument2, iDisp);
 
1015             return wxEmptyString;
 
1018         IHTMLElement *_body = NULL;
 
1019         hd->get_body(&_body);
 
1021             return wxEmptyString;
 
1022         wxAutoOleInterface<IHTMLElement> body(_body);
 
1029             hr = body->get_innerHTML(&text);
 
1031             hr = body->get_innerText(&text);
 
1033             return wxEmptyString;
 
1036         SysFreeString(text);
 
1042 //     void wxIEHtmlWin::SetEditMode(bool seton)
 
1044 //         m_bAmbientUserMode = ! seton;
 
1045 //         AmbientPropertyChanged(DISPID_AMBIENT_USERMODE);
 
1048 //     bool wxIEHtmlWin::GetEditMode()
 
1050 //         return ! m_bAmbientUserMode;
 
1054 IMPLEMENT_ABSTRACT_CLASS( wxIEHtmlWindowBase, wxActiveXWindow );
 
1059 // we'll document it in the derived Python class
 
1060 %feature("noautodoc") wxIEHtmlWindowBase;
 
1061 %feature("noautodoc") wxIEHtmlWindowBase::SetCharset;
 
1062 %feature("noautodoc") wxIEHtmlWindowBase::LoadString;
 
1063 %feature("noautodoc") wxIEHtmlWindowBase::LoadStream;
 
1064 %feature("noautodoc") wxIEHtmlWindowBase::GetStringSelection;
 
1065 %feature("noautodoc") wxIEHtmlWindowBase::GetText;
 
1068 MustHaveApp(wxIEHtmlWindowBase);
 
1070 class wxIEHtmlWindowBase : public wxActiveXWindow {
 
1072     %pythonAppend wxIEHtmlWindowBase    "self._setOORInfo(self)"
 
1074     wxIEHtmlWindowBase ( wxWindow* parent, const CLSID& clsId, wxWindowID id = -1,
 
1075                          const wxPoint& pos = wxDefaultPosition,
 
1076                          const wxSize& size = wxDefaultSize,
 
1078                          const wxString& name = wxPyPanelNameStr);
 
1080     void SetCharset(const wxString& charset);
 
1081     bool LoadString(const wxString& html);
 
1082     bool LoadStream(wxInputStream *is);
 
1083     wxString GetStringSelection(bool asHTML);
 
1084     wxString GetText(bool asHTML);
 
1098 enum wxIEHtmlRefreshLevel
 
1100     wxIEHTML_REFRESH_NORMAL = 0,
 
1101     wxIEHTML_REFRESH_IFEXPIRED = 1,
 
1102     wxIEHTML_REFRESH_CONTINUE = 2,
 
1103     wxIEHTML_REFRESH_COMPLETELY = 3
 
1108 class wxIEHtmlWin : public wxWindow 
 
1111     %pythonAppend wxIEHtmlWin      "self._setOORInfo(self)"
 
1113     wxIEHtmlWin(wxWindow * parent, wxWindowID id = -1,
 
1114                 const wxPoint& pos = wxDefaultPosition,
 
1115                 const wxSize& size = wxDefaultSize,
 
1117                 const wxString& name = wxPyPanelNameStr);
 
1119     void LoadUrl(const wxString& url);
 
1120     bool LoadString(wxString html);
 
1121     bool LoadStream(wxInputStream *is);
 
1123     %pythoncode { Navigate = LoadUrl }
 
1125     void SetCharset(wxString charset);
 
1126     void SetEditMode(bool seton);
 
1128     wxString GetStringSelection(bool asHTML = false);
 
1129     wxString GetText(bool asHTML = false);
 
1135     %name(RefreshPage)bool Refresh(wxIEHtmlRefreshLevel level);
 
1142 wxEVT_COMMAND_MSHTML_BEFORENAVIGATE2  = RegisterActiveXEvent('BeforeNavigate2')
 
1143 wxEVT_COMMAND_MSHTML_NEWWINDOW2       = RegisterActiveXEvent('NewWindow2')
 
1144 wxEVT_COMMAND_MSHTML_DOCUMENTCOMPLETE = RegisterActiveXEvent('DocumentComplete')
 
1145 wxEVT_COMMAND_MSHTML_PROGRESSCHANGE   = RegisterActiveXEvent('ProgressChange')
 
1146 wxEVT_COMMAND_MSHTML_STATUSTEXTCHANGE = RegisterActiveXEvent('StatusTextChange')
 
1147 wxEVT_COMMAND_MSHTML_TITLECHANGE      = RegisterActiveXEvent('TitleChange')
 
1149 EVT_MSHTML_BEFORENAVIGATE2      = wx.PyEventBinder(wxEVT_COMMAND_MSHTML_BEFORENAVIGATE2, 1)
 
1150 EVT_MSHTML_NEWWINDOW2           = wx.PyEventBinder(wxEVT_COMMAND_MSHTML_NEWWINDOW2, 1)
 
1151 EVT_MSHTML_DOCUMENTCOMPLETE     = wx.PyEventBinder(wxEVT_COMMAND_MSHTML_DOCUMENTCOMPLETE, 1)
 
1152 EVT_MSHTML_PROGRESSCHANGE       = wx.PyEventBinder(wxEVT_COMMAND_MSHTML_PROGRESSCHANGE, 1)
 
1153 EVT_MSHTML_STATUSTEXTCHANGE     = wx.PyEventBinder(wxEVT_COMMAND_MSHTML_STATUSTEXTCHANGE, 1)
 
1154 EVT_MSHTML_TITLECHANGE          = wx.PyEventBinder(wxEVT_COMMAND_MSHTML_TITLECHANGE, 1)
 
1159 //---------------------------------------------------------------------------
 
1160 // Include some extra Python code into the proxy module
 
1162 %pythoncode "_activex_ex.py"
 
1164 //---------------------------------------------------------------------------