]>
Commit | Line | Data |
---|---|---|
61b98a2d | 1 | ///////////////////////////////////////////////////////////////////////////// |
8290e3cd | 2 | // Name: src/msw/webview_ie.cpp |
61b98a2d SL |
3 | // Purpose: wxMSW wxWebViewIE class implementation for web view component |
4 | // Author: Marianne Gagnon | |
5 | // Id: $Id$ | |
74af0b13 | 6 | // Copyright: (c) 2010 Marianne Gagnon, Steven Lamerton |
61b98a2d SL |
7 | // Licence: wxWindows licence |
8 | ///////////////////////////////////////////////////////////////////////////// | |
9 | ||
384b8d9f SL |
10 | // For compilers that support precompilation, includes "wx.h". |
11 | #include "wx/wxprec.h" | |
12 | ||
13 | #if defined(__BORLANDC__) | |
14 | #pragma hdrstop | |
15 | #endif | |
16 | ||
8290e3cd | 17 | #include "wx/msw/webview_ie.h" |
61b98a2d | 18 | |
66f2aa61 | 19 | #if wxUSE_WEBVIEW_IE |
61b98a2d SL |
20 | |
21 | #include <olectl.h> | |
22 | #include <oleidl.h> | |
23 | #include <exdispid.h> | |
24 | #include <exdisp.h> | |
25 | #include <mshtml.h> | |
26 | ||
726cc869 | 27 | // Various definitions are missing from mingw |
97ad1425 | 28 | #ifdef __MINGW32__ |
61b98a2d SL |
29 | typedef enum CommandStateChangeConstants { |
30 | CSC_UPDATECOMMANDS = (int) 0xFFFFFFFF, | |
31 | CSC_NAVIGATEFORWARD = 0x1, | |
32 | CSC_NAVIGATEBACK = 0x2 | |
33 | } CommandStateChangeConstants; | |
34 | ||
726cc869 SL |
35 | #define DISPID_COMMANDSTATECHANGE 105 |
36 | #define DISPID_NAVIGATECOMPLETE2 252 | |
37 | #define DISPID_NAVIGATEERROR 271 | |
38 | #define DISPID_NEWWINDOW3 273 | |
39 | #define OLECMDID_OPTICAL_ZOOM 63 | |
61b98a2d SL |
40 | #define INET_E_ERROR_FIRST 0x800C0002L |
41 | #define INET_E_INVALID_URL 0x800C0002L | |
42 | #define INET_E_NO_SESSION 0x800C0003L | |
43 | #define INET_E_CANNOT_CONNECT 0x800C0004L | |
44 | #define INET_E_RESOURCE_NOT_FOUND 0x800C0005L | |
45 | #define INET_E_OBJECT_NOT_FOUND 0x800C0006L | |
46 | #define INET_E_DATA_NOT_AVAILABLE 0x800C0007L | |
47 | #define INET_E_DOWNLOAD_FAILURE 0x800C0008L | |
48 | #define INET_E_AUTHENTICATION_REQUIRED 0x800C0009L | |
49 | #define INET_E_NO_VALID_MEDIA 0x800C000AL | |
50 | #define INET_E_CONNECTION_TIMEOUT 0x800C000BL | |
51 | #define INET_E_INVALID_REQUEST 0x800C000CL | |
52 | #define INET_E_UNKNOWN_PROTOCOL 0x800C000DL | |
53 | #define INET_E_SECURITY_PROBLEM 0x800C000EL | |
54 | #define INET_E_CANNOT_LOAD_DATA 0x800C000FL | |
55 | #define INET_E_CANNOT_INSTANTIATE_OBJECT 0x800C0010L | |
56 | #define INET_E_QUERYOPTION_UNKNOWN 0x800C0013L | |
57 | #define INET_E_REDIRECT_FAILED 0x800C0014L | |
58 | #define INET_E_REDIRECT_TO_DIR 0x800C0015L | |
59 | #define INET_E_CANNOT_LOCK_REQUEST 0x800C0016L | |
60 | #define INET_E_USE_EXTEND_BINDING 0x800C0017L | |
61 | #define INET_E_TERMINATED_BIND 0x800C0018L | |
62 | #define INET_E_INVALID_CERTIFICATE 0x800C0019L | |
63 | #define INET_E_CODE_DOWNLOAD_DECLINED 0x800C0100L | |
64 | #define INET_E_RESULT_DISPATCHED 0x800C0200L | |
65 | #define INET_E_CANNOT_REPLACE_SFP_FILE 0x800C0300L | |
66 | #define INET_E_CODE_INSTALL_BLOCKED_BY_HASH_POLICY 0x800C0500L | |
67 | #define INET_E_CODE_INSTALL_SUPPRESSED 0x800C0400L | |
68 | ||
726cc869 | 69 | #define REFRESH_NORMAL 0 |
61b98a2d | 70 | #define REFRESH_COMPLETELY 3 |
97ad1425 | 71 | #endif |
61b98a2d SL |
72 | |
73 | BEGIN_EVENT_TABLE(wxWebViewIE, wxControl) | |
97ad1425 SL |
74 | EVT_ACTIVEX(wxID_ANY, wxWebViewIE::onActiveXEvent) |
75 | EVT_ERASE_BACKGROUND(wxWebViewIE::onEraseBg) | |
61b98a2d SL |
76 | END_EVENT_TABLE() |
77 | ||
78 | bool wxWebViewIE::Create(wxWindow* parent, | |
79 | wxWindowID id, | |
80 | const wxString& url, | |
81 | const wxPoint& pos, | |
82 | const wxSize& size, | |
83 | long style, | |
84 | const wxString& name) | |
85 | { | |
86 | if (!wxControl::Create(parent, id, pos, size, style, | |
87 | wxDefaultValidator, name)) | |
88 | { | |
89 | return false; | |
90 | } | |
91 | ||
92 | m_webBrowser = NULL; | |
93 | m_canNavigateBack = false; | |
94 | m_canNavigateForward = false; | |
95 | m_isBusy = false; | |
74af0b13 SL |
96 | m_historyLoadingFromList = false; |
97 | m_historyEnabled = true; | |
98 | m_historyPosition = -1; | |
61b98a2d SL |
99 | |
100 | if (::CoCreateInstance(CLSID_WebBrowser, NULL, | |
101 | CLSCTX_INPROC_SERVER, // CLSCTX_INPROC, | |
102 | IID_IWebBrowser2 , (void**)&m_webBrowser) != 0) | |
103 | { | |
104 | wxLogError("Failed to initialize IE, CoCreateInstance returned an error"); | |
105 | return false; | |
106 | } | |
107 | ||
108 | m_ie.SetDispatchPtr(m_webBrowser); // wxAutomationObject will release itself | |
109 | ||
110 | m_webBrowser->put_RegisterAsBrowser(VARIANT_TRUE); | |
111 | m_webBrowser->put_RegisterAsDropTarget(VARIANT_TRUE); | |
112 | //m_webBrowser->put_Silent(VARIANT_FALSE); | |
113 | ||
114 | m_container = new wxActiveXContainer(this, IID_IWebBrowser2, m_webBrowser); | |
115 | ||
116 | SetBackgroundStyle(wxBG_STYLE_PAINT); | |
117 | SetDoubleBuffered(true); | |
9ef101cd | 118 | LoadUrl(url); |
61b98a2d SL |
119 | return true; |
120 | } | |
121 | ||
122 | ||
123 | void wxWebViewIE::LoadUrl(const wxString& url) | |
124 | { | |
7fbc727b | 125 | m_ie.CallMethod("Navigate", (BSTR) url.wc_str(), NULL, NULL, NULL, NULL); |
61b98a2d SL |
126 | } |
127 | ||
22ca10fa | 128 | void wxWebViewIE::SetPage(const wxString& html, const wxString&) |
61b98a2d SL |
129 | { |
130 | LoadUrl("about:blank"); | |
131 | ||
132 | // Let the wx events generated for navigation events be processed, so | |
133 | // that the underlying IE component completes its Document object. | |
134 | // FIXME: calling wxYield is not elegant nor very reliable probably | |
135 | wxYield(); | |
136 | ||
61b98a2d SL |
137 | // TODO: consider the "baseUrl" parameter if possible |
138 | // TODO: consider encoding | |
139 | BSTR bstr = SysAllocString(html.wc_str()); | |
140 | ||
141 | // Creates a new one-dimensional array | |
142 | SAFEARRAY *psaStrings = SafeArrayCreateVector(VT_VARIANT, 0, 1); | |
143 | if (psaStrings != NULL) | |
144 | { | |
145 | VARIANT *param; | |
146 | HRESULT hr = SafeArrayAccessData(psaStrings, (LPVOID*)¶m); | |
147 | param->vt = VT_BSTR; | |
148 | param->bstrVal = bstr; | |
149 | ||
150 | hr = SafeArrayUnaccessData(psaStrings); | |
617227c3 | 151 | IHTMLDocument2* document = GetDocument(); |
61b98a2d SL |
152 | document->write(psaStrings); |
153 | ||
154 | // SafeArrayDestroy calls SysFreeString for each BSTR | |
155 | SafeArrayDestroy(psaStrings); | |
156 | } | |
157 | else | |
158 | { | |
159 | wxLogError("wxWebViewIE::SetPage() : psaStrings is NULL"); | |
160 | } | |
161 | ||
162 | } | |
163 | ||
164 | wxString wxWebViewIE::GetPageSource() | |
165 | { | |
617227c3 | 166 | IHTMLDocument2* document = GetDocument(); |
61b98a2d SL |
167 | IHTMLElement *bodyTag = NULL; |
168 | IHTMLElement *htmlTag = NULL; | |
7fbc727b SL |
169 | BSTR bstr; |
170 | HRESULT hr = document->get_body(&bodyTag); | |
171 | if(SUCCEEDED(hr)) | |
172 | { | |
173 | hr = bodyTag->get_parentElement(&htmlTag); | |
174 | if(SUCCEEDED(hr)) | |
175 | { | |
176 | htmlTag->get_outerHTML(&bstr); | |
177 | htmlTag->Release(); | |
178 | } | |
179 | bodyTag->Release(); | |
180 | } | |
61b98a2d SL |
181 | |
182 | document->Release(); | |
61b98a2d SL |
183 | return wxString(bstr); |
184 | } | |
185 | ||
186 | // FIXME? retrieve OLECMDID_GETZOOMRANGE instead of hardcoding range 0-4 | |
187 | wxWebViewZoom wxWebViewIE::GetZoom() | |
188 | { | |
189 | const int zoom = GetIETextZoom(); | |
190 | ||
191 | switch (zoom) | |
192 | { | |
193 | case 0: | |
194 | return wxWEB_VIEW_ZOOM_TINY; | |
195 | break; | |
196 | case 1: | |
197 | return wxWEB_VIEW_ZOOM_SMALL; | |
198 | break; | |
199 | case 2: | |
200 | return wxWEB_VIEW_ZOOM_MEDIUM; | |
201 | break; | |
202 | case 3: | |
203 | return wxWEB_VIEW_ZOOM_LARGE; | |
204 | break; | |
205 | case 4: | |
206 | return wxWEB_VIEW_ZOOM_LARGEST; | |
207 | break; | |
208 | default: | |
209 | wxASSERT(false); | |
210 | return wxWEB_VIEW_ZOOM_MEDIUM; | |
211 | } | |
212 | } | |
213 | void wxWebViewIE::SetZoom(wxWebViewZoom zoom) | |
214 | { | |
215 | // I know I could cast from enum to int since wxWebViewZoom happens to | |
216 | // match with IE's zoom levels, but I don't like doing that, what if enum | |
217 | // values change... | |
218 | switch (zoom) | |
219 | { | |
220 | case wxWEB_VIEW_ZOOM_TINY: | |
221 | SetIETextZoom(0); | |
222 | break; | |
223 | case wxWEB_VIEW_ZOOM_SMALL: | |
224 | SetIETextZoom(1); | |
225 | break; | |
226 | case wxWEB_VIEW_ZOOM_MEDIUM: | |
227 | SetIETextZoom(2); | |
228 | break; | |
229 | case wxWEB_VIEW_ZOOM_LARGE: | |
230 | SetIETextZoom(3); | |
231 | break; | |
232 | case wxWEB_VIEW_ZOOM_LARGEST: | |
233 | SetIETextZoom(4); | |
234 | break; | |
235 | default: | |
236 | wxASSERT(false); | |
237 | } | |
238 | } | |
239 | ||
240 | void wxWebViewIE::SetIETextZoom(int level) | |
241 | { | |
242 | VARIANT zoomVariant; | |
243 | VariantInit (&zoomVariant); | |
244 | V_VT(&zoomVariant) = VT_I4; | |
245 | V_I4(&zoomVariant) = level; | |
246 | ||
247 | HRESULT result = m_webBrowser->ExecWB(OLECMDID_ZOOM, | |
248 | OLECMDEXECOPT_DONTPROMPTUSER, | |
249 | &zoomVariant, NULL); | |
250 | wxASSERT (result == S_OK); | |
251 | ||
252 | VariantClear (&zoomVariant); | |
253 | } | |
254 | ||
255 | int wxWebViewIE::GetIETextZoom() | |
256 | { | |
257 | VARIANT zoomVariant; | |
258 | VariantInit (&zoomVariant); | |
259 | V_VT(&zoomVariant) = VT_I4; | |
260 | V_I4(&zoomVariant) = 4; | |
261 | ||
262 | HRESULT result = m_webBrowser->ExecWB(OLECMDID_ZOOM, | |
263 | OLECMDEXECOPT_DONTPROMPTUSER, | |
264 | NULL, &zoomVariant); | |
265 | wxASSERT (result == S_OK); | |
266 | ||
267 | int zoom = V_I4(&zoomVariant); | |
61b98a2d SL |
268 | VariantClear (&zoomVariant); |
269 | ||
270 | return zoom; | |
271 | } | |
272 | ||
273 | void wxWebViewIE::SetIEOpticalZoom(float zoom) | |
274 | { | |
275 | // TODO: add support for optical zoom (IE7+ only) | |
276 | ||
277 | // TODO: get range from OLECMDID_OPTICAL_GETZOOMRANGE instead of hardcoding? | |
278 | wxASSERT(zoom >= 10.0f); | |
279 | wxASSERT(zoom <= 1000.0f); | |
280 | ||
281 | VARIANT zoomVariant; | |
282 | VariantInit (&zoomVariant); | |
283 | V_VT(&zoomVariant) = VT_I4; | |
284 | V_I4(&zoomVariant) = (zoom * 100.0f); | |
285 | ||
286 | HRESULT result = m_webBrowser->ExecWB((OLECMDID)OLECMDID_OPTICAL_ZOOM, | |
287 | OLECMDEXECOPT_DODEFAULT, | |
288 | &zoomVariant, | |
289 | NULL); | |
290 | wxASSERT (result == S_OK); | |
291 | } | |
292 | ||
293 | float wxWebViewIE::GetIEOpticalZoom() | |
294 | { | |
295 | // TODO: add support for optical zoom (IE7+ only) | |
296 | ||
297 | VARIANT zoomVariant; | |
298 | VariantInit (&zoomVariant); | |
299 | V_VT(&zoomVariant) = VT_I4; | |
300 | V_I4(&zoomVariant) = -1; | |
301 | ||
302 | HRESULT result = m_webBrowser->ExecWB((OLECMDID)OLECMDID_OPTICAL_ZOOM, | |
303 | OLECMDEXECOPT_DODEFAULT, NULL, | |
304 | &zoomVariant); | |
305 | wxASSERT (result == S_OK); | |
306 | ||
307 | const int zoom = V_I4(&zoomVariant); | |
308 | VariantClear (&zoomVariant); | |
309 | ||
310 | return zoom / 100.0f; | |
311 | } | |
312 | ||
313 | void wxWebViewIE::SetZoomType(wxWebViewZoomType) | |
314 | { | |
315 | // TODO: add support for optical zoom (IE7+ only) | |
316 | wxASSERT(false); | |
317 | } | |
318 | ||
319 | wxWebViewZoomType wxWebViewIE::GetZoomType() const | |
320 | { | |
321 | // TODO: add support for optical zoom (IE7+ only) | |
322 | return wxWEB_VIEW_ZOOM_TYPE_TEXT; | |
323 | } | |
324 | ||
325 | bool wxWebViewIE::CanSetZoomType(wxWebViewZoomType) const | |
326 | { | |
327 | // both are supported | |
328 | // TODO: IE6 only supports text zoom, check if it's IE6 first | |
329 | return true; | |
330 | } | |
331 | ||
332 | void wxWebViewIE::Print() | |
333 | { | |
334 | m_webBrowser->ExecWB(OLECMDID_PRINTPREVIEW, | |
335 | OLECMDEXECOPT_DODEFAULT, NULL, NULL); | |
336 | } | |
337 | ||
74af0b13 | 338 | bool wxWebViewIE::CanGoBack() |
61b98a2d | 339 | { |
74af0b13 SL |
340 | if(m_historyEnabled) |
341 | return m_historyPosition > 0; | |
342 | else | |
343 | return false; | |
344 | } | |
61b98a2d | 345 | |
74af0b13 SL |
346 | bool wxWebViewIE::CanGoForward() |
347 | { | |
348 | if(m_historyEnabled) | |
22ca10fa | 349 | return m_historyPosition != static_cast<int>(m_historyList.size()) - 1; |
74af0b13 SL |
350 | else |
351 | return false; | |
61b98a2d SL |
352 | } |
353 | ||
3e7968c2 | 354 | void wxWebViewIE::LoadHistoryItem(wxSharedPtr<wxWebHistoryItem> item) |
61b98a2d | 355 | { |
74af0b13 SL |
356 | int pos = -1; |
357 | for(unsigned int i = 0; i < m_historyList.size(); i++) | |
358 | { | |
3e7968c2 SL |
359 | //We compare the actual pointers to find the correct item |
360 | if(m_historyList[i].get() == item.get()) | |
74af0b13 SL |
361 | pos = i; |
362 | } | |
22ca10fa SL |
363 | wxASSERT_MSG(pos != static_cast<int>(m_historyList.size()), |
364 | "invalid history item"); | |
74af0b13 SL |
365 | m_historyLoadingFromList = true; |
366 | LoadUrl(item->GetUrl()); | |
367 | m_historyPosition = pos; | |
368 | } | |
61b98a2d | 369 | |
5cbda74b SL |
370 | wxVector<wxSharedPtr<wxWebHistoryItem> > wxWebViewIE::GetBackwardHistory() |
371 | { | |
372 | wxVector<wxSharedPtr<wxWebHistoryItem> > backhist; | |
373 | //As we don't have std::copy or an iterator constructor in the wxwidgets | |
374 | //native vector we construct it by hand | |
375 | for(int i = 0; i < m_historyPosition; i++) | |
376 | { | |
377 | backhist.push_back(m_historyList[i]); | |
378 | } | |
379 | return backhist; | |
380 | } | |
381 | ||
382 | wxVector<wxSharedPtr<wxWebHistoryItem> > wxWebViewIE::GetForwardHistory() | |
383 | { | |
384 | wxVector<wxSharedPtr<wxWebHistoryItem> > forwardhist; | |
385 | //As we don't have std::copy or an iterator constructor in the wxwidgets | |
386 | //native vector we construct it by hand | |
22ca10fa | 387 | for(int i = m_historyPosition + 1; i < static_cast<int>(m_historyList.size()); i++) |
5cbda74b SL |
388 | { |
389 | forwardhist.push_back(m_historyList[i]); | |
390 | } | |
391 | return forwardhist; | |
392 | } | |
393 | ||
74af0b13 SL |
394 | void wxWebViewIE::GoBack() |
395 | { | |
3e7968c2 | 396 | LoadHistoryItem(m_historyList[m_historyPosition - 1]); |
74af0b13 SL |
397 | } |
398 | ||
399 | void wxWebViewIE::GoForward() | |
400 | { | |
3e7968c2 | 401 | LoadHistoryItem(m_historyList[m_historyPosition + 1]); |
61b98a2d SL |
402 | } |
403 | ||
404 | void wxWebViewIE::Stop() | |
405 | { | |
7fbc727b | 406 | m_ie.CallMethod("Stop"); |
61b98a2d SL |
407 | } |
408 | ||
74af0b13 SL |
409 | void wxWebViewIE::ClearHistory() |
410 | { | |
411 | m_historyList.clear(); | |
412 | m_historyPosition = -1; | |
413 | } | |
414 | ||
415 | void wxWebViewIE::EnableHistory(bool enable) | |
416 | { | |
417 | m_historyEnabled = enable; | |
418 | m_historyList.clear(); | |
419 | m_historyPosition = -1; | |
420 | } | |
61b98a2d SL |
421 | |
422 | void wxWebViewIE::Reload(wxWebViewReloadFlags flags) | |
423 | { | |
7aa18fc7 SL |
424 | VARIANTARG level; |
425 | VariantInit(&level); | |
426 | V_VT(&level) = VT_I2; | |
61b98a2d | 427 | |
7aa18fc7 | 428 | switch(flags) |
61b98a2d | 429 | { |
7aa18fc7 SL |
430 | case wxWEB_VIEW_RELOAD_DEFAULT: |
431 | V_I2(&level) = REFRESH_NORMAL; | |
432 | break; | |
433 | case wxWEB_VIEW_RELOAD_NO_CACHE: | |
434 | V_I2(&level) = REFRESH_COMPLETELY; | |
435 | break; | |
436 | default: | |
437 | wxFAIL_MSG("Unexpected reload type"); | |
61b98a2d SL |
438 | } |
439 | ||
7aa18fc7 | 440 | m_webBrowser->Refresh2(&level); |
61b98a2d SL |
441 | } |
442 | ||
443 | bool wxWebViewIE::IsOfflineMode() | |
444 | { | |
445 | wxVariant out = m_ie.GetProperty("Offline"); | |
446 | ||
447 | wxASSERT(out.GetType() == "bool"); | |
448 | ||
449 | return out.GetBool(); | |
450 | } | |
451 | ||
452 | void wxWebViewIE::SetOfflineMode(bool offline) | |
453 | { | |
454 | // FIXME: the wxWidgets docs do not really document what the return | |
455 | // parameter of PutProperty is | |
456 | const bool success = m_ie.PutProperty("Offline", (offline ? | |
457 | VARIANT_TRUE : | |
458 | VARIANT_FALSE)); | |
459 | wxASSERT(success); | |
460 | } | |
461 | ||
462 | bool wxWebViewIE::IsBusy() | |
463 | { | |
464 | if (m_isBusy) return true; | |
465 | ||
466 | wxVariant out = m_ie.GetProperty("Busy"); | |
467 | ||
468 | wxASSERT(out.GetType() == "bool"); | |
469 | ||
470 | return out.GetBool(); | |
471 | } | |
472 | ||
473 | wxString wxWebViewIE::GetCurrentURL() | |
474 | { | |
475 | wxVariant out = m_ie.GetProperty("LocationURL"); | |
476 | ||
477 | wxASSERT(out.GetType() == "string"); | |
478 | return out.GetString(); | |
479 | } | |
480 | ||
481 | wxString wxWebViewIE::GetCurrentTitle() | |
482 | { | |
617227c3 | 483 | IHTMLDocument2* document = GetDocument(); |
977c5320 | 484 | BSTR title; |
7fbc727b | 485 | |
977c5320 | 486 | document->get_nameProp(&title); |
7fbc727b | 487 | document->Release(); |
977c5320 | 488 | return wxString(title); |
61b98a2d SL |
489 | } |
490 | ||
4681a3ea SL |
491 | bool wxWebViewIE::CanCut() |
492 | { | |
493 | return CanExecCommand("Cut"); | |
494 | } | |
495 | ||
496 | bool wxWebViewIE::CanCopy() | |
497 | { | |
498 | return CanExecCommand("Copy"); | |
499 | } | |
500 | bool wxWebViewIE::CanPaste() | |
501 | { | |
502 | return CanExecCommand("Paste"); | |
503 | } | |
504 | ||
505 | void wxWebViewIE::Cut() | |
506 | { | |
507 | ExecCommand("Cut"); | |
508 | } | |
509 | ||
510 | void wxWebViewIE::Copy() | |
511 | { | |
512 | ExecCommand("Copy"); | |
513 | } | |
514 | ||
515 | void wxWebViewIE::Paste() | |
516 | { | |
517 | ExecCommand("Paste"); | |
518 | } | |
519 | ||
97e49559 SL |
520 | bool wxWebViewIE::CanUndo() |
521 | { | |
522 | return CanExecCommand("Undo"); | |
523 | } | |
524 | bool wxWebViewIE::CanRedo() | |
525 | { | |
526 | return CanExecCommand("Redo"); | |
527 | } | |
528 | ||
529 | void wxWebViewIE::Undo() | |
530 | { | |
531 | ExecCommand("Undo"); | |
532 | } | |
533 | ||
534 | void wxWebViewIE::Redo() | |
535 | { | |
536 | ExecCommand("Redo"); | |
537 | } | |
538 | ||
c7cbe308 SL |
539 | void wxWebViewIE::SetEditable(bool enable) |
540 | { | |
541 | IHTMLDocument2* document = GetDocument(); | |
542 | if( enable ) | |
543 | document->put_designMode(SysAllocString(L"On")); | |
544 | else | |
545 | document->put_designMode(SysAllocString(L"Off")); | |
7fbc727b SL |
546 | |
547 | document->Release(); | |
c7cbe308 SL |
548 | } |
549 | ||
550 | bool wxWebViewIE::IsEditable() | |
551 | { | |
552 | IHTMLDocument2* document = GetDocument(); | |
553 | BSTR mode; | |
554 | document->get_designMode(&mode); | |
555 | if(wxString(mode) == "On") | |
556 | return true; | |
557 | else | |
558 | return false; | |
7fbc727b SL |
559 | |
560 | document->Release(); | |
c7cbe308 SL |
561 | } |
562 | ||
63a65070 SL |
563 | void wxWebViewIE::SelectAll() |
564 | { | |
565 | ExecCommand("SelectAll"); | |
566 | } | |
567 | ||
568 | bool wxWebViewIE::HasSelection() | |
569 | { | |
570 | IHTMLDocument2* document = GetDocument(); | |
571 | IHTMLSelectionObject* selection; | |
63a65070 | 572 | BSTR type; |
7fbc727b SL |
573 | HRESULT hr = document->get_selection(&selection); |
574 | if(SUCCEEDED(hr)) | |
575 | { | |
576 | selection->get_type(&type); | |
577 | selection->Release(); | |
578 | } | |
579 | document->Release(); | |
63a65070 SL |
580 | return wxString(type) != "None"; |
581 | } | |
582 | ||
583 | void wxWebViewIE::DeleteSelection() | |
584 | { | |
585 | ExecCommand("Delete"); | |
586 | } | |
587 | ||
c9355a3d SL |
588 | wxString wxWebViewIE::GetSelectedText() |
589 | { | |
590 | IHTMLDocument2* document = GetDocument(); | |
591 | IHTMLSelectionObject* selection; | |
592 | wxString selected; | |
593 | HRESULT hr = document->get_selection(&selection); | |
594 | if(SUCCEEDED(hr)) | |
595 | { | |
596 | IDispatch* disrange; | |
597 | hr = selection->createRange(&disrange); | |
598 | if(SUCCEEDED(hr)) | |
599 | { | |
600 | IHTMLTxtRange* range; | |
601 | hr = disrange->QueryInterface(IID_IHTMLTxtRange, (void**)&range); | |
602 | if(SUCCEEDED(hr)) | |
603 | { | |
604 | BSTR text; | |
605 | range->get_text(&text); | |
606 | selected = wxString(text); | |
607 | range->Release(); | |
608 | } | |
609 | disrange->Release(); | |
610 | } | |
611 | selection->Release(); | |
612 | } | |
613 | document->Release(); | |
614 | return selected; | |
615 | } | |
616 | ||
4681a3ea SL |
617 | bool wxWebViewIE::CanExecCommand(wxString command) |
618 | { | |
617227c3 | 619 | IHTMLDocument2* document = GetDocument(); |
4681a3ea | 620 | VARIANT_BOOL enabled; |
7fbc727b | 621 | |
4681a3ea | 622 | document->queryCommandEnabled(SysAllocString(command.wc_str()), &enabled); |
7fbc727b | 623 | document->Release(); |
4681a3ea SL |
624 | |
625 | return (enabled == VARIANT_TRUE); | |
626 | } | |
627 | ||
628 | void wxWebViewIE::ExecCommand(wxString command) | |
629 | { | |
617227c3 SL |
630 | IHTMLDocument2* document = GetDocument(); |
631 | document->execCommand(SysAllocString(command.wc_str()), VARIANT_FALSE, VARIANT(), NULL); | |
7fbc727b | 632 | document->Release(); |
617227c3 | 633 | } |
4681a3ea | 634 | |
617227c3 SL |
635 | IHTMLDocument2* wxWebViewIE::GetDocument() |
636 | { | |
637 | wxVariant variant = m_ie.GetProperty("Document"); | |
638 | IHTMLDocument2* document = (IHTMLDocument2*)variant.GetVoidPtr(); | |
4681a3ea | 639 | |
617227c3 SL |
640 | wxASSERT(document); |
641 | ||
642 | return document; | |
4681a3ea SL |
643 | } |
644 | ||
61b98a2d SL |
645 | void wxWebViewIE::onActiveXEvent(wxActiveXEvent& evt) |
646 | { | |
647 | if (m_webBrowser == NULL) return; | |
648 | ||
649 | switch (evt.GetDispatchId()) | |
650 | { | |
651 | case DISPID_BEFORENAVIGATE2: | |
652 | { | |
653 | m_isBusy = true; | |
654 | ||
655 | wxString url = evt[1].GetString(); | |
656 | wxString target = evt[3].GetString(); | |
657 | ||
658 | wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATING, | |
659 | GetId(), url, target, true); | |
660 | event.SetEventObject(this); | |
661 | HandleWindowEvent(event); | |
662 | ||
663 | if (event.IsVetoed()) | |
664 | { | |
665 | wxActiveXEventNativeMSW* nativeParams = | |
666 | evt.GetNativeParameters(); | |
667 | *V_BOOLREF(&nativeParams->pDispParams->rgvarg[0]) = VARIANT_TRUE; | |
668 | } | |
669 | ||
670 | // at this point, either the navigation event has been cancelled | |
671 | // and we're not busy, either it was accepted and IWebBrowser2's | |
672 | // Busy property will be true; so we don't need our override | |
673 | // flag anymore. | |
674 | m_isBusy = false; | |
675 | ||
676 | break; | |
677 | } | |
678 | ||
679 | case DISPID_NAVIGATECOMPLETE2: | |
680 | { | |
681 | wxString url = evt[1].GetString(); | |
682 | // TODO: set target parameter if possible | |
683 | wxString target = wxEmptyString; | |
684 | wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATED, | |
685 | GetId(), url, target, false); | |
686 | event.SetEventObject(this); | |
687 | HandleWindowEvent(event); | |
688 | break; | |
689 | } | |
690 | ||
691 | case DISPID_PROGRESSCHANGE: | |
692 | { | |
693 | // download progress | |
694 | break; | |
695 | } | |
696 | ||
697 | case DISPID_DOCUMENTCOMPLETE: | |
698 | { | |
3ee442ff SL |
699 | //Only send a complete even if we are actually finished, this brings |
700 | //the event in to line with webkit | |
701 | READYSTATE rs; | |
702 | m_webBrowser->get_ReadyState( &rs ); | |
703 | if(rs != READYSTATE_COMPLETE) | |
704 | break; | |
705 | ||
61b98a2d | 706 | wxString url = evt[1].GetString(); |
113e0a92 SL |
707 | |
708 | //As we are complete we also add to the history list, but not if the | |
709 | //page is not the main page, ie it is a subframe | |
710 | if(m_historyEnabled && !m_historyLoadingFromList && url == GetCurrentURL()) | |
74af0b13 SL |
711 | { |
712 | //If we are not at the end of the list, then erase everything | |
713 | //between us and the end before adding the new page | |
22ca10fa | 714 | if(m_historyPosition != static_cast<int>(m_historyList.size()) - 1) |
74af0b13 SL |
715 | { |
716 | m_historyList.erase(m_historyList.begin() + m_historyPosition + 1, | |
717 | m_historyList.end()); | |
718 | } | |
719 | wxSharedPtr<wxWebHistoryItem> item(new wxWebHistoryItem(url, GetCurrentTitle())); | |
720 | m_historyList.push_back(item); | |
721 | m_historyPosition++; | |
722 | } | |
723 | //Reset as we are done now | |
724 | m_historyLoadingFromList = false; | |
61b98a2d SL |
725 | // TODO: set target parameter if possible |
726 | wxString target = wxEmptyString; | |
727 | wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_LOADED, GetId(), | |
728 | url, target, false); | |
729 | event.SetEventObject(this); | |
730 | HandleWindowEvent(event); | |
731 | break; | |
732 | } | |
733 | ||
734 | case DISPID_STATUSTEXTCHANGE: | |
735 | { | |
736 | break; | |
737 | } | |
738 | ||
739 | case DISPID_TITLECHANGE: | |
740 | { | |
741 | break; | |
742 | } | |
743 | ||
744 | case DISPID_NAVIGATEERROR: | |
745 | { | |
746 | wxWebNavigationError errorType = wxWEB_NAV_ERR_OTHER; | |
747 | wxString errorCode = "?"; | |
748 | switch (evt[3].GetLong()) | |
749 | { | |
750 | case INET_E_INVALID_URL: // (0x800C0002L or -2146697214) | |
751 | errorCode = "INET_E_INVALID_URL"; | |
752 | errorType = wxWEB_NAV_ERR_REQUEST; | |
753 | break; | |
754 | case INET_E_NO_SESSION: // (0x800C0003L or -2146697213) | |
755 | errorCode = "INET_E_NO_SESSION"; | |
756 | errorType = wxWEB_NAV_ERR_CONNECTION; | |
757 | break; | |
758 | case INET_E_CANNOT_CONNECT: // (0x800C0004L or -2146697212) | |
759 | errorCode = "INET_E_CANNOT_CONNECT"; | |
760 | errorType = wxWEB_NAV_ERR_CONNECTION; | |
761 | break; | |
762 | case INET_E_RESOURCE_NOT_FOUND: // (0x800C0005L or -2146697211) | |
763 | errorCode = "INET_E_RESOURCE_NOT_FOUND"; | |
764 | errorType = wxWEB_NAV_ERR_NOT_FOUND; | |
765 | break; | |
766 | case INET_E_OBJECT_NOT_FOUND: // (0x800C0006L or -2146697210) | |
767 | errorCode = "INET_E_OBJECT_NOT_FOUND"; | |
768 | errorType = wxWEB_NAV_ERR_NOT_FOUND; | |
769 | break; | |
770 | case INET_E_DATA_NOT_AVAILABLE: // (0x800C0007L or -2146697209) | |
771 | errorCode = "INET_E_DATA_NOT_AVAILABLE"; | |
772 | errorType = wxWEB_NAV_ERR_NOT_FOUND; | |
773 | break; | |
774 | case INET_E_DOWNLOAD_FAILURE: // (0x800C0008L or -2146697208) | |
775 | errorCode = "INET_E_DOWNLOAD_FAILURE"; | |
776 | errorType = wxWEB_NAV_ERR_CONNECTION; | |
777 | break; | |
778 | case INET_E_AUTHENTICATION_REQUIRED: // (0x800C0009L or -2146697207) | |
779 | errorCode = "INET_E_AUTHENTICATION_REQUIRED"; | |
780 | errorType = wxWEB_NAV_ERR_AUTH; | |
781 | break; | |
782 | case INET_E_NO_VALID_MEDIA: // (0x800C000AL or -2146697206) | |
783 | errorCode = "INET_E_NO_VALID_MEDIA"; | |
784 | errorType = wxWEB_NAV_ERR_REQUEST; | |
785 | break; | |
786 | case INET_E_CONNECTION_TIMEOUT: // (0x800C000BL or -2146697205) | |
787 | errorCode = "INET_E_CONNECTION_TIMEOUT"; | |
788 | errorType = wxWEB_NAV_ERR_CONNECTION; | |
789 | break; | |
790 | case INET_E_INVALID_REQUEST: // (0x800C000CL or -2146697204) | |
791 | errorCode = "INET_E_INVALID_REQUEST"; | |
792 | errorType = wxWEB_NAV_ERR_REQUEST; | |
793 | break; | |
794 | case INET_E_UNKNOWN_PROTOCOL: // (0x800C000DL or -2146697203) | |
795 | errorCode = "INET_E_UNKNOWN_PROTOCOL"; | |
796 | errorType = wxWEB_NAV_ERR_REQUEST; | |
797 | break; | |
798 | case INET_E_SECURITY_PROBLEM: // (0x800C000EL or -2146697202) | |
799 | errorCode = "INET_E_SECURITY_PROBLEM"; | |
800 | errorType = wxWEB_NAV_ERR_SECURITY; | |
801 | break; | |
802 | case INET_E_CANNOT_LOAD_DATA: // (0x800C000FL or -2146697201) | |
803 | errorCode = "INET_E_CANNOT_LOAD_DATA"; | |
804 | errorType = wxWEB_NAV_ERR_OTHER; | |
805 | break; | |
806 | case INET_E_CANNOT_INSTANTIATE_OBJECT: | |
807 | // CoCreateInstance will return an error code if this happens, | |
808 | // we'll handle this above. | |
809 | return; | |
810 | break; | |
811 | case INET_E_REDIRECT_FAILED: // (0x800C0014L or -2146697196) | |
812 | errorCode = "INET_E_REDIRECT_FAILED"; | |
813 | errorType = wxWEB_NAV_ERR_OTHER; | |
814 | break; | |
815 | case INET_E_REDIRECT_TO_DIR: // (0x800C0015L or -2146697195) | |
816 | errorCode = "INET_E_REDIRECT_TO_DIR"; | |
817 | errorType = wxWEB_NAV_ERR_REQUEST; | |
818 | break; | |
819 | case INET_E_CANNOT_LOCK_REQUEST: // (0x800C0016L or -2146697194) | |
820 | errorCode = "INET_E_CANNOT_LOCK_REQUEST"; | |
821 | errorType = wxWEB_NAV_ERR_OTHER; | |
822 | break; | |
823 | case INET_E_USE_EXTEND_BINDING: // (0x800C0017L or -2146697193) | |
824 | errorCode = "INET_E_USE_EXTEND_BINDING"; | |
825 | errorType = wxWEB_NAV_ERR_OTHER; | |
826 | break; | |
827 | case INET_E_TERMINATED_BIND: // (0x800C0018L or -2146697192) | |
828 | errorCode = "INET_E_TERMINATED_BIND"; | |
829 | errorType = wxWEB_NAV_ERR_OTHER; | |
830 | break; | |
831 | case INET_E_INVALID_CERTIFICATE: // (0x800C0019L or -2146697191) | |
832 | errorCode = "INET_E_INVALID_CERTIFICATE"; | |
833 | errorType = wxWEB_NAV_ERR_CERTIFICATE; | |
834 | break; | |
835 | case INET_E_CODE_DOWNLOAD_DECLINED: // (0x800C0100L or -2146696960) | |
836 | errorCode = "INET_E_CODE_DOWNLOAD_DECLINED"; | |
837 | errorType = wxWEB_NAV_ERR_USER_CANCELLED; | |
838 | break; | |
839 | case INET_E_RESULT_DISPATCHED: // (0x800C0200L or -2146696704) | |
840 | // cancel request cancelled... | |
841 | errorCode = "INET_E_RESULT_DISPATCHED"; | |
842 | errorType = wxWEB_NAV_ERR_OTHER; | |
843 | break; | |
844 | case INET_E_CANNOT_REPLACE_SFP_FILE: // (0x800C0300L or -2146696448) | |
845 | errorCode = "INET_E_CANNOT_REPLACE_SFP_FILE"; | |
846 | errorType = wxWEB_NAV_ERR_SECURITY; | |
847 | break; | |
848 | case INET_E_CODE_INSTALL_BLOCKED_BY_HASH_POLICY: | |
849 | errorCode = "INET_E_CODE_INSTALL_BLOCKED_BY_HASH_POLICY"; | |
850 | errorType = wxWEB_NAV_ERR_SECURITY; | |
851 | break; | |
852 | case INET_E_CODE_INSTALL_SUPPRESSED: | |
853 | errorCode = "INET_E_CODE_INSTALL_SUPPRESSED"; | |
854 | errorType = wxWEB_NAV_ERR_SECURITY; | |
855 | break; | |
856 | } | |
857 | ||
858 | wxString url = evt[1].GetString(); | |
859 | wxString target = evt[2].GetString(); | |
860 | wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_ERROR, GetId(), | |
861 | url, target, false); | |
862 | event.SetEventObject(this); | |
863 | event.SetInt(errorType); | |
864 | event.SetString(errorCode); | |
865 | HandleWindowEvent(event); | |
866 | break; | |
867 | } | |
868 | ||
869 | case DISPID_COMMANDSTATECHANGE: | |
870 | { | |
871 | long commandId = evt[0].GetLong(); | |
872 | bool enable = evt[1].GetBool(); | |
873 | if (commandId == CSC_NAVIGATEBACK) | |
874 | { | |
875 | m_canNavigateBack = enable; | |
876 | } | |
877 | else if (commandId == CSC_NAVIGATEFORWARD) | |
878 | { | |
879 | m_canNavigateForward = enable; | |
880 | } | |
be19c556 | 881 | break; |
61b98a2d | 882 | } |
853b6cd0 | 883 | case DISPID_NEWWINDOW3: |
61b98a2d | 884 | { |
853b6cd0 SL |
885 | wxString url = evt[4].GetString(); |
886 | ||
887 | wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_NEWWINDOW, | |
888 | GetId(), url, wxEmptyString, true); | |
889 | event.SetEventObject(this); | |
890 | HandleWindowEvent(event); | |
891 | ||
892 | //If we veto the event then we cancel the new window | |
893 | if (event.IsVetoed()) | |
894 | { | |
895 | wxActiveXEventNativeMSW* nativeParams = evt.GetNativeParameters(); | |
896 | *V_BOOLREF(&nativeParams->pDispParams->rgvarg[3]) = VARIANT_TRUE; | |
897 | } | |
be19c556 SL |
898 | break; |
899 | } | |
61b98a2d SL |
900 | } |
901 | ||
902 | evt.Skip(); | |
903 | } | |
904 | ||
905 | #endif |