reinitialize image list in ShellBrowser::invalidate_cache()
[reactos.git] / reactos / subsys / system / explorer / shell / webchild.cpp
1 /*
2 * Copyright 2004, 2005 Martin Fuchs
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19
20 //
21 // Explorer clone
22 //
23 // webchild.cpp
24 //
25 // Martin Fuchs, 08.02.2004
26 //
27
28
29 #include <precomp.h>
30
31 #include "../resource.h"
32
33 #include "webchild.h"
34
35
36 #ifdef _MSC_VER
37
38 #if _MSC_VER>=1300 // vtMissing for VS.Net
39 #include <comutil.h>
40 #pragma comment(lib, "comsupp")
41 #endif
42
43 #else
44
45 #ifdef __MINGW32__ // MinGW is lacking vtMissing (as of 07.02.2004)
46 static Variant vtMissing;
47 #endif
48
49 #endif
50
51 //#include <mshtml.h>
52
53
54 Variant::Variant(const VARIANT& var)
55 {
56 VariantInit(this);
57 CheckError(VariantCopy(this, const_cast<VARIANT*>(&var)));
58 }
59
60 Variant::Variant(const VARIANT* var)
61 {
62 VariantInit(this);
63 CheckError(VariantCopy(this, const_cast<VARIANT*>(var)));
64 }
65
66 Variant::~Variant()
67 {
68 VariantClear(this);
69 }
70
71
72 Variant::operator long() const
73 {
74 Variant v;
75 CheckError(VariantChangeType(&v, (VARIANT*)this, 0, VT_I4));
76 return V_I4(&v);
77 }
78
79 Variant::operator bool() const
80 {
81 Variant v;
82 CheckError(VariantChangeType(&v, (VARIANT*)this, 0, VT_BOOL));
83 return V_BOOL(&v)? true: false;
84 }
85
86 Variant::operator IDispatch*() const
87 {
88 Variant v;
89 CheckError(VariantChangeType(&v, (VARIANT*)this, 0, VT_DISPATCH));
90 return V_DISPATCH(&v);
91 }
92
93 Variant::operator VARIANT_BOOL() const
94 {
95 Variant v;
96 CheckError(VariantChangeType(&v, (VARIANT*)this, 0, VT_BOOL));
97 return V_BOOL(&v);
98 }
99
100
101 void BStr::assign(BSTR s)
102 {
103 if (!SysReAllocString(&_p, s))
104 THROW_EXCEPTION(E_OUTOFMEMORY);
105 }
106
107 void BStr::assign(const VARIANT& var)
108 {
109 if (V_VT(&var) == VT_BSTR)
110 assign(V_BSTR(&var));
111 else {
112 Variant v;
113 CheckError(VariantChangeType(&v, const_cast<VARIANT*>(&var), 0, VT_BSTR));
114 assign(V_BSTR(&v));
115 }
116 }
117
118
119 BrowserNavigator::BrowserNavigator()
120 : _browser_initialized(false)
121 {
122 }
123
124 void BrowserNavigator::attach(IWebBrowser* browser)
125 {
126 _browser = browser;
127 }
128
129 void BrowserNavigator::goto_url(LPCTSTR url)
130 {
131 if (_browser_initialized)
132 _browser->Navigate(BStr(url), NULL, NULL, NULL, NULL);
133 else {
134 _new_url = url;
135
136 _browser->Navigate(L"about:blank", NULL, NULL, NULL, NULL);
137 }
138 }
139
140 void BrowserNavigator::set_html_page(const String& html_txt)
141 {
142 _new_html_txt = html_txt;
143
144 goto_url(TEXT("about:blank"));
145 }
146
147 void T2nA_binary(LPCTSTR s, LPSTR d, int len)
148 {
149 while(len-- > 0)
150 *d++ = (unsigned char)*s++;
151 }
152
153 void BrowserNavigator::navigated(LPCTSTR url)
154 {
155 _browser_initialized = true;
156
157 bool nav = false;
158
159 if (!_new_url.empty()) {
160 if (!_tcscmp(url,TEXT("about:blank")) && _new_url!=TEXT("about:blank")) {
161 _browser->Navigate(BStr(_new_url), NULL, NULL, NULL, NULL);
162 ++nav;
163 }
164
165 _new_url.erase();
166 }
167
168 if (!nav && !_new_html_txt.empty()) { ///@todo move this into DocumentComplete() ?
169 int len = _new_html_txt.length();
170 HGLOBAL hHtmlText = GlobalAlloc(GPTR, len);
171
172 if (!hHtmlText) {
173 T2nA_binary(_new_html_txt, (char*)hHtmlText, len);
174 _new_html_txt.erase();
175
176 SIfacePtr<IStream> pStream;
177 HRESULT hr = CreateStreamOnHGlobal(hHtmlText, TRUE, &pStream);
178
179 if (SUCCEEDED(hr)) {
180 SIfacePtr<IDispatch> pHtmlDoc;
181 CheckError(_browser->get_Document(&pHtmlDoc));
182
183 SIfacePtr<IPersistStreamInit> pPersistStreamInit;
184 pHtmlDoc.QueryInterface(IID_IPersistStreamInit, &pPersistStreamInit);
185
186 CheckError(pPersistStreamInit->InitNew());
187 CheckError(pPersistStreamInit->Load(pStream));
188 } else
189 GlobalFree(hHtmlText);
190 }
191 }
192 }
193
194
195 HWND create_webchildwindow(const WebChildWndInfo& info)
196 {
197 WebChildWindow* pWnd = WebChildWindow::create(info);
198
199 if (!pWnd)
200 return 0;
201
202 return *pWnd;
203 }
204
205 static const CLSID CLSID_MozillaBrowser =
206 {0x1339B54C, 0x3453, 0x11D2, {0x93, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
207
208
209 WebChildWindow::WebChildWindow(HWND hwnd, const WebChildWndInfo& info)
210 : super(hwnd, info),
211 web_super(_navigator)
212 {
213 // first try to create a web control with MS IE's CLASSID
214 HRESULT hr = create_control(hwnd, CLSID_WebBrowser, IID_IWebBrowser2);
215
216 // If this failed, try to use Mozilla's web control
217 if (FAILED(hr))
218 hr = create_control(hwnd, CLSID_MozillaBrowser, IID_IWebBrowser2);
219
220 if (SUCCEEDED(hr)) {
221 _navigator.attach(_control);
222
223 _connector = auto_ptr<EventConnector>(new EventConnector(_control, DIID_DWebBrowserEvents2, this));
224
225 _control->Navigate(BStr(info._path), &vtMissing, &vtMissing, &vtMissing, &vtMissing);
226 //browser->Navigate2(&Variant(info._path), &vtMissing, &vtMissing, &vtMissing, &vtMissing);
227 }
228 }
229
230 LRESULT WebChildWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
231 {
232 try {
233 switch(nmsg) {
234 case WM_ERASEBKGND:
235 if (!_control) {
236 HDC hdc = (HDC)wparam;
237 ClientRect rect(_hwnd);
238
239 HBRUSH hbrush = CreateSolidBrush(RGB(200,200,235));
240 BkMode mode(hdc, TRANSPARENT);
241 TextColor color(hdc, RGB(200,40,40));
242 FillRect(hdc, &rect, hbrush);
243 DrawText(hdc, TEXT("Sorry - no web browser control could be loaded."), -1, &rect, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
244 DeleteObject(hbrush);
245 }
246
247 return TRUE;
248
249 case PM_DISPATCH_COMMAND: {
250 if (!_control)
251 return FALSE;
252
253 HRESULT hr = E_FAIL;
254
255 switch(LOWORD(wparam)) {
256 case ID_GO_BACK:
257 hr = _control->GoBack();
258 break;
259
260 case ID_GO_FORWARD:
261 hr = _control->GoForward();
262 break;
263
264 case ID_GO_UP:
265 ///@todo
266 break;
267
268 case ID_GO_HOME:
269 hr = _control->GoHome();
270 break;
271
272 case ID_GO_SEARCH:
273 hr = _control->GoSearch();
274 break;
275
276 case ID_REFRESH:
277 hr = _control->Refresh();
278 break;
279
280 case ID_STOP:
281 hr = _control->Stop();
282 break;
283
284 default:
285 return super::WndProc(nmsg, wparam, lparam);
286 }
287
288 if (FAILED(hr) && hr!=E_FAIL)
289 THROW_EXCEPTION(hr);
290
291 return TRUE;}
292
293 default:
294 return super::WndProc(nmsg, wparam, lparam);
295 }
296 } catch(COMException& e) {
297 HandleException(e, _hwnd);
298 }
299
300 return 0;
301 }
302
303
304 String WebChildWindow::jump_to_int(LPCTSTR url)
305 {
306 _navigator.goto_url(url);
307
308 return url;
309 }