]> git.saurik.com Git - wxWidgets.git/blob - wxPython/contrib/iewin/IEHtmlWin.cpp
6e59a054da09fd879ba2b39e40ff60d7b9d3fb94
[wxWidgets.git] / wxPython / contrib / iewin / IEHtmlWin.cpp
1 #include "IEHtmlWin.h"
2 #include <wx/strconv.h>
3 #include <wx/event.h>
4 #include <wx/listctrl.h>
5 #include <oleidl.h>
6 #include <winerror.h>
7 #include <exdispid.h>
8 #include <exdisp.h>
9 #include <olectl.h>
10 #include <Mshtml.h>
11 #include <sstream>
12 using namespace std;
13
14 DEFINE_EVENT_TYPE(wxEVT_COMMAND_MSHTML_BEFORENAVIGATE2);
15 DEFINE_EVENT_TYPE(wxEVT_COMMAND_MSHTML_NEWWINDOW2);
16 DEFINE_EVENT_TYPE(wxEVT_COMMAND_MSHTML_DOCUMENTCOMPLETE);
17 DEFINE_EVENT_TYPE(wxEVT_COMMAND_MSHTML_PROGRESSCHANGE);
18 DEFINE_EVENT_TYPE(wxEVT_COMMAND_MSHTML_STATUSTEXTCHANGE);
19 DEFINE_EVENT_TYPE(wxEVT_COMMAND_MSHTML_TITLECHANGE);
20
21 IMPLEMENT_DYNAMIC_CLASS(wxMSHTMLEvent, wxNotifyEvent);
22
23
24 //////////////////////////////////////////////////////////////////////
25 BEGIN_EVENT_TABLE(wxIEHtmlWin, wxActiveX)
26 END_EVENT_TABLE()
27
28 class FS_DWebBrowserEvents2 : public IDispatch
29 {
30 private:
31 DECLARE_OLE_UNKNOWN(FS_DWebBrowserEvents2);
32
33
34 wxIEHtmlWin *m_iewin;
35
36 public:
37 FS_DWebBrowserEvents2(wxIEHtmlWin *iewin) : m_iewin(iewin) {}
38 ~FS_DWebBrowserEvents2()
39 {
40 }
41
42 //IDispatch
43 STDMETHODIMP GetIDsOfNames(REFIID r, OLECHAR** o, unsigned int i, LCID l, DISPID* d)
44 {
45 return E_NOTIMPL;
46 };
47
48 STDMETHODIMP GetTypeInfo(unsigned int i, LCID l, ITypeInfo** t)
49 {
50 return E_NOTIMPL;
51 };
52
53 STDMETHODIMP GetTypeInfoCount(unsigned int* i)
54 {
55 return E_NOTIMPL;
56 };
57
58 void Post(WXTYPE etype, wxString text, long l1 = 0, long l2 = 0)
59 {
60 if (! m_iewin || ! m_iewin->GetParent())
61 return;
62
63 wxMSHTMLEvent event;
64 event.SetId(m_iewin->GetId());
65 event.SetEventType(etype);
66 event.m_text1 = text;
67 event.m_long1 = l1;
68 event.m_long2 = l2;
69
70 m_iewin->GetParent()->AddPendingEvent(event);
71 };
72
73 bool Process(WXTYPE etype, wxString text = "", long l1 = 0, long l2 = 0)
74 {
75 if (! m_iewin || ! m_iewin->GetParent())
76 return true;
77
78 wxMSHTMLEvent event;
79 event.SetId(m_iewin->GetId());
80 event.SetEventType(etype);
81 event.m_text1 = text;
82 event.m_long1 = l1;
83 event.m_long2 = l2;
84
85 m_iewin->GetParent()->ProcessEvent(event);
86
87 return event.IsAllowed();
88 };
89
90 wxString GetStrArg(VARIANT& v)
91 {
92 VARTYPE vt = v.vt & ~VT_BYREF;
93
94 if (vt == VT_VARIANT)
95 return GetStrArg(*v.pvarVal);
96 else if (vt == VT_BSTR)
97 {
98 if (v.vt & VT_BYREF)
99 return (v.pbstrVal ? *v.pbstrVal : L"");
100 else
101 return v.bstrVal;
102 }
103 else
104 return "";
105 };
106
107 #define STR_ARG(arg) GetStrArg(pDispParams->rgvarg[arg])
108
109 #define LONG_ARG(arg)\
110 (pDispParams->rgvarg[arg].lVal)
111
112
113 STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
114 WORD wFlags, DISPPARAMS * pDispParams,
115 VARIANT * pVarResult, EXCEPINFO * pExcepInfo,
116 unsigned int * puArgErr)
117 {
118 if (wFlags & DISPATCH_PROPERTYGET)
119 return E_NOTIMPL;
120
121 switch (dispIdMember)
122 {
123 case DISPID_BEFORENAVIGATE2:
124 if (Process(wxEVT_COMMAND_MSHTML_BEFORENAVIGATE2, STR_ARG(5)))
125 *pDispParams->rgvarg->pboolVal = VARIANT_FALSE;
126 else
127 *pDispParams->rgvarg->pboolVal = VARIANT_TRUE;
128 break;
129
130 case DISPID_NEWWINDOW2:
131 if (Process(wxEVT_COMMAND_MSHTML_NEWWINDOW2))
132 *pDispParams->rgvarg->pboolVal = VARIANT_FALSE;
133 else
134 *pDispParams->rgvarg->pboolVal = VARIANT_TRUE;
135 break;
136
137 case DISPID_PROGRESSCHANGE:
138 Post(wxEVT_COMMAND_MSHTML_PROGRESSCHANGE, "", LONG_ARG(1), LONG_ARG(0));
139 break;
140
141 case DISPID_DOCUMENTCOMPLETE:
142 Post(wxEVT_COMMAND_MSHTML_DOCUMENTCOMPLETE, STR_ARG(0));
143 break;
144
145 case DISPID_STATUSTEXTCHANGE:
146 Post(wxEVT_COMMAND_MSHTML_STATUSTEXTCHANGE, STR_ARG(0));
147 break;
148
149 case DISPID_TITLECHANGE:
150 Post(wxEVT_COMMAND_MSHTML_TITLECHANGE, STR_ARG(0));
151 break;
152 }
153
154 return S_OK;
155 }
156 };
157
158 #undef STR_ARG
159
160 DEFINE_OLE_TABLE(FS_DWebBrowserEvents2)
161 OLE_IINTERFACE(IUnknown)
162 OLE_INTERFACE(DIID_DWebBrowserEvents2, DWebBrowserEvents2)
163 END_OLE_TABLE;
164
165
166 static const CLSID CLSID_MozillaBrowser =
167 { 0x1339B54C, 0x3453, 0x11D2,
168 { 0x93, 0xB9, 0x00, 0x00,
169 0x00, 0x00, 0x00, 0x00 } };
170
171
172 //#define PROGID L"Shell.Explorer"
173 #define PROGID CLSID_WebBrowser
174 //#define PROGID CLSID_HTMLDocument
175 //#define PROGID L"MSCAL.Calendar"
176 //#define PROGID L"WordPad.Document.1"
177 //#define PROGID L"SoftwareFX.ChartFX.20"
178
179
180 wxIEHtmlWin::wxIEHtmlWin(wxWindow * parent, wxWindowID id,
181 const wxPoint& pos,
182 const wxSize& size,
183 long style,
184 const wxString& name)
185 : wxActiveX(parent, PROGID, id, pos, size, style, name)
186 {
187 SetupBrowser();
188 }
189
190 wxIEHtmlWin::~wxIEHtmlWin()
191 {
192 }
193
194 void wxIEHtmlWin::SetupBrowser()
195 {
196 HRESULT hret;
197
198 // Get IWebBrowser2 Interface
199 hret = m_webBrowser.QueryInterface(IID_IWebBrowser2, m_ActiveX);
200 assert(SUCCEEDED(hret));
201
202 // Web Browser Events
203 FS_DWebBrowserEvents2 *events = new FS_DWebBrowserEvents2(this);
204 hret = ConnectAdvise(DIID_DWebBrowserEvents2, events);
205 if (! SUCCEEDED(hret))
206 delete events;
207
208 // web browser setup
209 m_webBrowser->put_MenuBar(VARIANT_FALSE);
210 m_webBrowser->put_AddressBar(VARIANT_FALSE);
211 m_webBrowser->put_StatusBar(VARIANT_FALSE);
212 m_webBrowser->put_ToolBar(VARIANT_FALSE);
213
214 m_webBrowser->put_RegisterAsBrowser(VARIANT_TRUE);
215 m_webBrowser->put_RegisterAsDropTarget(VARIANT_TRUE);
216
217 m_webBrowser->Navigate( L"about:blank", NULL, NULL, NULL, NULL );
218 }
219
220
221 void wxIEHtmlWin::SetEditMode(bool seton)
222 {
223 m_bAmbientUserMode = ! seton;
224 AmbientPropertyChanged(DISPID_AMBIENT_USERMODE);
225 };
226
227 bool wxIEHtmlWin::GetEditMode()
228 {
229 return ! m_bAmbientUserMode;
230 };
231
232
233 void wxIEHtmlWin::SetCharset(wxString charset)
234 {
235 // HTML Document ?
236 IDispatch *pDisp = NULL;
237 HRESULT hret = m_webBrowser->get_Document(&pDisp);
238 wxAutoOleInterface<IDispatch> disp(pDisp);
239
240 if (disp.Ok())
241 {
242 wxAutoOleInterface<IHTMLDocument2> doc(IID_IHTMLDocument2, disp);
243 if (doc.Ok())
244 doc->put_charset((BSTR) (const wchar_t*)charset.wc_str(wxConvUTF8));
245 };
246 };
247
248
249 class IStreamAdaptorBase : public IStream
250 {
251 private:
252 DECLARE_OLE_UNKNOWN(IStreamAdaptorBase);
253
254 public:
255 IStreamAdaptorBase() {}
256 virtual ~IStreamAdaptorBase() {}
257
258 // ISequentialStream
259 HRESULT STDMETHODCALLTYPE Read(void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbRead) = 0;
260 HRESULT STDMETHODCALLTYPE Write(const void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbWritten) {return E_NOTIMPL;}
261
262 // IStream
263 HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER __RPC_FAR *plibNewPosition) {return E_NOTIMPL;}
264 HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER libNewSize) {return E_NOTIMPL;}
265 HRESULT STDMETHODCALLTYPE CopyTo(IStream __RPC_FAR *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER __RPC_FAR *pcbRead, ULARGE_INTEGER __RPC_FAR *pcbWritten) {return E_NOTIMPL;}
266 HRESULT STDMETHODCALLTYPE Commit(DWORD grfCommitFlags) {return E_NOTIMPL;}
267 HRESULT STDMETHODCALLTYPE Revert(void) {return E_NOTIMPL;}
268 HRESULT STDMETHODCALLTYPE LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {return E_NOTIMPL;}
269 HRESULT STDMETHODCALLTYPE UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {return E_NOTIMPL;}
270 HRESULT STDMETHODCALLTYPE Stat(STATSTG __RPC_FAR *pstatstg, DWORD grfStatFlag) {return E_NOTIMPL;}
271 HRESULT STDMETHODCALLTYPE Clone(IStream __RPC_FAR *__RPC_FAR *ppstm) {return E_NOTIMPL;}
272 };
273
274 DEFINE_OLE_TABLE(IStreamAdaptorBase)
275 OLE_IINTERFACE(IUnknown)
276 OLE_IINTERFACE(ISequentialStream)
277 OLE_IINTERFACE(IStream)
278 END_OLE_TABLE;
279
280 class IStreamAdaptor : public IStreamAdaptorBase
281 {
282 private:
283 istream *m_is;
284
285 public:
286
287 IStreamAdaptor(istream *is) : IStreamAdaptorBase(), m_is(is)
288 {
289 wxASSERT(m_is != NULL);
290 }
291 ~IStreamAdaptor()
292 {
293 delete m_is;
294 }
295
296 // ISequentialStream
297 HRESULT STDMETHODCALLTYPE Read(void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbRead)
298 {
299 m_is->read((char *) pv, cb);
300 if (pcbRead)
301 *pcbRead = m_is->gcount();
302
303 return S_OK;
304 };
305 };
306
307
308 void wxIEHtmlWin::LoadUrl(const wxString& url)
309 {
310 VARIANTARG navFlag, targetFrame, postData, headers;
311 navFlag.vt = VT_EMPTY;
312 navFlag.vt = VT_I2;
313 navFlag.iVal = navNoReadFromCache;
314 targetFrame.vt = VT_EMPTY;
315 postData.vt = VT_EMPTY;
316 headers.vt = VT_EMPTY;
317
318 HRESULT hret = 0;
319 hret = m_webBrowser->Navigate((BSTR) (const wchar_t*)url.wc_str(wxConvUTF8),
320 &navFlag, &targetFrame, &postData, &headers);
321 };
322
323
324 bool wxIEHtmlWin::LoadString(wxString html)
325 {
326 string s = html.mb_str(wxConvUTF8);
327 istringstream *is = new istringstream(s);
328 return LoadStream(is);
329 };
330
331 bool wxIEHtmlWin::LoadStream(istream *is)
332 {
333 // wrap refernce around stream
334 IStreamAdaptor *pstrm = new IStreamAdaptor(is);
335 pstrm->AddRef();
336
337 wxAutoOleInterface<IStream> strm(pstrm);
338
339 // Document Interface
340 IDispatch *pDisp = NULL;
341 HRESULT hret = m_webBrowser->get_Document(&pDisp);
342 if (! pDisp)
343 return false;
344 wxAutoOleInterface<IDispatch> disp(pDisp);
345
346
347 // get IPersistStreamInit
348 wxAutoOleInterface<IPersistStreamInit>
349 pPersistStreamInit(IID_IPersistStreamInit, disp);
350
351 if (pPersistStreamInit.Ok())
352 {
353 HRESULT hr = pPersistStreamInit->InitNew();
354 if (SUCCEEDED(hr))
355 hr = pPersistStreamInit->Load(strm);
356 };
357
358 return true;
359 };
360
361 bool wxIEHtmlWin::GoBack()
362 {
363 HRESULT hret = 0;
364 hret = m_webBrowser->GoBack();
365 return hret == S_OK;
366 }
367
368 bool wxIEHtmlWin::GoForward()
369 {
370 HRESULT hret = 0;
371 hret = m_webBrowser->GoForward();
372 return hret == S_OK;
373 }
374
375 bool wxIEHtmlWin::GoHome()
376 {
377 HRESULT hret = 0;
378 hret = m_webBrowser->GoHome();
379 return hret == S_OK;
380 }
381
382 bool wxIEHtmlWin::GoSearch()
383 {
384 HRESULT hret = 0;
385 hret = m_webBrowser->GoSearch();
386 return hret == S_OK;
387 }
388
389 bool wxIEHtmlWin::Refresh(wxIEHtmlRefreshLevel level)
390 {
391 VARIANTARG levelArg;
392 HRESULT hret = 0;
393
394 levelArg.vt = VT_I2;
395 levelArg.iVal = level;
396 hret = m_webBrowser->Refresh2(&levelArg);
397 return hret == S_OK;
398 }
399
400 bool wxIEHtmlWin::Stop()
401 {
402 HRESULT hret = 0;
403 hret = m_webBrowser->Stop();
404 return hret == S_OK;
405 }
406
407 ///////////////////////////////////////////////////////////////////////////////
408
409 static wxAutoOleInterface<IHTMLSelectionObject> GetSelObject(IOleObject *oleObject)
410 {
411 // Query for IWebBrowser interface
412 wxAutoOleInterface<IWebBrowser2> wb(IID_IWebBrowser2, oleObject);
413 if (! wb.Ok())
414 return wxAutoOleInterface<IHTMLSelectionObject>();
415
416 IDispatch *iDisp = NULL;
417 HRESULT hr = wb->get_Document(&iDisp);
418 if (hr != S_OK)
419 return wxAutoOleInterface<IHTMLSelectionObject>();
420
421 // Query for Document Interface
422 wxAutoOleInterface<IHTMLDocument2> hd(IID_IHTMLDocument2, iDisp);
423 iDisp->Release();
424
425 if (! hd.Ok())
426 return wxAutoOleInterface<IHTMLSelectionObject>();
427
428 IHTMLSelectionObject *_so = NULL;
429 hr = hd->get_selection(&_so);
430
431 // take ownership of selection object
432 wxAutoOleInterface<IHTMLSelectionObject> so(_so);
433
434 return so;
435 };
436
437 static wxAutoOleInterface<IHTMLTxtRange> GetSelRange(IOleObject *oleObject)
438 {
439 wxAutoOleInterface<IHTMLTxtRange> tr;
440
441 wxAutoOleInterface<IHTMLSelectionObject> so(GetSelObject(oleObject));
442 if (! so)
443 return tr;
444
445 IDispatch *iDisp = NULL;
446 HRESULT hr = so->createRange(&iDisp);
447 if (hr != S_OK)
448 return tr;
449
450 // Query for IHTMLTxtRange interface
451 tr.QueryInterface(IID_IHTMLTxtRange, iDisp);
452 iDisp->Release();
453 return tr;
454 };
455
456
457 wxString wxIEHtmlWin::GetStringSelection(bool asHTML)
458 {
459 wxAutoOleInterface<IHTMLTxtRange> tr(GetSelRange(m_oleObject));
460 if (! tr)
461 return "";
462
463 BSTR text = NULL;
464 HRESULT hr = E_FAIL;
465
466 if (asHTML)
467 hr = tr->get_htmlText(&text);
468 else
469 hr = tr->get_text(&text);
470 if (hr != S_OK)
471 return "";
472
473 wxString s = text;
474 SysFreeString(text);
475
476 return s;
477 };
478
479 wxString wxIEHtmlWin::GetText(bool asHTML)
480 {
481 if (! m_webBrowser.Ok())
482 return "";
483
484 // get document dispatch interface
485 IDispatch *iDisp = NULL;
486 HRESULT hr = m_webBrowser->get_Document(&iDisp);
487 if (hr != S_OK)
488 return "";
489
490 // Query for Document Interface
491 wxAutoOleInterface<IHTMLDocument2> hd(IID_IHTMLDocument2, iDisp);
492 iDisp->Release();
493
494 if (! hd.Ok())
495 return "";
496
497 // get body element
498 IHTMLElement *_body = NULL;
499 hd->get_body(&_body);
500 if (! _body)
501 return "";
502 wxAutoOleInterface<IHTMLElement> body(_body);
503
504 // get inner text
505 BSTR text = NULL;
506 hr = E_FAIL;
507
508 if (asHTML)
509 hr = body->get_innerHTML(&text);
510 else
511 hr = body->get_innerText(&text);
512 if (hr != S_OK)
513 return "";
514
515 wxString s = text;
516 SysFreeString(text);
517
518 return s;
519 };