[EXPLORER]
[reactos.git] / reactos / base / shell / 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 #include <comutil.h>
37
38 //#include <mshtml.h>
39
40
41 Variant::Variant(const VARIANT& var)
42 {
43 VariantInit(this);
44 CheckError(VariantCopy(this, const_cast<VARIANT*>(&var)));
45 }
46
47 Variant::Variant(const VARIANT* var)
48 {
49 VariantInit(this);
50 CheckError(VariantCopy(this, const_cast<VARIANT*>(var)));
51 }
52
53 Variant::~Variant()
54 {
55 VariantClear(this);
56 }
57
58
59 Variant::operator long() const
60 {
61 Variant v;
62 CheckError(VariantChangeType(&v, (VARIANT*)this, 0, VT_I4));
63 return V_I4(&v);
64 }
65
66 Variant::operator bool() const
67 {
68 Variant v;
69 CheckError(VariantChangeType(&v, (VARIANT*)this, 0, VT_BOOL));
70 return V_BOOL(&v)? true: false;
71 }
72
73 Variant::operator IDispatch*() const
74 {
75 Variant v;
76 CheckError(VariantChangeType(&v, (VARIANT*)this, 0, VT_DISPATCH));
77 return V_DISPATCH(&v);
78 }
79
80 Variant::operator VARIANT_BOOL() const
81 {
82 Variant v;
83 CheckError(VariantChangeType(&v, (VARIANT*)this, 0, VT_BOOL));
84 return V_BOOL(&v);
85 }
86
87
88 void BStr::assign(BSTR s)
89 {
90 if (!SysReAllocString(&_p, s))
91 THROW_EXCEPTION(E_OUTOFMEMORY);
92 }
93
94 void BStr::assign(const VARIANT& var)
95 {
96 if (V_VT(&var) == VT_BSTR)
97 assign(V_BSTR(&var));
98 else {
99 Variant v;
100 CheckError(VariantChangeType(&v, const_cast<VARIANT*>(&var), 0, VT_BSTR));
101 assign(V_BSTR(&v));
102 }
103 }
104
105
106 BrowserNavigator::BrowserNavigator()
107 : _browser_initialized(false)
108 {
109 }
110
111 void BrowserNavigator::attach(IWebBrowser* browser)
112 {
113 _browser = browser;
114 }
115
116 void BrowserNavigator::goto_url(LPCTSTR url)
117 {
118 if (_browser_initialized)
119 _browser->Navigate(BStr(url), NULL, NULL, NULL, NULL);
120 else {
121 _new_url = url;
122
123 _browser->Navigate(BStr(L"about:blank"), NULL, NULL, NULL, NULL);
124 }
125 }
126
127 void BrowserNavigator::set_html_page(const String& html_txt)
128 {
129 _new_html_txt = html_txt;
130
131 goto_url(TEXT("about:blank"));
132 }
133
134 void T2nA_binary(LPCTSTR s, LPSTR d, int len)
135 {
136 while(len-- > 0)
137 *d++ = (unsigned char)*s++;
138 }
139
140 void BrowserNavigator::navigated(LPCTSTR url)
141 {
142 _browser_initialized = true;
143
144 bool nav = false;
145
146 if (!_new_url.empty()) {
147 if (!_tcscmp(url,TEXT("about:blank")) && _new_url!=TEXT("about:blank")) {
148 _browser->Navigate(BStr(_new_url), NULL, NULL, NULL, NULL);
149 ++nav;
150 }
151
152 _new_url.erase();
153 }
154
155 if (!nav && !_new_html_txt.empty()) { ///@todo move this into DocumentComplete() ?
156 int len = _new_html_txt.length();
157 HGLOBAL hHtmlText = GlobalAlloc(GPTR, len);
158
159 if (!hHtmlText) {
160 T2nA_binary(_new_html_txt, (char*)hHtmlText, len);
161 _new_html_txt.erase();
162
163 SIfacePtr<IStream> pStream;
164 HRESULT hr = CreateStreamOnHGlobal(hHtmlText, TRUE, &pStream);
165
166 if (SUCCEEDED(hr)) {
167 SIfacePtr<IDispatch> pHtmlDoc;
168 CheckError(_browser->get_Document(&pHtmlDoc));
169
170 SIfacePtr<IPersistStreamInit> pPersistStreamInit;
171 pHtmlDoc.QueryInterface(IID_IPersistStreamInit, &pPersistStreamInit);
172
173 CheckError(pPersistStreamInit->InitNew());
174 CheckError(pPersistStreamInit->Load(pStream));
175 } else
176 GlobalFree(hHtmlText);
177 }
178 }
179 }
180
181
182 HWND create_webchildwindow(const WebChildWndInfo& info)
183 {
184 WebChildWindow* pWnd = WebChildWindow::create(info);
185
186 if (!pWnd)
187 return 0;
188
189 return *pWnd;
190 }
191
192 static const CLSID CLSID_MozillaBrowser =
193 {0x1339B54C, 0x3453, 0x11D2, {0x93, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
194
195
196 WebChildWindow::WebChildWindow(HWND hwnd, const WebChildWndInfo& info)
197 : super(hwnd, info),
198 web_super(_navigator)
199 {
200 // first try to create a web control with MS IE's CLASSID
201 HRESULT hr = create_control(hwnd, CLSID_WebBrowser, IID_IWebBrowser2);
202
203 // If this failed, try to use Mozilla's web control
204 if (FAILED(hr))
205 hr = create_control(hwnd, CLSID_MozillaBrowser, IID_IWebBrowser2);
206
207 if (SUCCEEDED(hr)) {
208 _navigator.attach(_control);
209
210 _connector = auto_ptr<EventConnector>(new EventConnector(_control, DIID_DWebBrowserEvents2, this));
211
212 _control->Navigate(BStr(info._path), &vtMissing, &vtMissing, &vtMissing, &vtMissing);
213 //browser->Navigate2(&Variant(info._path), &vtMissing, &vtMissing, &vtMissing, &vtMissing);
214 }
215 }
216
217 LRESULT WebChildWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
218 {
219 try {
220 switch(nmsg) {
221 case WM_ERASEBKGND:
222 if (!_control) {
223 HDC hdc = (HDC)wparam;
224 ClientRect rect(_hwnd);
225
226 HBRUSH hbrush = CreateSolidBrush(RGB(200,200,235));
227 BkMode mode(hdc, TRANSPARENT);
228 TextColor color(hdc, RGB(200,40,40));
229 FillRect(hdc, &rect, hbrush);
230 DrawText(hdc, TEXT("Sorry - no web browser control could be loaded."), -1, &rect, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
231 DeleteObject(hbrush);
232 }
233
234 return TRUE;
235
236 case PM_DISPATCH_COMMAND: {
237 if (!_control)
238 return FALSE;
239
240 HRESULT hr = E_FAIL;
241
242 switch(LOWORD(wparam)) {
243 case ID_GO_BACK:
244 hr = _control->GoBack();
245 break;
246
247 case ID_GO_FORWARD:
248 hr = _control->GoForward();
249 break;
250
251 case ID_GO_UP:
252 ///@todo
253 break;
254
255 case ID_GO_HOME:
256 hr = _control->GoHome();
257 break;
258
259 case ID_GO_SEARCH:
260 hr = _control->GoSearch();
261 break;
262
263 case ID_REFRESH:
264 hr = _control->Refresh();
265 break;
266
267 case ID_STOP:
268 hr = _control->Stop();
269 break;
270
271 default:
272 return super::WndProc(nmsg, wparam, lparam);
273 }
274
275 if (FAILED(hr) && hr!=E_FAIL)
276 THROW_EXCEPTION(hr);
277
278 return TRUE;}
279
280 default:
281 return super::WndProc(nmsg, wparam, lparam);
282 }
283 } catch(COMException& e) {
284 HandleException(e, _hwnd);
285 }
286
287 return 0;
288 }
289
290
291 String WebChildWindow::jump_to_int(LPCTSTR url)
292 {
293 _navigator.goto_url(url);
294
295 return url;
296 }