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);
 
  33 //---------------------------------------------------------------------------
 
  35 typedef unsigned short  USHORT;
 
  37 typedef long            MEMBERID;
 
  38 typedef unsigned short  VARTYPE;
 
  42 // Since SWIG doesn't support nested classes, we need to fool it a bit
 
  43 // and make them look like global classes.  These defines make the C++ code
 
  44 // know what we are doing.
 
  45 #define wxParamX        wxActiveX::ParamX
 
  46 #define wxFuncX         wxActiveX::FuncX
 
  47 #define wxPropX         wxActiveX::PropX
 
  48 #define wxParamXArray   wxActiveX::ParamXArray
 
  49 #define wxFuncXArray    wxActiveX::FuncXArray
 
  50 #define wxPropXArray    wxActiveX::PropXArray
 
  55 // Some conversion helpers
 
  56 static wxVariant _PyObj2Variant(PyObject* value);
 
  57 static bool  _PyObj2Variant(PyObject* value, wxVariant& wv);
 
  58 static PyObject* _Variant2PyObj(wxVariant& value, bool useNone=false);
 
  59 static wxString  _VARTYPEname(VARTYPE vt);
 
  61 // Check if an exception has been raised  (blocking threads)
 
  62 inline bool wxPyErr_Occurred()
 
  65     wxPyBlock_t blocked = wxPyBeginBlockThreads();
 
  66     rval = PyErr_Occurred() != NULL;
 
  67     wxPyEndBlockThreads(blocked);
 
  73 //---------------------------------------------------------------------------
 
  77 "This class wraps the Windows CLSID structure and is used to
 
  78 specify the class of the ActiveX object that is to be created.  A
 
  79 CLSID can be constructed from either a ProgID string, (such as
 
  80 'WordPad.Document.1') or a classID string, (such as
 
  81 '{CA8A9783-280D-11CF-A24D-444553540000}').", "");
 
  86         CLSID(const wxString& id)
 
  89             CLSID* self = new CLSID;
 
  90             memset(self, 0, sizeof(CLSID));
 
  92             if (id[0] == _T('{')) {
 
  93                 // Looks like a classID string
 
  96                         (LPOLESTR)(const wchar_t *)id.wc_str(wxConvUTF8),
 
 102                         (LPOLESTR)(const wchar_t *)id.wc_str(wxConvUTF8),
 
 105             if (result != NOERROR) {
 
 106                 wxPyErr_SetString(PyExc_ValueError, "Not a recognized classID or progID");
 
 113         ~CLSID() { delete self; }
 
 115         wxString GetCLSIDString()
 
 119             if (StringFromCLSID(*self, &s) == S_OK) {
 
 124                 str = _T("Error!");  // TODO: raise exception?
 
 128         wxString GetProgIDString()
 
 132             if (ProgIDFromCLSID(*self, &s) == S_OK) {
 
 137                 str = _T("Error!"); // TODO: raise exception?
 
 142     %pythoncode { def __str__(self):   return self.GetCLSIDString() }
 
 146 //---------------------------------------------------------------------------
 
 149 %define MAKE_ARRAY_WRAPPER(basetype, arrayname)
 
 154         bool __nonzero__()          { return self->size() > 0; }
 
 155         int  __len__()              { return self->size(); }
 
 157         const basetype& __getitem__(int idx) {
 
 158             if ( idx >= 0 && idx < self->size() )
 
 161                 static basetype BadVal;
 
 162                 wxPyErr_SetString(PyExc_IndexError, "Index out of range");
 
 171 //---------------------------------------------------------------------------
 
 185     %feature("shadow") vt_type_get "vt_type = property(_activex.ParamX_vt_type_get)";
 
 186     %extend { wxString vt_type_get() { return _VARTYPEname(self->vt); } }
 
 188     %feature("shadow") IsIn     "isIn = property(_activex.ParamX_IsIn)";
 
 189     %feature("shadow") IsOut    "isOut = property(_activex.ParamX_IsOut)";
 
 190     %feature("shadow") IsRetVal "isRetVal = property(_activex.ParamX_IsRetVal)";
 
 193     bool IsRetVal() const;
 
 206     wxParamXArray params;
 
 219     %feature("shadow") CanGet "canGet = property(_activex.PropX_CanGet)";
 
 220     %feature("shadow") CanSet "canSet = property(_activex.PropX_CanSet)";
 
 227 MAKE_ARRAY_WRAPPER(wxParamX, wxParamXArray);
 
 228 MAKE_ARRAY_WRAPPER(wxFuncX, wxFuncXArray);
 
 229 MAKE_ARRAY_WRAPPER(wxPropX, wxPropXArray);
 
 232 //---------------------------------------------------------------------------
 
 236 // C++ version of a Python-aware wxActiveX    
 
 237 class wxActiveXWindow : public wxActiveX
 
 242     DECLARE_ABSTRACT_CLASS(wxActiveXWindow);
 
 245     wxActiveXWindow( wxWindow* parent, const CLSID& clsId, wxWindowID id = -1,
 
 246                      const wxPoint& pos = wxDefaultPosition,
 
 247                      const wxSize& size = wxDefaultSize,
 
 249                      const wxString& name = wxPyPanelNameStr)
 
 250         : wxActiveX(parent, clsId, id, pos, size, style, name)
 
 255     const CLSID& GetCLSID() const { return m_CLSID; }
 
 258     // Renamed versions of some base class methods that delegate
 
 259     // to the base where appropriate, and raise Python exceptions
 
 261     int GetAXEventCount() const  { return wxActiveX::GetEventCount(); }
 
 262     int GetAXPropCount() const   { return wxActiveX::GetPropCount(); }
 
 263     int GetAXMethodCount() const { return wxActiveX::GetMethodCount(); }
 
 265     const wxFuncX& GetAXEventDesc(int idx) const
 
 267         static wxFuncX BadVal;
 
 268         if (idx < 0 || idx >= GetAXEventCount()) {
 
 269             wxPyErr_SetString(PyExc_IndexError, "Index out of range");
 
 272         return m_events[idx];
 
 274     const wxFuncX& GetAXMethodDesc(int idx) const
 
 276         static wxFuncX BadVal;
 
 277         if (idx < 0 || idx >= GetAXMethodCount()) {
 
 278             wxPyErr_SetString(PyExc_IndexError, "Index out of range");
 
 281         return m_methods[idx];
 
 283     const wxPropX& GetAXPropDesc(int idx) const
 
 285         static wxPropX BadVal;
 
 286         if (idx < 0 || idx >= GetAXPropCount()) {
 
 287             wxPyErr_SetString(PyExc_IndexError, "Index out of range");
 
 293     const wxFuncX& GetAXMethodDesc(const wxString& name) const
 
 295         NameMap::const_iterator it = m_methodNames.find(name);
 
 296         if (it == m_methodNames.end())     {
 
 298             msg << _T("method <") << name << _T("> not found");
 
 299             wxPyErr_SetString(PyExc_KeyError, msg.mb_str());
 
 300             static wxFuncX BadVal;
 
 303         return GetAXMethodDesc(it->second);
 
 305     const wxPropX& GetAXPropDesc(const wxString& name) const
 
 307         NameMap::const_iterator it = m_propNames.find(name);
 
 308         if (it == m_propNames.end())     {
 
 310             msg << _T("property <") << name << _T("> not found");
 
 311             wxPyErr_SetString(PyExc_KeyError, msg.mb_str());
 
 312             static wxPropX BadVal;
 
 315         return GetAXPropDesc(it->second);
 
 318     // Accessors for the internal vectors of events, methods and
 
 319     // proprties.  Can be used as sequence like objects from
 
 321     const wxFuncXArray& GetAXEvents()      { return m_events; }
 
 322     const wxFuncXArray& GetAXMethods()     { return m_methods; }
 
 323     const wxPropXArray& GetAXProperties()  { return m_props; }
 
 326     // Set a property from a Python object
 
 327     void SetAXProp(const wxString& name, PyObject* value)
 
 329         const wxPropX& prop = GetAXPropDesc(name);
 
 330         wxPyBlock_t blocked = wxPyBeginBlockThreads();
 
 331         if (! PyErr_Occurred() ) {
 
 332             if (! prop.CanSet()) {
 
 334                 msg << _T("property <") << name << _T("> is readonly");
 
 335                 PyErr_SetString(PyExc_TypeError, msg.mb_str());
 
 338                 wxVariant wxV = _PyObj2Variant(value);
 
 339                 if (PyErr_Occurred())
 
 341                 VARIANT v = {prop.arg.vt};
 
 342                 if (!VariantToMSWVariant(wxV, v) || PyErr_Occurred()) {
 
 344                     msg << _T("Unable to convert value to expected type: (")
 
 345                         << _VARTYPEname(prop.arg.vt) << _T(") for property <")
 
 347                     PyErr_SetString(PyExc_TypeError, msg.mb_str());
 
 350                 PyThreadState* tstate = wxPyBeginAllowThreads();
 
 351                 SetProp(prop.memid, v);
 
 353                 wxPyEndAllowThreads(tstate);
 
 357         wxPyEndBlockThreads(blocked);
 
 361     // Get a property and convert it to a Python object
 
 362     PyObject* GetAXProp(const wxString& name)
 
 364         PyObject* rval = NULL;
 
 365         const wxPropX& prop = GetAXPropDesc(name);
 
 366         wxPyBlock_t blocked = wxPyBeginBlockThreads();
 
 367         if (! PyErr_Occurred() ) {
 
 368             if (! prop.CanGet()) {
 
 370                 msg << _T("property <") << name << _T("> is writeonly");
 
 371                 PyErr_SetString(PyExc_TypeError, msg.mb_str());
 
 374                 PyThreadState* tstate = wxPyBeginAllowThreads();
 
 375                 VARIANT v = GetPropAsVariant(prop.memid);
 
 376                 wxPyEndAllowThreads(tstate);
 
 378                 if (!MSWVariantToVariant(v, wv) || PyErr_Occurred()) {
 
 380                     msg << _T("Unable to convert value to expected type: (")
 
 381                         << _VARTYPEname(prop.arg.vt) << _T(") for property <")
 
 383                     PyErr_SetString(PyExc_TypeError, msg.mb_str());
 
 386                 rval = _Variant2PyObj(wv);
 
 391         wxPyEndBlockThreads(blocked);
 
 396     // If both IsIn and isOut are false, assume it is actually an
 
 398     bool paramIsIn(const wxParamX& p)
 
 400         return p.IsIn() || (!p.IsIn() && !p.IsOut());
 
 404     // Call a method of the ActiveX object
 
 405     PyObject* _CallAXMethod(const wxString& name, PyObject* args)
 
 407         VARIANTARG *vargs = NULL;
 
 409         PyObject* rval = NULL;
 
 410         const wxFuncX& func = GetAXMethodDesc(name);
 
 412         wxPyBlock_t blocked = wxPyBeginBlockThreads();
 
 413         if (! PyErr_Occurred() ) {
 
 414             nargs = func.params.size();
 
 416                 vargs = new VARIANTARG[nargs];
 
 419                 // init type of vargs, in reverse order
 
 421                 for (i = 0; i < nargs; i++)
 
 422                     vargs[nargs - i - 1].vt = func.params[i].vt;
 
 424                 // Map the args coming from Python to the input parameters in vargs
 
 427                 while ( i<nargs && pi<PyTuple_Size(args) ) {
 
 428                     // Move to the next input param. 
 
 429                     if (! paramIsIn(func.params[i])) {
 
 433                     // convert the python object
 
 434                     PyObject* obj = PyTuple_GetItem(args, pi);
 
 435                     if (obj == Py_None) // special-case None?
 
 436                         vargs[nargs - i - 1].vt = VT_EMPTY;
 
 438                         wxVariant wxV = _PyObj2Variant(obj);
 
 439                         if (PyErr_Occurred())
 
 441                         if (!VariantToMSWVariant(wxV, vargs[nargs - i - 1]) || PyErr_Occurred()) {
 
 443                             msg << _T("Unable to convert value to expected type: (")
 
 444                                 << _VARTYPEname(vargs[nargs - i - 1].vt)
 
 445                                 << _T(") for parameter ") << i;
 
 446                             PyErr_SetString(PyExc_TypeError, msg.mb_str());
 
 456             PyThreadState* tstate = wxPyBeginAllowThreads();
 
 457             VARIANT rv = CallMethod(func.memid, vargs, nargs);
 
 458             wxPyEndAllowThreads(tstate);
 
 460             // Convert the return value and any out-params, ignoring
 
 461             // conversion errors for now
 
 463             MSWVariantToVariant(rv, wv);
 
 464             rval = _Variant2PyObj(wv, true);
 
 468                 // make a list and put the rval in it if it is not None
 
 469                 PyObject* lst = PyList_New(0);
 
 471                     PyList_Append(lst, rval);
 
 475                 // find the out params and convert them
 
 476                 for (int i = 0; i < nargs; i++) {
 
 477                     VARIANTARG& va = vargs[nargs - i - 1];
 
 478                     const wxParamX &px = func.params[i];
 
 480                         MSWVariantToVariant(va, wv);
 
 481                         PyObject* obj = _Variant2PyObj(wv, true);
 
 482                         PyList_Append(lst, obj);
 
 485                 rval = PyList_AsTuple(lst);
 
 488             if (PyErr_Occurred())
 
 492         wxPyEndBlockThreads(blocked);
 
 494             for (int i = 0; i < nargs; i++)
 
 495                 VariantClear(&vargs[i]);
 
 502 IMPLEMENT_ABSTRACT_CLASS( wxActiveXWindow, wxWindow );
 
 507 // Now tell SWIG about this new class that is implemented above.
 
 509 DocStr(wxActiveXWindow,
 
 510 "ActiveXWindow derives from wxWindow and the constructor accepts a
 
 511 CLSID for the ActiveX Control that should be created.  The
 
 512 ActiveXWindow class simply adds methods that allow you to query
 
 513 some of the TypeInfo exposed by the ActiveX object, and also to
 
 514 get/set properties or call methods by name.  The Python
 
 515 implementation automatically handles converting parameters and
 
 516 return values to/from the types expected by the ActiveX code as
 
 517 specified by the TypeInfo.
 
 521 MustHaveApp(wxActiveXWindow);
 
 523 class wxActiveXWindow : public wxWindow
 
 526     %pythonAppend wxActiveXWindow      "self._setOORInfo(self)"
 
 529         wxActiveXWindow( wxWindow* parent, const CLSID& clsId, wxWindowID id = -1,
 
 530                          const wxPoint& pos = wxDefaultPosition,
 
 531                          const wxSize& size = wxDefaultSize,
 
 533                          const wxString& name = wxPyPanelNameStr),
 
 534         "Creates an ActiveX control from the clsID given and makes it act
 
 535 as much like a regular wx.Window as possible.", "");
 
 538         const CLSID& , GetCLSID() const,
 
 539         "Return the CLSID used to construct this ActiveX window", "");
 
 543         int , GetAXEventCount() const,
 
 544         "Number of events defined for this control", "");
 
 547         const wxFuncX& , GetAXEventDesc(int idx) const,
 
 548         "Returns event description by index", "");
 
 552         int , GetAXPropCount() const,
 
 553         "Number of properties defined for this control", "");
 
 555     %nokwargs GetAXPropDesc;
 
 556     DocStr(GetPropDesc, "Returns property description by index or by name", "");
 
 557     const wxPropX& GetAXPropDesc(int idx) const;
 
 558     const wxPropX& GetAXPropDesc(const wxString& name) const;
 
 563         int , GetAXMethodCount() const,
 
 564         "Number of methods defined for this control", "");
 
 566     %nokwargs GetAXMethodDesc;
 
 567     DocStr(GetMethodDesc, "Returns method description by index or name", "");
 
 568     const wxFuncX& GetAXMethodDesc(int idx) const;
 
 569     const wxFuncX& GetAXMethodDesc(const wxString& name) const;
 
 573         const wxFuncXArray& , GetAXEvents(),
 
 574         "Returns a sequence of FuncX objects describing the events
 
 575 available for this ActiveX object.", "");
 
 578         const wxFuncXArray& , GetAXMethods(),
 
 579         "Returns a sequence of FuncX objects describing the methods
 
 580 available for this ActiveX object.", "");
 
 583         const wxPropXArray& , GetAXProperties(),
 
 584         "Returns a sequence of PropX objects describing the properties
 
 585 available for this ActiveX object.", "");
 
 590         void , SetAXProp(const wxString& name, PyObject* value),
 
 591         "Set a property of the ActiveX object by name.", "");
 
 595         PyObject* , GetAXProp(const wxString& name),
 
 596         "Get the value of an ActiveX property by name.", "");
 
 599     %nokwargs _CallAXMethod;
 
 601         PyObject* , _CallAXMethod(const wxString& name, PyObject* args),
 
 602         "The implementation for CallMethod.  Calls an ActiveX method, by
 
 603 name passing the parameters given in args.", "");
 
 605         def CallAXMethod(self, name, *args):
 
 607             Front-end for _CallMethod.  Simply passes all positional args
 
 608             after the name as a single tuple to _CallMethod.
 
 610             return self._CallAXMethod(name, args)
 
 614 //---------------------------------------------------------------------------
 
 618     wxEventType , RegisterActiveXEvent(const wxString& eventName),
 
 619     "Creates a standard wx event ID for the given eventName.", "");
 
 623 DocStr(wxActiveXEvent,
 
 624 "An instance of ActiveXEvent is sent to the handler for all bound
 
 625 ActiveX events.  Any event parameters from the ActiveX cntrol are
 
 626 turned into attributes of the Python proxy for this event object.
 
 627 Additionally, there is a property called eventName that will
 
 628 return (surprisingly <wink>) the name of the ActiveX event.", "");
 
 630 class wxActiveXEvent : public wxCommandEvent
 
 633     %feature("shadow") EventName "eventName = property(_activex.ActiveXEvent_EventName)";
 
 634     wxString EventName();
 
 638         // This is called by the EventThunker before calling the
 
 639         // handler. We'll convert and load the ActiveX event parameters into
 
 640         // attributes of the Python event object.
 
 641         void _preCallInit(PyObject* pyself) {
 
 642             wxPyBlock_t blocked = wxPyBeginBlockThreads();
 
 643             PyObject* pList = PyList_New(0);
 
 644             PyObject_SetAttrString(pyself, "paramList", pList);
 
 646             for (int i=0; i<self->ParamCount(); i+=1) {
 
 647                 PyObject* name = PyString_FromString((char*)(const char*)self->ParamName(i).mb_str());
 
 648                 PyObject* val = _Variant2PyObj((*self)[i], true);
 
 649                 PyObject_SetAttr(pyself, name, val);
 
 650                 PyList_Append(pList, name);
 
 654             wxPyEndBlockThreads(blocked);
 
 657         // This one is called by the EventThunker after calling the
 
 658         // handler. It reloads any "out" parameters from the python attributes
 
 659         // back into the wxVariant they came from.        
 
 660         void _postCallCleanup(PyObject* pyself) {
 
 661             wxPyBlock_t blocked = wxPyBeginBlockThreads();
 
 662             for (int i=0; i<self->ParamCount(); i+=1) {
 
 663                 PyObject* val = PyObject_GetAttrString(
 
 664                     pyself, (char*)(const char*)self->ParamName(i).mb_str());
 
 665                 _PyObj2Variant(val, (*self)[i]);
 
 668             wxPyEndBlockThreads(blocked);
 
 675 //---------------------------------------------------------------------------
 
 679 // Caller should already have the GIL!
 
 680 wxVariant _PyObj2Variant(PyObject* value)
 
 684     if (value == Py_None)
 
 687 #if PYTHON_API_VERSION >= 1012  // Python 2.3+
 
 688     else if (PyBool_Check(value))
 
 689         rval = (value == Py_True) ? true : false;
 
 692     else if (PyInt_Check(value))
 
 693         rval = PyInt_AS_LONG(value);
 
 695     else if (PyFloat_Check(value))
 
 696         rval = PyFloat_AS_DOUBLE(value);
 
 698     else if (PyString_Check(value) || PyUnicode_Check(value))
 
 699         rval = Py2wxString(value);
 
 701     // TODO:    PyList of strings --> wxArrayString
 
 707         PyErr_SetString(PyExc_TypeError, "Unsupported object type in _PyObj2Variant");
 
 714 // This one uses the type of the variant to try and force the conversion
 
 715 bool  _PyObj2Variant(PyObject* value, wxVariant& wv)
 
 717     wxString type = wv.GetType();
 
 719     if ( type == _T("long") || type == _T("bool") || type == _T("char") )
 
 720         wv = PyInt_AsLong(value);
 
 722     else if ( type == _T("string") )
 
 723         wv = Py2wxString(value);
 
 725     else if ( type == _T("double") )
 
 726         wv  = PyFloat_AsDouble(value);
 
 729         // it's some other type that we dont' handle yet.  Log it?
 
 735 // Caller should already have the GIL!
 
 736 PyObject* _Variant2PyObj(wxVariant& value, bool useNone)
 
 738     PyObject* rval = NULL;
 
 740     if (value.IsNull()) {
 
 745     // should "char" be treated as an int or as a string?
 
 746     else if (value.IsType(_T("char")) || value.IsType(_T("long")))
 
 747         rval = PyInt_FromLong(value);
 
 749     else if (value.IsType(_T("double")))
 
 750         rval = PyFloat_FromDouble(value);
 
 752     else if (value.IsType(_T("bool"))) {
 
 753         rval = (bool)value ? Py_True : Py_False;
 
 757     else if (value.IsType(_T("string")))
 
 758         rval = wx2PyString(value);
 
 766             PyErr_SetString(PyExc_TypeError, "Unsupported object type in _Variant2PyObj");
 
 773 wxString _VARTYPEname(VARTYPE vt)
 
 780         return _T("VT_VARIANT");
 
 800     // decimals are converted from doubles too
 
 808         return _T("wx.DateTime");
 
 814         return _T("VT_UNKNOWN");
 
 817         return _T("VT_DISPATCH");
 
 820         return _T("VT_EMPTY");
 
 823         return _T("VT_NULL");
 
 826         return _T("VT_VOID");
 
 830         msg << _T("unsupported type ") << vt;
 
 837 //---------------------------------------------------------------------------
 
 838 //---------------------------------------------------------------------------
 
 843 // A class derived from our wxActiveXWindow for the IE WebBrowser
 
 844 // control that will serve as a base class for a Python
 
 845 // implementation.  This is done so we can "eat our own dog food"
 
 846 // and use a class at least mostly generated by genaxmodule, but
 
 847 // also get some of the extra stuff like loading a document from
 
 848 // a string or a stream, getting text contents, etc. that
 
 849 // Lindsay's version gives us.
 
 852 #include <wx/mstream.h>
 
 854 #include <winerror.h>
 
 855 #include <exdispid.h>
 
 861 #include "IEHtmlStream.h"
 
 863 class wxIEHtmlWindowBase : public wxActiveXWindow {
 
 865     wxAutoOleInterface<IWebBrowser2>  m_webBrowser;
 
 867     DECLARE_ABSTRACT_CLASS(wxIEHtmlWindowBase);
 
 871     wxIEHtmlWindowBase ( wxWindow* parent, const CLSID& clsId, wxWindowID id = -1,
 
 872                          const wxPoint& pos = wxDefaultPosition,
 
 873                          const wxSize& size = wxDefaultSize,
 
 875                          const wxString& name = wxPyPanelNameStr)
 
 876         : wxActiveXWindow(parent, clsId, id, pos, size, style, name)
 
 880         // Get IWebBrowser2 Interface
 
 881         hret = m_webBrowser.QueryInterface(IID_IWebBrowser2, m_ActiveX);
 
 882         wxASSERT(SUCCEEDED(hret));
 
 885         m_webBrowser->put_MenuBar(VARIANT_FALSE);
 
 886         m_webBrowser->put_AddressBar(VARIANT_FALSE);
 
 887         m_webBrowser->put_StatusBar(VARIANT_FALSE);
 
 888         m_webBrowser->put_ToolBar(VARIANT_FALSE);
 
 890         m_webBrowser->put_RegisterAsBrowser(VARIANT_TRUE);
 
 891         m_webBrowser->put_RegisterAsDropTarget(VARIANT_TRUE);
 
 893         m_webBrowser->Navigate( L"about:blank", NULL, NULL, NULL, NULL );
 
 897     void SetCharset(const wxString& charset)
 
 902         IDispatch *pDisp = NULL;
 
 903         hret = m_webBrowser->get_Document(&pDisp);
 
 904         wxAutoOleInterface<IDispatch> disp(pDisp);
 
 908             wxAutoOleInterface<IHTMLDocument2> doc(IID_IHTMLDocument2, disp);
 
 910                 doc->put_charset((BSTR) (const wchar_t *) charset.wc_str(wxConvUTF8));
 
 911             //doc->put_charset((BSTR) wxConvUTF8.cMB2WC(charset).data());
 
 916     bool LoadString(const wxString& html)
 
 919         size_t len = html.length();
 
 920         len *= sizeof(wxChar);
 
 921         data = (char *) malloc(len);
 
 922         memcpy(data, html.c_str(), len);
 
 923         return LoadStream(new wxOwnedMemInputStream(data, len));
 
 927     bool LoadStream(IStreamAdaptorBase *pstrm)
 
 929         // need to prepend this as poxy MSHTML will not recognise a HTML comment
 
 930         // as starting a html document and treats it as plain text
 
 931         // Does nayone know how to force it to html mode ?
 
 933         // TODO: What to do in this case???
 
 935         pstrm->prepend = _T("<html>");
 
 938         // strip leading whitespace as it can confuse MSHTML
 
 939         wxAutoOleInterface<IStream> strm(pstrm);
 
 941         // Document Interface
 
 942         IDispatch *pDisp = NULL;
 
 943         HRESULT hret = m_webBrowser->get_Document(&pDisp);
 
 946         wxAutoOleInterface<IDispatch> disp(pDisp);
 
 949         // get IPersistStreamInit
 
 950         wxAutoOleInterface<IPersistStreamInit>
 
 951             pPersistStreamInit(IID_IPersistStreamInit, disp);
 
 953         if (pPersistStreamInit.Ok())
 
 955             HRESULT hr = pPersistStreamInit->InitNew();
 
 957                 hr = pPersistStreamInit->Load(strm);
 
 959             return SUCCEEDED(hr);
 
 965     bool LoadStream(wxInputStream *is)
 
 967         // wrap reference around stream
 
 968         IwxStreamAdaptor *pstrm = new IwxStreamAdaptor(is);
 
 971         return LoadStream(pstrm);
 
 975     wxString GetStringSelection(bool asHTML)
 
 977         wxAutoOleInterface<IHTMLTxtRange> tr(wxieGetSelRange(m_oleObject));
 
 979             return wxEmptyString;
 
 985             hr = tr->get_htmlText(&text);
 
 987             hr = tr->get_text(&text);
 
 989             return wxEmptyString;
 
 997     wxString GetText(bool asHTML)
 
 999         if (! m_webBrowser.Ok())
 
1000             return wxEmptyString;
 
1002         // get document dispatch interface
 
1003         IDispatch *iDisp = NULL;
 
1004         HRESULT hr = m_webBrowser->get_Document(&iDisp);
 
1006             return wxEmptyString;
 
1008         // Query for Document Interface
 
1009         wxAutoOleInterface<IHTMLDocument2> hd(IID_IHTMLDocument2, iDisp);
 
1013             return wxEmptyString;
 
1016         IHTMLElement *_body = NULL;
 
1017         hd->get_body(&_body);
 
1019             return wxEmptyString;
 
1020         wxAutoOleInterface<IHTMLElement> body(_body);
 
1027             hr = body->get_innerHTML(&text);
 
1029             hr = body->get_innerText(&text);
 
1031             return wxEmptyString;
 
1034         SysFreeString(text);
 
1040 //     void wxIEHtmlWin::SetEditMode(bool seton)
 
1042 //         m_bAmbientUserMode = ! seton;
 
1043 //         AmbientPropertyChanged(DISPID_AMBIENT_USERMODE);
 
1046 //     bool wxIEHtmlWin::GetEditMode()
 
1048 //         return ! m_bAmbientUserMode;
 
1052 IMPLEMENT_ABSTRACT_CLASS( wxIEHtmlWindowBase, wxActiveXWindow );
 
1057 // we'll document it in the derived Python class
 
1058 %feature("noautodoc") wxIEHtmlWindowBase;
 
1059 %feature("noautodoc") wxIEHtmlWindowBase::SetCharset;
 
1060 %feature("noautodoc") wxIEHtmlWindowBase::LoadString;
 
1061 %feature("noautodoc") wxIEHtmlWindowBase::LoadStream;
 
1062 %feature("noautodoc") wxIEHtmlWindowBase::GetStringSelection;
 
1063 %feature("noautodoc") wxIEHtmlWindowBase::GetText;
 
1066 MustHaveApp(wxIEHtmlWindowBase);
 
1068 class wxIEHtmlWindowBase : public wxActiveXWindow {
 
1070     %pythonAppend wxIEHtmlWindowBase    "self._setOORInfo(self)"
 
1072     wxIEHtmlWindowBase ( wxWindow* parent, const CLSID& clsId, wxWindowID id = -1,
 
1073                          const wxPoint& pos = wxDefaultPosition,
 
1074                          const wxSize& size = wxDefaultSize,
 
1076                          const wxString& name = wxPyPanelNameStr);
 
1078     void SetCharset(const wxString& charset);
 
1079     bool LoadString(const wxString& html);
 
1080     bool LoadStream(wxInputStream *is);
 
1081     wxString GetStringSelection(bool asHTML);
 
1082     wxString GetText(bool asHTML);
 
1096 enum wxIEHtmlRefreshLevel
 
1098     wxIEHTML_REFRESH_NORMAL = 0,
 
1099     wxIEHTML_REFRESH_IFEXPIRED = 1,
 
1100     wxIEHTML_REFRESH_CONTINUE = 2,
 
1101     wxIEHTML_REFRESH_COMPLETELY = 3
 
1106 class wxIEHtmlWin : public wxWindow 
 
1109     %pythonAppend wxIEHtmlWin      "self._setOORInfo(self)"
 
1111     wxIEHtmlWin(wxWindow * parent, wxWindowID id = -1,
 
1112                 const wxPoint& pos = wxDefaultPosition,
 
1113                 const wxSize& size = wxDefaultSize,
 
1115                 const wxString& name = wxPyPanelNameStr);
 
1117     void LoadUrl(const wxString& url);
 
1118     bool LoadString(wxString html);
 
1119     bool LoadStream(wxInputStream *is);
 
1121     %pythoncode { Navigate = LoadUrl }
 
1123     void SetCharset(wxString charset);
 
1124     void SetEditMode(bool seton);
 
1126     wxString GetStringSelection(bool asHTML = false);
 
1127     wxString GetText(bool asHTML = false);
 
1133     %name(RefreshPage)bool Refresh(wxIEHtmlRefreshLevel level);
 
1140 wxEVT_COMMAND_MSHTML_BEFORENAVIGATE2  = RegisterActiveXEvent('BeforeNavigate2')
 
1141 wxEVT_COMMAND_MSHTML_NEWWINDOW2       = RegisterActiveXEvent('NewWindow2')
 
1142 wxEVT_COMMAND_MSHTML_DOCUMENTCOMPLETE = RegisterActiveXEvent('DocumentComplete')
 
1143 wxEVT_COMMAND_MSHTML_PROGRESSCHANGE   = RegisterActiveXEvent('ProgressChange')
 
1144 wxEVT_COMMAND_MSHTML_STATUSTEXTCHANGE = RegisterActiveXEvent('StatusTextChange')
 
1145 wxEVT_COMMAND_MSHTML_TITLECHANGE      = RegisterActiveXEvent('TitleChange')
 
1147 EVT_MSHTML_BEFORENAVIGATE2      = wx.PyEventBinder(wxEVT_COMMAND_MSHTML_BEFORENAVIGATE2, 1)
 
1148 EVT_MSHTML_NEWWINDOW2           = wx.PyEventBinder(wxEVT_COMMAND_MSHTML_NEWWINDOW2, 1)
 
1149 EVT_MSHTML_DOCUMENTCOMPLETE     = wx.PyEventBinder(wxEVT_COMMAND_MSHTML_DOCUMENTCOMPLETE, 1)
 
1150 EVT_MSHTML_PROGRESSCHANGE       = wx.PyEventBinder(wxEVT_COMMAND_MSHTML_PROGRESSCHANGE, 1)
 
1151 EVT_MSHTML_STATUSTEXTCHANGE     = wx.PyEventBinder(wxEVT_COMMAND_MSHTML_STATUSTEXTCHANGE, 1)
 
1152 EVT_MSHTML_TITLECHANGE          = wx.PyEventBinder(wxEVT_COMMAND_MSHTML_TITLECHANGE, 1)
 
1157 //---------------------------------------------------------------------------
 
1158 // Include some extra Python code into the proxy module
 
1160 %pythoncode "_activex_ex.py"
 
1162 //---------------------------------------------------------------------------