]> git.saurik.com Git - wxWidgets.git/blobdiff - wxPython/contrib/iewin/IEHtmlWin.cpp
Added wxIEHtmlWin wrappers to wxPython.
[wxWidgets.git] / wxPython / contrib / iewin / IEHtmlWin.cpp
diff --git a/wxPython/contrib/iewin/IEHtmlWin.cpp b/wxPython/contrib/iewin/IEHtmlWin.cpp
new file mode 100644 (file)
index 0000000..ac41315
--- /dev/null
@@ -0,0 +1,515 @@
+#include "IEHtmlWin.h"
+#include <wx/strconv.h>
+#include <wx/event.h>
+#include <wx/listctrl.h>
+#include <oleidl.h>
+#include <winerror.h>
+#include <exdispid.h>
+#include <exdisp.h>
+#include <olectl.h>
+#include <Mshtml.h>
+#include <sstream>
+using namespace std;
+
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_MSHTML_BEFORENAVIGATE2);
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_MSHTML_NEWWINDOW2);
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_MSHTML_DOCUMENTCOMPLETE);
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_MSHTML_PROGRESSCHANGE);
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_MSHTML_STATUSTEXTCHANGE);
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_MSHTML_TITLECHANGE);
+
+IMPLEMENT_DYNAMIC_CLASS(wxMSHTMLEvent, wxNotifyEvent);
+
+
+//////////////////////////////////////////////////////////////////////
+BEGIN_EVENT_TABLE(wxIEHtmlWin, wxActiveX)
+END_EVENT_TABLE()
+
+class FS_DWebBrowserEvents2 : public IDispatch
+{
+private:
+    DECLARE_OLE_UNKNOWN(FS_DWebBrowserEvents2);
+
+
+    wxIEHtmlWin *m_iewin;
+
+public:
+    FS_DWebBrowserEvents2(wxIEHtmlWin *iewin) : m_iewin(iewin) {}
+       ~FS_DWebBrowserEvents2()
+    {
+    }
+
+       //IDispatch
+       STDMETHODIMP GetIDsOfNames(REFIID r, OLECHAR** o, unsigned int i, LCID l, DISPID* d)
+       {
+        return E_NOTIMPL;
+    };
+
+       STDMETHODIMP GetTypeInfo(unsigned int i, LCID l, ITypeInfo** t)
+       {
+        return E_NOTIMPL;
+    };
+
+       STDMETHODIMP GetTypeInfoCount(unsigned int* i)
+       {
+        return E_NOTIMPL;
+    };
+
+       void Post(WXTYPE etype, wxString text, long l1 = 0, long l2 = 0)
+       {
+               if (! m_iewin || ! m_iewin->GetParent())
+                       return;
+
+               wxMSHTMLEvent event;
+               event.SetId(m_iewin->GetId());
+               event.SetEventType(etype);
+               event.m_text1 = text;
+               event.m_long1 = l1;
+               event.m_long2 = l2;
+
+               m_iewin->GetParent()->AddPendingEvent(event);
+       };
+
+       bool Process(WXTYPE etype, wxString text = "", long l1 = 0, long l2 = 0)
+       {
+               if (! m_iewin || ! m_iewin->GetParent())
+                       return true;
+
+               wxMSHTMLEvent event;
+               event.SetId(m_iewin->GetId());
+               event.SetEventType(etype);
+               event.m_text1 = text;
+               event.m_long1 = l1;
+               event.m_long2 = l2;
+
+               m_iewin->GetParent()->ProcessEvent(event);
+
+               return event.IsAllowed();
+       };
+
+       wxString GetStrArg(VARIANT& v)
+       {
+               VARTYPE vt = v.vt & ~VT_BYREF;
+
+               if (vt == VT_VARIANT)
+                       return GetStrArg(*v.pvarVal);
+               else if (vt == VT_BSTR)
+               {
+                       if (v.vt & VT_BYREF)
+                               return (v.pbstrVal ? *v.pbstrVal : L"");
+                       else
+                               return v.bstrVal;
+               }
+               else
+                       return "";
+       };
+
+#define STR_ARG(arg) GetStrArg(pDispParams->rgvarg[arg])
+
+#define LONG_ARG(arg)\
+                       (pDispParams->rgvarg[arg].lVal)
+
+
+       STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
+                                                 WORD wFlags, DISPPARAMS * pDispParams,
+                                                 VARIANT * pVarResult, EXCEPINFO * pExcepInfo,
+                                                 unsigned int * puArgErr)
+       {
+           if (wFlags & DISPATCH_PROPERTYGET)
+            return E_NOTIMPL;
+
+           switch (dispIdMember)
+           {
+                   case DISPID_BEFORENAVIGATE2:
+                               if (Process(wxEVT_COMMAND_MSHTML_BEFORENAVIGATE2, STR_ARG(5)))
+                                       *pDispParams->rgvarg->pboolVal = VARIANT_FALSE;
+                               else
+                                       *pDispParams->rgvarg->pboolVal = VARIANT_TRUE;
+                               break;
+
+                   case DISPID_NEWWINDOW2:
+                               if (Process(wxEVT_COMMAND_MSHTML_NEWWINDOW2))
+                                       *pDispParams->rgvarg->pboolVal = VARIANT_FALSE;
+                               else
+                                       *pDispParams->rgvarg->pboolVal = VARIANT_TRUE;
+                               break;
+
+            case DISPID_PROGRESSCHANGE:
+                               Post(wxEVT_COMMAND_MSHTML_PROGRESSCHANGE, "", LONG_ARG(1), LONG_ARG(0));
+                               break;
+
+            case DISPID_DOCUMENTCOMPLETE:
+                               Post(wxEVT_COMMAND_MSHTML_DOCUMENTCOMPLETE, STR_ARG(0));
+                               break;
+
+            case DISPID_STATUSTEXTCHANGE:
+                               Post(wxEVT_COMMAND_MSHTML_STATUSTEXTCHANGE, STR_ARG(0));
+                               break;
+
+            case DISPID_TITLECHANGE:
+                               Post(wxEVT_COMMAND_MSHTML_TITLECHANGE, STR_ARG(0));
+                               break;
+           }
+
+       return S_OK;
+    }
+};
+
+#undef STR_ARG
+
+DEFINE_OLE_TABLE(FS_DWebBrowserEvents2)
+       OLE_IINTERFACE(IUnknown)
+       OLE_INTERFACE(DIID_DWebBrowserEvents2, DWebBrowserEvents2)
+END_OLE_TABLE;
+
+
+static const CLSID CLSID_MozillaBrowser =
+{ 0x1339B54C, 0x3453, 0x11D2,
+  { 0x93, 0xB9, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00 } };
+
+
+//#define PROGID L"Shell.Explorer"
+#define PROGID CLSID_WebBrowser
+//#define PROGID CLSID_HTMLDocument
+//#define PROGID L"MSCAL.Calendar"
+//#define PROGID L"WordPad.Document.1"
+//#define PROGID L"SoftwareFX.ChartFX.20"
+
+
+wxIEHtmlWin::wxIEHtmlWin(wxWindow * parent, wxWindowID id)
+       : wxActiveX(parent, PROGID, id)
+{
+    SetupBrowser();
+}
+
+wxIEHtmlWin::~wxIEHtmlWin()
+{
+}
+
+void wxIEHtmlWin::SetupBrowser()
+{
+       HRESULT hret;
+
+       // Get IWebBrowser2 Interface
+       hret = m_webBrowser.QueryInterface(IID_IWebBrowser2, m_ActiveX);
+       assert(SUCCEEDED(hret));
+
+       // Web Browser Events
+       FS_DWebBrowserEvents2 *events = new FS_DWebBrowserEvents2(this);
+       hret = ConnectAdvise(DIID_DWebBrowserEvents2, events);
+       if (! SUCCEEDED(hret))
+               delete events;
+
+       // web browser setup
+       m_webBrowser->put_MenuBar(VARIANT_FALSE);
+       m_webBrowser->put_AddressBar(VARIANT_FALSE);
+       m_webBrowser->put_StatusBar(VARIANT_FALSE);
+       m_webBrowser->put_ToolBar(VARIANT_FALSE);
+
+       m_webBrowser->put_RegisterAsBrowser(VARIANT_TRUE);
+       m_webBrowser->put_RegisterAsDropTarget(VARIANT_TRUE);
+
+    m_webBrowser->Navigate( L"about:blank", NULL, NULL, NULL, NULL );
+}
+
+
+void wxIEHtmlWin::SetEditMode(bool seton)
+{
+    m_bAmbientUserMode = ! seton;
+    AmbientPropertyChanged(DISPID_AMBIENT_USERMODE);
+};
+
+bool wxIEHtmlWin::GetEditMode()
+{
+    return ! m_bAmbientUserMode;
+};
+
+
+void wxIEHtmlWin::SetCharset(wxString charset)
+{
+       // HTML Document ?
+       IDispatch *pDisp = NULL;
+       HRESULT hret = m_webBrowser->get_Document(&pDisp);
+       wxAutoOleInterface<IDispatch> disp(pDisp);
+
+       if (disp.Ok())
+       {
+               wxAutoOleInterface<IHTMLDocument2> doc(IID_IHTMLDocument2, disp);
+               if (doc.Ok())
+                       doc->put_charset((BSTR) wxConvUTF8.cMB2WC(charset).data());
+       };
+};
+
+
+class IStreamAdaptorBase : public IStream
+{
+private:
+    DECLARE_OLE_UNKNOWN(IStreamAdaptorBase);
+
+public:
+    IStreamAdaptorBase() {}
+    virtual ~IStreamAdaptorBase() {}
+
+    // ISequentialStream
+    HRESULT STDMETHODCALLTYPE Read(void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbRead) = 0;
+    HRESULT STDMETHODCALLTYPE Write(const void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbWritten) {return E_NOTIMPL;}
+
+    // IStream
+    HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER __RPC_FAR *plibNewPosition) {return E_NOTIMPL;}
+    HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER libNewSize) {return E_NOTIMPL;}
+    HRESULT STDMETHODCALLTYPE CopyTo(IStream __RPC_FAR *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER __RPC_FAR *pcbRead, ULARGE_INTEGER __RPC_FAR *pcbWritten) {return E_NOTIMPL;}
+    HRESULT STDMETHODCALLTYPE Commit(DWORD grfCommitFlags) {return E_NOTIMPL;}
+    HRESULT STDMETHODCALLTYPE Revert(void) {return E_NOTIMPL;}
+    HRESULT STDMETHODCALLTYPE LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {return E_NOTIMPL;}
+    HRESULT STDMETHODCALLTYPE UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {return E_NOTIMPL;}
+    HRESULT STDMETHODCALLTYPE Stat(STATSTG __RPC_FAR *pstatstg, DWORD grfStatFlag) {return E_NOTIMPL;}
+    HRESULT STDMETHODCALLTYPE Clone(IStream __RPC_FAR *__RPC_FAR *ppstm) {return E_NOTIMPL;}
+};
+
+DEFINE_OLE_TABLE(IStreamAdaptorBase)
+       OLE_IINTERFACE(IUnknown)
+       OLE_IINTERFACE(ISequentialStream)
+       OLE_IINTERFACE(IStream)
+END_OLE_TABLE;
+
+class IStreamAdaptor : public IStreamAdaptorBase
+{
+private:
+    istream *m_is;
+
+public:
+
+    IStreamAdaptor(istream *is)        : IStreamAdaptorBase(), m_is(is)
+    {
+        wxASSERT(m_is != NULL);
+    }
+    ~IStreamAdaptor()
+    {
+        delete m_is;
+    }
+
+    // ISequentialStream
+    HRESULT STDMETHODCALLTYPE Read(void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbRead)
+       {
+               m_is->read((char *) pv, cb);
+               if (pcbRead)
+                       *pcbRead = m_is->gcount();
+
+               return S_OK;
+       };
+};
+
+
+void wxIEHtmlWin::LoadUrl(const wxString& url)
+{
+       VARIANTARG navFlag, targetFrame, postData, headers;
+       navFlag.vt = VT_EMPTY;
+       navFlag.vt = VT_I2;
+       navFlag.iVal = navNoReadFromCache;
+       targetFrame.vt = VT_EMPTY;
+       postData.vt = VT_EMPTY;
+       headers.vt = VT_EMPTY;
+
+       HRESULT hret = 0;
+       hret = m_webBrowser->Navigate((BSTR) wxConvUTF8.cMB2WC(url).data(),
+               &navFlag, &targetFrame, &postData, &headers);
+};
+
+
+bool  wxIEHtmlWin::LoadString(wxString html)
+{
+       string s = html.c_str();
+       istringstream *is = new istringstream(s);
+       return LoadStream(is);
+};
+
+bool  wxIEHtmlWin::LoadStream(istream *is)
+{
+       // wrap refernce around stream
+    IStreamAdaptor *pstrm = new IStreamAdaptor(is);
+       pstrm->AddRef();
+
+       wxAutoOleInterface<IStream>     strm(pstrm);
+
+    // Document Interface
+    IDispatch *pDisp = NULL;
+    HRESULT hret = m_webBrowser->get_Document(&pDisp);
+       if (! pDisp)
+               return false;
+       wxAutoOleInterface<IDispatch> disp(pDisp);
+
+
+       // get IPersistStreamInit
+    wxAutoOleInterface<IPersistStreamInit>
+               pPersistStreamInit(IID_IPersistStreamInit, disp);
+
+    if (pPersistStreamInit.Ok())
+    {
+        HRESULT hr = pPersistStreamInit->InitNew();
+        if (SUCCEEDED(hr))
+            hr = pPersistStreamInit->Load(strm);
+    };
+
+    return true;
+};
+
+bool wxIEHtmlWin::GoBack()
+{
+    HRESULT hret = 0;
+    hret = m_webBrowser->GoBack();
+    return hret == S_OK;
+}
+
+bool wxIEHtmlWin::GoForward()
+{
+    HRESULT hret = 0;
+    hret = m_webBrowser->GoForward();
+    return hret == S_OK;
+}
+
+bool wxIEHtmlWin::GoHome()
+{
+    HRESULT hret = 0;
+    hret = m_webBrowser->GoHome();
+    return hret == S_OK;
+}
+
+bool wxIEHtmlWin::GoSearch()
+{
+    HRESULT hret = 0;
+    hret = m_webBrowser->GoSearch();
+    return hret == S_OK;
+}
+
+bool wxIEHtmlWin::Refresh(wxIEHtmlRefreshLevel level)
+{
+    VARIANTARG levelArg;
+    HRESULT hret = 0;
+
+    levelArg.vt = VT_I2;
+    levelArg.iVal = level;
+    hret = m_webBrowser->Refresh2(&levelArg);
+    return hret == S_OK;
+}
+
+bool wxIEHtmlWin::Stop()
+{
+    HRESULT hret = 0;
+    hret = m_webBrowser->Stop();
+    return hret == S_OK;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static wxAutoOleInterface<IHTMLSelectionObject> GetSelObject(IOleObject *oleObject)
+{
+       // Query for IWebBrowser interface
+    wxAutoOleInterface<IWebBrowser2> wb(IID_IWebBrowser2, oleObject);
+    if (! wb.Ok())
+       return wxAutoOleInterface<IHTMLSelectionObject>();
+
+       IDispatch *iDisp = NULL;
+    HRESULT hr = wb->get_Document(&iDisp);
+    if (hr != S_OK)
+       return wxAutoOleInterface<IHTMLSelectionObject>();
+
+       // Query for Document Interface
+    wxAutoOleInterface<IHTMLDocument2> hd(IID_IHTMLDocument2, iDisp);
+    iDisp->Release();
+
+    if (! hd.Ok())
+       return wxAutoOleInterface<IHTMLSelectionObject>();
+
+    IHTMLSelectionObject *_so = NULL;
+    hr = hd->get_selection(&_so);
+
+    // take ownership of selection object
+       wxAutoOleInterface<IHTMLSelectionObject> so(_so);
+
+    return so;
+};
+
+static wxAutoOleInterface<IHTMLTxtRange> GetSelRange(IOleObject *oleObject)
+{
+       wxAutoOleInterface<IHTMLTxtRange> tr;
+
+    wxAutoOleInterface<IHTMLSelectionObject> so(GetSelObject(oleObject));
+    if (! so)
+       return tr;
+
+       IDispatch *iDisp = NULL;
+    HRESULT hr = so->createRange(&iDisp);
+    if (hr != S_OK)
+       return tr;
+
+       // Query for IHTMLTxtRange interface
+       tr.QueryInterface(IID_IHTMLTxtRange, iDisp);
+    iDisp->Release();
+    return tr;
+};
+
+
+wxString wxIEHtmlWin::GetStringSelection(bool asHTML)
+{
+       wxAutoOleInterface<IHTMLTxtRange> tr(GetSelRange(m_oleObject));
+    if (! tr)
+       return "";
+
+    BSTR text = NULL;
+    HRESULT hr = E_FAIL;
+
+       if (asHTML)
+               hr = tr->get_htmlText(&text);
+       else
+               hr = tr->get_text(&text);
+    if (hr != S_OK)
+       return "";
+
+    wxString s = text;
+    SysFreeString(text);
+
+    return s;
+};
+
+wxString wxIEHtmlWin::GetText(bool asHTML)
+{
+       if (! m_webBrowser.Ok())
+               return "";
+
+       // get document dispatch interface
+       IDispatch *iDisp = NULL;
+    HRESULT hr = m_webBrowser->get_Document(&iDisp);
+    if (hr != S_OK)
+       return "";
+
+       // Query for Document Interface
+    wxAutoOleInterface<IHTMLDocument2> hd(IID_IHTMLDocument2, iDisp);
+    iDisp->Release();
+
+    if (! hd.Ok())
+               return "";
+
+       // get body element
+       IHTMLElement *_body = NULL;
+       hd->get_body(&_body);
+       if (! _body)
+               return "";
+       wxAutoOleInterface<IHTMLElement> body(_body);
+
+       // get inner text
+    BSTR text = NULL;
+    hr = E_FAIL;
+
+       if (asHTML)
+               hr = body->get_innerHTML(&text);
+       else
+               hr = body->get_innerText(&text);
+    if (hr != S_OK)
+       return "";
+
+    wxString s = text;
+    SysFreeString(text);
+
+    return s;
+};