]>
Commit | Line | Data |
---|---|---|
c731eb47 RD |
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) {} | |
811712d8 | 38 | ~FS_DWebBrowserEvents2() |
c731eb47 RD |
39 | { |
40 | } | |
41 | ||
42 | //IDispatch | |
43 | STDMETHODIMP GetIDsOfNames(REFIID r, OLECHAR** o, unsigned int i, LCID l, DISPID* d) | |
811712d8 | 44 | { |
c731eb47 RD |
45 | return E_NOTIMPL; |
46 | }; | |
47 | ||
48 | STDMETHODIMP GetTypeInfo(unsigned int i, LCID l, ITypeInfo** t) | |
811712d8 | 49 | { |
c731eb47 RD |
50 | return E_NOTIMPL; |
51 | }; | |
52 | ||
53 | STDMETHODIMP GetTypeInfoCount(unsigned int* i) | |
811712d8 | 54 | { |
c731eb47 RD |
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) | |
811712d8 | 117 | { |
c731eb47 RD |
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; | |
811712d8 | 126 | else |
c731eb47 RD |
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; | |
811712d8 | 133 | else |
c731eb47 RD |
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; | |
811712d8 | 140 | |
c731eb47 RD |
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 | ||
83a73288 | 172 | //#define PROGID "Shell.Explorer" |
c731eb47 | 173 | #define PROGID CLSID_WebBrowser |
83a73288 | 174 | //#define PROGID CLSID_MozillaBrowser |
c731eb47 | 175 | //#define PROGID CLSID_HTMLDocument |
83a73288 RD |
176 | //#define PROGID "MSCAL.Calendar" |
177 | //#define PROGID "WordPad.Document.1" | |
178 | //#define PROGID "SoftwareFX.ChartFX.20" | |
c731eb47 | 179 | |
d7abf017 | 180 | wxIEHtmlWin::wxIEHtmlWin(wxWindow * parent, wxWindowID id, |
83a73288 RD |
181 | const wxPoint& pos, |
182 | const wxSize& size, | |
183 | long style, | |
811712d8 | 184 | const wxString& name) : |
83a73288 | 185 | wxActiveX(parent, PROGID, id, pos, size, style, name) |
c731eb47 RD |
186 | { |
187 | SetupBrowser(); | |
188 | } | |
189 | ||
83a73288 | 190 | |
c731eb47 RD |
191 | wxIEHtmlWin::~wxIEHtmlWin() |
192 | { | |
193 | } | |
194 | ||
195 | void wxIEHtmlWin::SetupBrowser() | |
196 | { | |
197 | HRESULT hret; | |
198 | ||
199 | // Get IWebBrowser2 Interface | |
200 | hret = m_webBrowser.QueryInterface(IID_IWebBrowser2, m_ActiveX); | |
201 | assert(SUCCEEDED(hret)); | |
202 | ||
203 | // Web Browser Events | |
204 | FS_DWebBrowserEvents2 *events = new FS_DWebBrowserEvents2(this); | |
205 | hret = ConnectAdvise(DIID_DWebBrowserEvents2, events); | |
206 | if (! SUCCEEDED(hret)) | |
207 | delete events; | |
208 | ||
209 | // web browser setup | |
210 | m_webBrowser->put_MenuBar(VARIANT_FALSE); | |
211 | m_webBrowser->put_AddressBar(VARIANT_FALSE); | |
212 | m_webBrowser->put_StatusBar(VARIANT_FALSE); | |
213 | m_webBrowser->put_ToolBar(VARIANT_FALSE); | |
214 | ||
215 | m_webBrowser->put_RegisterAsBrowser(VARIANT_TRUE); | |
216 | m_webBrowser->put_RegisterAsDropTarget(VARIANT_TRUE); | |
217 | ||
218 | m_webBrowser->Navigate( L"about:blank", NULL, NULL, NULL, NULL ); | |
219 | } | |
220 | ||
221 | ||
222 | void wxIEHtmlWin::SetEditMode(bool seton) | |
223 | { | |
224 | m_bAmbientUserMode = ! seton; | |
225 | AmbientPropertyChanged(DISPID_AMBIENT_USERMODE); | |
226 | }; | |
227 | ||
228 | bool wxIEHtmlWin::GetEditMode() | |
229 | { | |
230 | return ! m_bAmbientUserMode; | |
231 | }; | |
232 | ||
233 | ||
234 | void wxIEHtmlWin::SetCharset(wxString charset) | |
235 | { | |
236 | // HTML Document ? | |
237 | IDispatch *pDisp = NULL; | |
238 | HRESULT hret = m_webBrowser->get_Document(&pDisp); | |
239 | wxAutoOleInterface<IDispatch> disp(pDisp); | |
240 | ||
241 | if (disp.Ok()) | |
242 | { | |
243 | wxAutoOleInterface<IHTMLDocument2> doc(IID_IHTMLDocument2, disp); | |
244 | if (doc.Ok()) | |
811712d8 | 245 | doc->put_charset((BSTR) (const wchar_t*)charset.wc_str(wxConvUTF8)); |
c731eb47 RD |
246 | }; |
247 | }; | |
248 | ||
249 | ||
250 | class IStreamAdaptorBase : public IStream | |
251 | { | |
252 | private: | |
253 | DECLARE_OLE_UNKNOWN(IStreamAdaptorBase); | |
254 | ||
255 | public: | |
256 | IStreamAdaptorBase() {} | |
257 | virtual ~IStreamAdaptorBase() {} | |
258 | ||
259 | // ISequentialStream | |
260 | HRESULT STDMETHODCALLTYPE Read(void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbRead) = 0; | |
261 | HRESULT STDMETHODCALLTYPE Write(const void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbWritten) {return E_NOTIMPL;} | |
262 | ||
263 | // IStream | |
264 | HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER __RPC_FAR *plibNewPosition) {return E_NOTIMPL;} | |
265 | HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER libNewSize) {return E_NOTIMPL;} | |
266 | HRESULT STDMETHODCALLTYPE CopyTo(IStream __RPC_FAR *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER __RPC_FAR *pcbRead, ULARGE_INTEGER __RPC_FAR *pcbWritten) {return E_NOTIMPL;} | |
267 | HRESULT STDMETHODCALLTYPE Commit(DWORD grfCommitFlags) {return E_NOTIMPL;} | |
268 | HRESULT STDMETHODCALLTYPE Revert(void) {return E_NOTIMPL;} | |
269 | HRESULT STDMETHODCALLTYPE LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {return E_NOTIMPL;} | |
270 | HRESULT STDMETHODCALLTYPE UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {return E_NOTIMPL;} | |
271 | HRESULT STDMETHODCALLTYPE Stat(STATSTG __RPC_FAR *pstatstg, DWORD grfStatFlag) {return E_NOTIMPL;} | |
272 | HRESULT STDMETHODCALLTYPE Clone(IStream __RPC_FAR *__RPC_FAR *ppstm) {return E_NOTIMPL;} | |
273 | }; | |
274 | ||
275 | DEFINE_OLE_TABLE(IStreamAdaptorBase) | |
276 | OLE_IINTERFACE(IUnknown) | |
277 | OLE_IINTERFACE(ISequentialStream) | |
278 | OLE_IINTERFACE(IStream) | |
279 | END_OLE_TABLE; | |
280 | ||
281 | class IStreamAdaptor : public IStreamAdaptorBase | |
282 | { | |
283 | private: | |
284 | istream *m_is; | |
285 | ||
286 | public: | |
811712d8 RD |
287 | |
288 | IStreamAdaptor(istream *is) : IStreamAdaptorBase(), m_is(is) | |
c731eb47 RD |
289 | { |
290 | wxASSERT(m_is != NULL); | |
291 | } | |
811712d8 | 292 | ~IStreamAdaptor() |
c731eb47 RD |
293 | { |
294 | delete m_is; | |
295 | } | |
296 | ||
297 | // ISequentialStream | |
298 | HRESULT STDMETHODCALLTYPE Read(void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbRead) | |
299 | { | |
300 | m_is->read((char *) pv, cb); | |
301 | if (pcbRead) | |
302 | *pcbRead = m_is->gcount(); | |
303 | ||
304 | return S_OK; | |
305 | }; | |
306 | }; | |
307 | ||
308 | ||
309 | void wxIEHtmlWin::LoadUrl(const wxString& url) | |
310 | { | |
311 | VARIANTARG navFlag, targetFrame, postData, headers; | |
811712d8 | 312 | navFlag.vt = VT_EMPTY; |
c731eb47 RD |
313 | navFlag.vt = VT_I2; |
314 | navFlag.iVal = navNoReadFromCache; | |
315 | targetFrame.vt = VT_EMPTY; | |
316 | postData.vt = VT_EMPTY; | |
317 | headers.vt = VT_EMPTY; | |
318 | ||
319 | HRESULT hret = 0; | |
811712d8 RD |
320 | hret = m_webBrowser->Navigate((BSTR) (const wchar_t*)url.wc_str(wxConvUTF8), |
321 | &navFlag, &targetFrame, &postData, &headers); | |
c731eb47 RD |
322 | }; |
323 | ||
324 | ||
325 | bool wxIEHtmlWin::LoadString(wxString html) | |
326 | { | |
811712d8 | 327 | string s = html.mb_str(wxConvUTF8); |
c731eb47 RD |
328 | istringstream *is = new istringstream(s); |
329 | return LoadStream(is); | |
330 | }; | |
331 | ||
332 | bool wxIEHtmlWin::LoadStream(istream *is) | |
333 | { | |
83a73288 | 334 | // wrap reference around stream |
c731eb47 RD |
335 | IStreamAdaptor *pstrm = new IStreamAdaptor(is); |
336 | pstrm->AddRef(); | |
337 | ||
338 | wxAutoOleInterface<IStream> strm(pstrm); | |
339 | ||
340 | // Document Interface | |
341 | IDispatch *pDisp = NULL; | |
342 | HRESULT hret = m_webBrowser->get_Document(&pDisp); | |
343 | if (! pDisp) | |
344 | return false; | |
345 | wxAutoOleInterface<IDispatch> disp(pDisp); | |
346 | ||
347 | ||
348 | // get IPersistStreamInit | |
349 | wxAutoOleInterface<IPersistStreamInit> | |
350 | pPersistStreamInit(IID_IPersistStreamInit, disp); | |
351 | ||
352 | if (pPersistStreamInit.Ok()) | |
353 | { | |
354 | HRESULT hr = pPersistStreamInit->InitNew(); | |
355 | if (SUCCEEDED(hr)) | |
356 | hr = pPersistStreamInit->Load(strm); | |
c731eb47 | 357 | |
83a73288 RD |
358 | return SUCCEEDED(hr); |
359 | } | |
360 | else | |
361 | return false; | |
c731eb47 RD |
362 | }; |
363 | ||
364 | bool wxIEHtmlWin::GoBack() | |
365 | { | |
366 | HRESULT hret = 0; | |
367 | hret = m_webBrowser->GoBack(); | |
368 | return hret == S_OK; | |
369 | } | |
370 | ||
371 | bool wxIEHtmlWin::GoForward() | |
372 | { | |
373 | HRESULT hret = 0; | |
374 | hret = m_webBrowser->GoForward(); | |
375 | return hret == S_OK; | |
376 | } | |
377 | ||
378 | bool wxIEHtmlWin::GoHome() | |
379 | { | |
380 | HRESULT hret = 0; | |
381 | hret = m_webBrowser->GoHome(); | |
382 | return hret == S_OK; | |
383 | } | |
384 | ||
385 | bool wxIEHtmlWin::GoSearch() | |
386 | { | |
387 | HRESULT hret = 0; | |
388 | hret = m_webBrowser->GoSearch(); | |
389 | return hret == S_OK; | |
390 | } | |
391 | ||
392 | bool wxIEHtmlWin::Refresh(wxIEHtmlRefreshLevel level) | |
393 | { | |
394 | VARIANTARG levelArg; | |
395 | HRESULT hret = 0; | |
396 | ||
397 | levelArg.vt = VT_I2; | |
398 | levelArg.iVal = level; | |
399 | hret = m_webBrowser->Refresh2(&levelArg); | |
400 | return hret == S_OK; | |
401 | } | |
402 | ||
403 | bool wxIEHtmlWin::Stop() | |
404 | { | |
405 | HRESULT hret = 0; | |
406 | hret = m_webBrowser->Stop(); | |
407 | return hret == S_OK; | |
408 | } | |
409 | ||
83a73288 | 410 | |
c731eb47 RD |
411 | /////////////////////////////////////////////////////////////////////////////// |
412 | ||
413 | static wxAutoOleInterface<IHTMLSelectionObject> GetSelObject(IOleObject *oleObject) | |
414 | { | |
415 | // Query for IWebBrowser interface | |
416 | wxAutoOleInterface<IWebBrowser2> wb(IID_IWebBrowser2, oleObject); | |
417 | if (! wb.Ok()) | |
418 | return wxAutoOleInterface<IHTMLSelectionObject>(); | |
419 | ||
420 | IDispatch *iDisp = NULL; | |
421 | HRESULT hr = wb->get_Document(&iDisp); | |
422 | if (hr != S_OK) | |
423 | return wxAutoOleInterface<IHTMLSelectionObject>(); | |
424 | ||
425 | // Query for Document Interface | |
426 | wxAutoOleInterface<IHTMLDocument2> hd(IID_IHTMLDocument2, iDisp); | |
427 | iDisp->Release(); | |
428 | ||
429 | if (! hd.Ok()) | |
430 | return wxAutoOleInterface<IHTMLSelectionObject>(); | |
431 | ||
432 | IHTMLSelectionObject *_so = NULL; | |
433 | hr = hd->get_selection(&_so); | |
434 | ||
435 | // take ownership of selection object | |
436 | wxAutoOleInterface<IHTMLSelectionObject> so(_so); | |
437 | ||
438 | return so; | |
439 | }; | |
440 | ||
441 | static wxAutoOleInterface<IHTMLTxtRange> GetSelRange(IOleObject *oleObject) | |
442 | { | |
443 | wxAutoOleInterface<IHTMLTxtRange> tr; | |
444 | ||
445 | wxAutoOleInterface<IHTMLSelectionObject> so(GetSelObject(oleObject)); | |
446 | if (! so) | |
447 | return tr; | |
448 | ||
449 | IDispatch *iDisp = NULL; | |
450 | HRESULT hr = so->createRange(&iDisp); | |
451 | if (hr != S_OK) | |
452 | return tr; | |
453 | ||
454 | // Query for IHTMLTxtRange interface | |
455 | tr.QueryInterface(IID_IHTMLTxtRange, iDisp); | |
456 | iDisp->Release(); | |
457 | return tr; | |
458 | }; | |
459 | ||
460 | ||
461 | wxString wxIEHtmlWin::GetStringSelection(bool asHTML) | |
462 | { | |
463 | wxAutoOleInterface<IHTMLTxtRange> tr(GetSelRange(m_oleObject)); | |
464 | if (! tr) | |
465 | return ""; | |
466 | ||
467 | BSTR text = NULL; | |
468 | HRESULT hr = E_FAIL; | |
811712d8 | 469 | |
c731eb47 RD |
470 | if (asHTML) |
471 | hr = tr->get_htmlText(&text); | |
472 | else | |
473 | hr = tr->get_text(&text); | |
474 | if (hr != S_OK) | |
475 | return ""; | |
476 | ||
477 | wxString s = text; | |
478 | SysFreeString(text); | |
479 | ||
480 | return s; | |
481 | }; | |
482 | ||
483 | wxString wxIEHtmlWin::GetText(bool asHTML) | |
484 | { | |
485 | if (! m_webBrowser.Ok()) | |
486 | return ""; | |
487 | ||
488 | // get document dispatch interface | |
489 | IDispatch *iDisp = NULL; | |
490 | HRESULT hr = m_webBrowser->get_Document(&iDisp); | |
491 | if (hr != S_OK) | |
492 | return ""; | |
493 | ||
494 | // Query for Document Interface | |
495 | wxAutoOleInterface<IHTMLDocument2> hd(IID_IHTMLDocument2, iDisp); | |
496 | iDisp->Release(); | |
497 | ||
498 | if (! hd.Ok()) | |
499 | return ""; | |
500 | ||
501 | // get body element | |
502 | IHTMLElement *_body = NULL; | |
503 | hd->get_body(&_body); | |
504 | if (! _body) | |
505 | return ""; | |
506 | wxAutoOleInterface<IHTMLElement> body(_body); | |
507 | ||
508 | // get inner text | |
509 | BSTR text = NULL; | |
510 | hr = E_FAIL; | |
811712d8 | 511 | |
c731eb47 RD |
512 | if (asHTML) |
513 | hr = body->get_innerHTML(&text); | |
514 | else | |
515 | hr = body->get_innerText(&text); | |
516 | if (hr != S_OK) | |
517 | return ""; | |
518 | ||
519 | wxString s = text; | |
520 | SysFreeString(text); | |
521 | ||
811712d8 RD |
522 | return s; |
523 | }; |