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