Browse Source

-tried to fix flicker when viewing images in description
- handle capital html
- handle copy when showing html

scott brogden 6 years ago
parent
commit
8edde0bc61
5 changed files with 1619 additions and 1573 deletions
  1. 7 0
      ImageViewer.cpp
  2. 40 39
      ImageViewer.h
  3. 1281 1271
      SimpleBrowser.cpp
  4. 259 257
      SimpleBrowser.h
  5. 32 6
      ToolTipEx.cpp

+ 7 - 0
ImageViewer.cpp

@@ -34,6 +34,7 @@ BEGIN_MESSAGE_MAP(CImageViewer, CWnd)
 	ON_WM_SETCURSOR()
 	ON_WM_LBUTTONUP()
 	ON_WM_MOUSEHWHEEL()
+	ON_WM_ERASEBKGND()
 END_MESSAGE_MAP()
 
 BOOL CImageViewer::Create(CWnd* pParent)
@@ -230,5 +231,11 @@ void CImageViewer::OnLButtonUp(UINT nFlags, CPoint point)
 	CWnd::OnLButtonUp(nFlags, point);
 }
 
+BOOL CImageViewer::OnEraseBkgnd(CDC* pDC)
+{
+	//OutputDebugString(_T("image viewer OnEraseBkgnd\r\n"));
+	//return CWnd::OnEraseBkgnd(pDC);
+	return FALSE;
+}
 
 

+ 40 - 39
ImageViewer.h

@@ -1,39 +1,40 @@
-#pragma once
-
-#include "ScrollHelper.h"
-#include "Clip.h"
-
-
-
-class CImageViewer : public CWnd
-{
-	DECLARE_DYNAMIC(CImageViewer)
-
-public:
-	CImageViewer();
-	virtual ~CImageViewer();
-
-	Gdiplus::Bitmap *m_pGdiplusBitmap;
-	CScrollHelper m_scrollHelper;
-
-	void UpdateBitmapSize();
-
-	BOOL Create(CWnd* pParent);
-
-	bool m_hoveringOverImage;
-
-protected:
-	DECLARE_MESSAGE_MAP()
-
-	afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
-	afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
-	afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
-	afx_msg void OnSize(UINT nType, int cx, int cy);
-	afx_msg void OnPaint();
-public:
-	afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
-	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
-	afx_msg void OnMouseHWheel(UINT nFlags, short zDelta, CPoint pt);
-};
-
-
+#pragma once
+
+#include "ScrollHelper.h"
+#include "Clip.h"
+
+
+
+class CImageViewer : public CWnd
+{
+	DECLARE_DYNAMIC(CImageViewer)
+
+public:
+	CImageViewer();
+	virtual ~CImageViewer();
+
+	Gdiplus::Bitmap *m_pGdiplusBitmap;
+	CScrollHelper m_scrollHelper;
+
+	void UpdateBitmapSize();
+
+	BOOL Create(CWnd* pParent);
+
+	bool m_hoveringOverImage;
+
+protected:
+	DECLARE_MESSAGE_MAP()
+
+	afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
+	afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
+	afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
+	afx_msg void OnSize(UINT nType, int cx, int cy);
+	afx_msg void OnPaint();
+public:
+	afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
+	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
+	afx_msg void OnMouseHWheel(UINT nFlags, short zDelta, CPoint pt);
+	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
+};
+
+

+ 1281 - 1271
SimpleBrowser.cpp

@@ -1,1271 +1,1281 @@
-/////////////////////////////////////////////////////////////////////////////
-// SimpleBrowser.cpp: Web browser control
-/////////////////////////////////////////////////////////////////////////////
-
-#include "stdafx.h"
-#include "comdef.h"
-#include "mshtml.h"
-#include "mshtmcid.h"
-#include "mshtmhst.h"
-#include "exdispid.h"
-
-#include "SimpleBrowser.h"
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-#define Unused(parameter) parameter					// avoid compile warnings
-													// about unused parameters
-
-/////////////////////////////////////////////////////////////////////////////
-// Construction and creation
-/////////////////////////////////////////////////////////////////////////////
-
-SimpleBrowser::SimpleBrowser()
-	:	_Browser(NULL),
-		_BrowserDispatch(NULL),
-		_Ready(false),
-		_Content(_T(""))
-{
-}
-
-SimpleBrowser::~SimpleBrowser()
-{
-    // release browser interfaces
-
-	if (_Browser != NULL) {
-		_Browser->Release();
-		_Browser = NULL;
-	}
-
-	if (_BrowserDispatch != NULL) {
-		_BrowserDispatch->Release();
-		_BrowserDispatch = NULL;
-	}
-}
-
-// Standard create
-
-BOOL SimpleBrowser::Create(DWORD dwStyle, 
-                           const RECT& rect, 
-                           CWnd* pParentWnd, 
-						   UINT nID)
-{
-    BOOL results = TRUE;
-
-	_Ready      = false;
-	
-    _Browser	= NULL;
-
-    // create this window
-
-    CWnd *window = this;
-	results = window->Create(AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW),
-	                         NULL,
-							 dwStyle,
-							 rect,
-							 pParentWnd,
-							 nID);
-    if (!results) return FALSE;
-
-    // create browser control window as child of this window; 
-	// this window sinks events from control
-
-	CRect browser_window_rect(0,0,(rect.right - rect.left),(rect.bottom - rect.top));
-
-    results = _BrowserWindow.CreateControl(CLSID_WebBrowser,
-                                           NULL,
-                                           (WS_VISIBLE | WS_TABSTOP),
-                                           browser_window_rect,
-                                           this,
-                                           AFX_IDW_PANE_FIRST);
-    if (!results) {
-        DestroyWindow();
-        return FALSE;
-    }
-
-    // get control interfaces
-
-    LPUNKNOWN unknown = _BrowserWindow.GetControlUnknown();
-
-    HRESULT hr = unknown->QueryInterface(IID_IWebBrowser2,(void **)&_Browser);
-    if (SUCCEEDED(hr)) {
-        hr = unknown->QueryInterface(IID_IDispatch,(void **)&_BrowserDispatch);
-    }
-
-    if (!SUCCEEDED(hr)) {
-        _BrowserWindow.DestroyWindow();
-        DestroyWindow();
-        return FALSE;        
-    }
-
-	// navigate to initial blank page
-
-	if (_Browser != NULL) {
-		Navigate(_T("about:blank"));
-	}
-
-    return TRUE;
-}
-
-// Create in place of dialog control
-
-BOOL SimpleBrowser::CreateFromControl(CWnd *pParentWnd,UINT nID,DWORD dwStyle)
-{
-	BOOL result = FALSE;
-
-	ASSERT(pParentWnd != NULL);
-
-	CWnd *control = pParentWnd->GetDlgItem(nID);
-
-	if (control != NULL) {
-
-		// get control location
-
-		CRect		rect;
-
-		control->GetWindowRect(&rect);
-		pParentWnd->ScreenToClient(&rect);
-
-		// destroy control, since the browser will take its place
-
-		control->DestroyWindow();
-
-		// create browser
-
-		result = Create(dwStyle,
-		                rect,
-						pParentWnd,
-						nID);
-
-	}
-
-	return result;
-}
-
-// Destruction
-
-void SimpleBrowser::PostNcDestroy()
-{
-    // release browser interfaces
-
-	if (_Browser != NULL) {
-		_Browser->Release();
-		_Browser = NULL;
-	}
-
-	if (_BrowserDispatch != NULL) {
-		_BrowserDispatch->Release();
-		_BrowserDispatch = NULL;
-	}
-	
-	_Ready		= false;
-	_Content	= _T("");
-	
-	CWnd::PostNcDestroy();
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// Controls
-/////////////////////////////////////////////////////////////////////////////
-
-// Navigate to URL
-
-void SimpleBrowser::Navigate(LPCTSTR URL)
-{
-	_Ready   = false;
-	_Content = _T("");
-
-	if (_Browser != NULL) {
-
-		CString		url(URL);
-
-		_variant_t	flags(0L,VT_I4);
-		_variant_t	target_frame_name("");
-		_variant_t	post_data("");
-		_variant_t	headers("");
-
-		_Browser->Navigate(url.AllocSysString(),
-						   &flags,
-						   &target_frame_name,
-						   &post_data,
-						   &headers);
-
-	}
-}
-
-// Navigate to HTML document in resource
-
-void SimpleBrowser::NavigateResource(int resource_ID)
-{
-	if (_Browser != NULL) {
-
-		CString resource_string;
-
-		// load HTML document from resource
-
-		HRSRC resource_handle = FindResource(AfxGetResourceHandle(),
-											 MAKEINTRESOURCE(resource_ID),
-											 RT_HTML);
-
-		if (resource_handle != NULL) {
-
-			HGLOBAL resource = LoadResource(AfxGetResourceHandle(),
-											resource_handle);
-
-			if (resource != NULL) {
-
-				LPVOID resource_memory = LockResource(resource);
-
-				if (resource_memory != NULL) {
-
-					DWORD resource_size = SizeofResource(AfxGetResourceHandle(),
-														 resource_handle);
-
-					// identify the resource document as MBCS (e.g. ANSI)
-					// or UNICODE
-
-					bool     UNICODE_document = false;
-
-					wchar_t *UNICODE_memory   = (wchar_t *)resource_memory;
-					int      UNICODE_size     = resource_size / sizeof(wchar_t);
-
-					if (UNICODE_size >= 1) {
-
-						// check for UNICODE byte order mark
-
-						if (*UNICODE_memory == L'\xFEFF') {
-							UNICODE_document = true;
-							UNICODE_memory  += 1;
-							UNICODE_size    -= 1;
-						}
-
-						// otherwise, check for UNICODE leading tag
-
-						else if (UNICODE_size >= 5) {
-
-							if ((UNICODE_memory[0]           == L'<') &&
-							    (towupper(UNICODE_memory[1]) == L'H') &&
-							    (towupper(UNICODE_memory[2]) == L'T') &&
-							    (towupper(UNICODE_memory[3]) == L'M') &&
-							    (towupper(UNICODE_memory[4]) == L'L')) {
-								UNICODE_document = true;
-							}
-
-						}
-
-						// Note: This logic assumes that the UNICODE resource document is 
-						//       in little-endian byte order, which would be typical for 
-						//       any HTML document used as a resource in a Windows application.
-
-					}
-
-					// convert resource document if required
-
-#if !defined(UNICODE)
-
-					if (UNICODE_document) {
-
-						char *MBCS_buffer = resource_string.GetBufferSetLength(resource_size + 1);
-
-						int MBCS_length = ::WideCharToMultiByte(CP_ACP,
-						                                        0,
-											                    UNICODE_memory,
-											                    UNICODE_size,
-											                    MBCS_buffer,
-											                    resource_size + 1,
-											                    NULL,
-											                    NULL);
-
-						resource_string.ReleaseBuffer(MBCS_length);
-
-					}
-
-					else {
-
-						resource_string = CString((char *)resource_memory,resource_size);
-
-					}
-
-#else
-
-					if (UNICODE_document) {
-
-						resource_string = CString(UNICODE_memory,UNICODE_size);
-
-					}
-
-					else {
-
-						wchar_t *UNICODE_buffer = resource_string.GetBufferSetLength(resource_size + 1);
-
-						int UNICODE_length = ::MultiByteToWideChar(CP_ACP,
-						                                           0,
-											                       (const char *)resource_memory,
-											                       resource_size,
-											                       UNICODE_buffer,
-											                       (resource_size + 1));
-
-						resource_string.ReleaseBuffer(UNICODE_length);
-
-					}
-
-#endif
-
-
-				}
-
-			}
-
-		}
-
-		Clear();
-		Write(resource_string);
-
-	}
-}
-
-// Append string to current document
-
-void SimpleBrowser::Write(LPCTSTR string)
-{
-	if (_Browser != NULL) {
-
-		_Content.Append(string);
-		
-		_ContentWrite();
-
-	}
-}
-
-void SimpleBrowser::Clear()
-{
-	if (_Browser != NULL) {
-
-		_Content = _T("");
-
-		// get document interface
-
-		IHTMLDocument2	*document	= GetDocument();
-		HRESULT			hr			= S_OK;
-		
-		if (document != NULL) {
-
-			// close and re-open document to empty contents
-
-			document->close();
-			
-			VARIANT		open_name;
-			VARIANT		open_features;
-			VARIANT		open_replace;
-			IDispatch	*open_window	= NULL;
-
-			::VariantInit(&open_name);
-
-			open_name.vt      = VT_BSTR;
-			open_name.bstrVal = ::SysAllocString(L"_self");
-
-			::VariantInit(&open_features);
-			::VariantInit(&open_replace);
-			
-			hr = document->open(::SysAllocString(L"text/html"),
-			                    open_name,
-			                    open_features,
-			                    open_replace,
-			                    &open_window);
-
-			if (hr == S_OK) {
-				Refresh();
-			}
-
-			if (open_window != NULL) {
-				open_window->Release();
-			}
-
-			::VariantClear(&open_name);
-			
-			document->Release();
-			document = NULL;
-		
-		}
-		
-		else {
-
-			Navigate(_T("about:blank"));
-
-		}
-		
-	}
-}
-
-// Navigation operations
-
-void SimpleBrowser::GoBack()
-{
-	if (_Browser != NULL) {
-		_Browser->GoBack();
-	}
-}
-
-void SimpleBrowser::GoForward()
-{
-	if (_Browser != NULL) {
-		_Browser->GoForward();
-	}
-}
-
-void SimpleBrowser::GoHome()
-{
-	if (_Browser != NULL) {
-		_Browser->GoHome();
-	}
-}
-
-void SimpleBrowser::Refresh()
-{
-	if (_Browser != NULL) {
-		_Browser->Refresh();
-	}
-}
-
-void SimpleBrowser::Stop()
-{
-	if (_Browser != NULL) {
-		_Browser->Stop();
-	}
-}
-
-// Print contents
-
-void SimpleBrowser::Print(LPCTSTR header,LPCTSTR footer)
-{
-	if (_Browser != NULL) {
-
-		// construct two element SAFEARRAY;
-		// first element is header string, second element is footer string
-
-		HRESULT hr;
-
-		VARIANT		header_variant;
-		VariantInit(&header_variant);
-		V_VT(&header_variant)   = VT_BSTR;
-		V_BSTR(&header_variant) = CString(header).AllocSysString();
-
-		VARIANT		footer_variant;
-		VariantInit(&footer_variant);
-		V_VT(&footer_variant)   = VT_BSTR;
-		V_BSTR(&footer_variant) = CString(footer).AllocSysString();
-
-		long index;
-
-		SAFEARRAYBOUND	parameter_array_bound[1];
-		SAFEARRAY		*parameter_array = NULL;
-
-		parameter_array_bound[0].cElements = 2;
-		parameter_array_bound[0].lLbound   = 0;
-
-		parameter_array = SafeArrayCreate(VT_VARIANT,1,parameter_array_bound);
-
-		index = 0;
-		hr    = SafeArrayPutElement(parameter_array,&index,&header_variant);
-
-		index = 1;
-		hr    = SafeArrayPutElement(parameter_array,&index,&footer_variant);
-
-		VARIANT	parameter;
-		VariantInit(&parameter);
-		V_VT(&parameter)    = VT_ARRAY | VT_BYREF;
-		V_ARRAY(&parameter) = parameter_array;
-
-		// start printing browser contents
-
-		hr = _Browser->ExecWB(OLECMDID_PRINT,OLECMDEXECOPT_DODEFAULT,&parameter,NULL);
-
-		// release SAFEARRAY
-
-		if (!SUCCEEDED(hr)) {
-			VariantClear(&header_variant);
-			VariantClear(&footer_variant);
-			if (parameter_array != NULL) {
-				SafeArrayDestroy(parameter_array);
-			}
-		}
-
-	}
-}
-
-void SimpleBrowser::PrintPreview()
-{
-	if (_Browser != NULL) {
-		_Browser->ExecWB(OLECMDID_PRINTPREVIEW,OLECMDEXECOPT_DODEFAULT,NULL,NULL);
-	}
-}
-
-// Miscellaneous
-
-bool SimpleBrowser::GetBusy()
-{
-    bool busy = false;
-
-	if (_Browser != NULL) {
-
-		VARIANT_BOOL    variant_bool;
-
-		HRESULT hr = _Browser->get_Busy(&variant_bool);
-		if (SUCCEEDED(hr)) {
-			busy = (variant_bool == VARIANT_TRUE);    
-		}
-
-	}
-
-    return busy;
-}
-
-CString SimpleBrowser::GetLocationName()
-{
-    CString location_name = _T("");
-
-	if (_Browser != NULL) {
-
-		BSTR location_name_BSTR = NULL;
-
-		HRESULT hr = _Browser->get_LocationName(&location_name_BSTR);
-		if (SUCCEEDED(hr)) {
-			location_name = location_name_BSTR;
-		}
-
-		::SysFreeString(location_name_BSTR);
-
-	}
-
-    return location_name;
-}
-
-CString SimpleBrowser::GetLocationURL()
-{
-    CString location_URL = _T("");
-
-	if (_Browser != NULL) {
-
-		BSTR location_URL_BSTR = NULL;
-
-		HRESULT hr = _Browser->get_LocationURL(&location_URL_BSTR);
-		if (SUCCEEDED(hr)) {
-			location_URL = location_URL_BSTR;
-		}
-
-		::SysFreeString(location_URL_BSTR);
-
-	}
-
-    return location_URL;
-}
-
-READYSTATE SimpleBrowser::GetReadyState()
-{
-    READYSTATE readystate = READYSTATE_UNINITIALIZED;
-
-    if (_Browser != NULL) {
-		_Browser->get_ReadyState(&readystate);
-	}
-
-    return readystate;
-}
-
-bool SimpleBrowser::GetSilent()
-{
-    bool silent = false;
-
-	if (_Browser != NULL) {
-
-		VARIANT_BOOL silent_variant;
-
-		HRESULT hr = _Browser->get_Silent(&silent_variant);
-		if (SUCCEEDED(hr)) {
-			silent = (silent_variant == VARIANT_TRUE);
-		}
-
-	}
-
-    return silent;
-}
-
-void SimpleBrowser::PutSilent(bool silent)
-{
-	if (_Browser != NULL) {
-
-		VARIANT_BOOL silent_variant;
-
-		if (silent) silent_variant = VARIANT_TRUE;
-		else        silent_variant = VARIANT_FALSE;
-
-		_Browser->put_Silent(silent_variant);
-	}
-}
-
-IHTMLDocument2 *SimpleBrowser::GetDocument()
-{
-	IHTMLDocument2 *document = NULL;
-	
-	if (_Browser != NULL) {
-	
-		// get browser document's dispatch interface
-
-		IDispatch *document_dispatch = NULL;
-
-		HRESULT hr = _Browser->get_Document(&document_dispatch);
-
-		if (SUCCEEDED(hr) && (document_dispatch != NULL)) {
-
-			// get the actual document interface
-
-			hr = document_dispatch->QueryInterface(IID_IHTMLDocument2,
-			                                       (void **)&document);
-
-			// release dispatch interface
-					
-			document_dispatch->Release();
-		
-		}
-		
-	}
-	
-	return document;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// Message handlers
-/////////////////////////////////////////////////////////////////////////////
-
-BEGIN_MESSAGE_MAP(SimpleBrowser,CWnd)
-    //{{AFX_MSG_MAP(SimpleBrowser)
-	ON_WM_SIZE()
-	//}}AFX_MSG_MAP
-END_MESSAGE_MAP()
-
-BOOL SimpleBrowser::PreTranslateMessage(MSG *pMsg)
-{
-	BOOL result = FALSE;
-
-	// translate keys correctly, especially Tab, Del, (Enter?)
-	
-	if (_Browser != NULL) {
-	
-		IOleInPlaceActiveObject* OleInPlaceActiveObject = NULL;
-
-		HRESULT hr = _Browser->QueryInterface(IID_IOleInPlaceActiveObject, (void**)&OleInPlaceActiveObject);
-
-		if (SUCCEEDED(hr) && (OleInPlaceActiveObject != NULL)) {
-
-			hr = OleInPlaceActiveObject->TranslateAccelerator(pMsg);
-			result = (hr == S_OK ? TRUE : FALSE);
-
-			OleInPlaceActiveObject->Release();
-
-		}
-
-	}
-
-	else {
-		result = CWnd::PreTranslateMessage(pMsg);
-	}
-
-	return result;
-}
-
-// Resize control window as this window is resized
-
-void SimpleBrowser::OnSize(UINT nType, int cx, int cy)
-{
-	CWnd::OnSize(nType, cx, cy);
-
-	if (_Browser != NULL) {
-        CRect rect(0,0,cx,cy);	
-		_BrowserWindow.MoveWindow(&rect);
-	}
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// Event handlers
-/////////////////////////////////////////////////////////////////////////////
-
-#ifndef DISPID_PRINTTEMPLATEINSTANTIATION
-	#define DISPID_PRINTTEMPLATEINSTANTIATION 225
-#endif
-#ifndef DISPID_PRINTTEMPLATETEARDOWN
-	#define DISPID_PRINTTEMPLATETEARDOWN 226
-#endif
-
-BEGIN_EVENTSINK_MAP(SimpleBrowser,CWnd)
-    ON_EVENT(SimpleBrowser,AFX_IDW_PANE_FIRST,
-	         DISPID_BEFORENAVIGATE2,
-             _OnBeforeNavigate2, 
-			 VTS_DISPATCH VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PBOOL)
-    ON_EVENT(SimpleBrowser,AFX_IDW_PANE_FIRST,
-	         DISPID_DOCUMENTCOMPLETE,
-             _OnDocumentComplete, 
-			 VTS_DISPATCH VTS_PVARIANT)
-    ON_EVENT(SimpleBrowser,AFX_IDW_PANE_FIRST,
-	         DISPID_DOWNLOADBEGIN,
-             _OnDownloadBegin, 
-			 VTS_NONE)
-    ON_EVENT(SimpleBrowser,AFX_IDW_PANE_FIRST,
-	         DISPID_PROGRESSCHANGE,
-             _OnProgressChange, 
-			 VTS_I4 VTS_I4)
-    ON_EVENT(SimpleBrowser,AFX_IDW_PANE_FIRST,
-	         DISPID_DOWNLOADCOMPLETE,
-             _OnDownloadComplete, 
-			 VTS_NONE)
-    ON_EVENT(SimpleBrowser,AFX_IDW_PANE_FIRST,
-	         DISPID_NAVIGATECOMPLETE2,
-             _OnNavigateComplete2, 
-			 VTS_DISPATCH VTS_PVARIANT)
-    ON_EVENT(SimpleBrowser,AFX_IDW_PANE_FIRST,
-	         DISPID_STATUSTEXTCHANGE,
-             _OnStatusTextChange, 
-			 VTS_BSTR)
-    ON_EVENT(SimpleBrowser,AFX_IDW_PANE_FIRST,
-	         DISPID_TITLECHANGE,
-             _OnTitleChange, 
-			 VTS_BSTR)
-	ON_EVENT(SimpleBrowser,AFX_IDW_PANE_FIRST,
-	         DISPID_PRINTTEMPLATEINSTANTIATION,
-	         _OnPrintTemplateInstantiation, 
-	         VTS_DISPATCH)
-	ON_EVENT(SimpleBrowser,AFX_IDW_PANE_FIRST,
-	         DISPID_PRINTTEMPLATETEARDOWN,
-	         _OnPrintTemplateTeardown, 
-	         VTS_DISPATCH)
-END_EVENTSINK_MAP()
-
-SimpleBrowser::Notification::Notification(HWND hwnd,UINT ID,NotificationType type)
-{
-	hdr.hwndFrom	= hwnd;
-	hdr.idFrom		= ID;
-	hdr.code		= type;
-	URL				= _T("");
-	frame			= _T("");
-	post_data		= NULL;
-	post_data_size	= 0;
-	headers			= _T("");
-	progress		= 0;
-	progress_max	= 0;
-	text			= _T("");
-}
-
-SimpleBrowser::Notification::~Notification()
-{
-}
-
-// Called before navigation begins; application may cancel if required
-
-void SimpleBrowser::_OnBeforeNavigate2(LPDISPATCH lpDisp,
-                                       VARIANT FAR *URL,
-                                       VARIANT FAR *Flags,
-                                       VARIANT FAR *TargetFrameName,
-                                       VARIANT FAR *PostData,
-                                       VARIANT FAR *Headers,
-                                       VARIANT_BOOL *Cancel)
-{
-	Unused(Flags);	// Note: flags value is reserved
-
-    if (lpDisp == _BrowserDispatch) {
-
-		CString				URL_string;
-		CString				frame;
-		unsigned char		*post_data		= NULL;
-		int					post_data_size	= 0;
-		CString				headers;
-
-        if ((URL       != NULL) && 
-		    (V_VT(URL) == VT_BSTR)) {
-            URL_string = V_BSTR(URL);
-        }
-
-		if ((TargetFrameName       != NULL) &&
-            (V_VT(TargetFrameName) == VT_BSTR)) {
-			frame = V_BSTR(TargetFrameName);
-        }
-
-		if ((PostData       != NULL)                    &&
-		    (V_VT(PostData) == (VT_VARIANT | VT_BYREF))) {
-
-			VARIANT *PostData_variant = V_VARIANTREF(PostData);
-
-			if ((PostData_variant       != NULL) &&
-			    (V_VT(PostData_variant) != VT_EMPTY)) {
-
-				SAFEARRAY *PostData_safearray = V_ARRAY(PostData_variant);
-
-				if (PostData_safearray != NULL) {
-
-					char *post_data_array = NULL;
-
-					SafeArrayAccessData(PostData_safearray,(void HUGEP **)&post_data_array);
-
-					long		lower_bound = 1;
-					long		upper_bound = 1;
-
-					SafeArrayGetLBound(PostData_safearray,1,&lower_bound);
-					SafeArrayGetUBound(PostData_safearray,1,&upper_bound);
-
-					post_data_size = (int)(upper_bound - lower_bound + 1);
-
-					post_data = new unsigned char[post_data_size];
-
-					memcpy(post_data,post_data_array,post_data_size);
-
-					SafeArrayUnaccessData(PostData_safearray);
-
-				}
-
-			}
-
-		}
-
-		if ((Headers       != NULL) &&
-            (V_VT(Headers) == VT_BSTR)) {
-			headers = V_BSTR(Headers);
-        }
-
-		bool cancel = OnBeforeNavigate2(URL_string,
-		                                frame,
-										post_data,post_data_size,
-										headers);
-
-		if (Cancel != NULL) {
-			if (cancel) *Cancel = VARIANT_TRUE;
-			else        *Cancel = VARIANT_FALSE;
-		}
-
-		delete []post_data;
-
-    }    
-}
-
-bool SimpleBrowser::OnBeforeNavigate2(CString URL,
-                                      CString frame,
-									  void    *post_data,int post_data_size,
-									  CString headers)
-{
-	bool cancel = false;
-	
-	CWnd *parent = GetParent();
-	
-	if (parent != NULL) {
-
-		Notification	notification(m_hWnd,GetDlgCtrlID(),BeforeNavigate2);
-		
-		notification.URL			= URL;
-		notification.frame			= frame;
-		notification.post_data		= post_data;
-		notification.post_data_size	= post_data_size;
-		notification.headers		= headers;
-
-		LRESULT result = parent->SendMessage(WM_NOTIFY,
-		                                     notification.hdr.idFrom,
-											 (LPARAM)&notification);
-		
-		if (result) {
-			cancel = true;
-		}
-
-	}
-	
-    return cancel;
-}
-
-bool SimpleBrowser::ParsePostData(CString post_data,
-	                              CStringArray &names,
-	                              CStringArray &values)
-{
-	bool result = true;
-	
-	int size = 1;
-	
-	names.SetSize(size);
-	values.SetSize(size);
-	
-	int offset = 0;
-	
-	bool parsing_name = true;
-	
-	CString hex(_T("0123456789ABCDEF"));
-	
-	while ((offset < post_data.GetLength()) && result) {
-
-		if      (post_data[offset] == _T('%')) {
-
-			if ((offset + 2) < post_data.GetLength()) {
-
-				int digit1 = hex.Find(_totupper(post_data[offset + 1]));
-				int digit2 = hex.Find(_totupper(post_data[offset + 2]));
-
-				if ((digit1 >= 0) && (digit2 >= 0)) {
-
-					_TCHAR character = (_TCHAR)((digit1 << 4) + digit2);
-
-					if (parsing_name) names[size - 1].AppendChar(character);
-					else              values[size - 1].AppendChar(character);
-
-				}
-				
-				else {
-					result = false;
-				}
-
-				offset += 2;
-
-			}
-
-			else {
-				result = false;
-			}
-
-		}
-
-		else if (post_data[offset] == _T('+')) {
-			if (parsing_name) names[size - 1].AppendChar(_T(' '));
-			else              values[size - 1].AppendChar(_T(' '));
-		}
-
-		else if (post_data[offset] == _T('=')) {
-
-			if (parsing_name) {
-				parsing_name = false;
-			}
-			else {
-				values[size - 1].AppendChar(post_data[offset]);
-			}
-
-		}
-
-		else if (post_data[offset] == _T('&')) {
-
-			if (!parsing_name) {
-				parsing_name = true;
-				size += 1;
-				names.SetSize(size);
-				values.SetSize(size);
-			}
-
-			else {
-				values[size - 1].AppendChar(post_data[offset]);
-			}
-
-		}
-		
-		else {
-
-			if (parsing_name) names[size - 1].AppendChar(post_data[offset]);
-			else              values[size - 1].AppendChar(post_data[offset]);
-
-		}
-
-		offset++;
-		
-	}
-
-	if ((names[size - 1]  == _T("")) &&
-	    (values[size - 1] == _T(""))) {
-		names.SetSize(size - 1);
-		values.SetSize(size - 1);
-	}
-
-	return result;
-}
-
-// Document loaded and initialized
-
-void SimpleBrowser::_OnDocumentComplete(LPDISPATCH lpDisp,VARIANT *URL)
-{
-    if (lpDisp == _BrowserDispatch) {
-
-		CString URL_string;
-		
-		if ((URL       != NULL) &&
-            (V_VT(URL) == VT_BSTR)) {
-			URL_string = CString(V_BSTR(URL));
-        }
-
-        OnDocumentComplete(URL_string);
-
-    }    
-}
-
-void SimpleBrowser::OnDocumentComplete(CString URL)
-{
-	CWnd *parent = GetParent();
-	
-	if (parent != NULL) {
-
-		Notification	notification(m_hWnd,GetDlgCtrlID(),DocumentComplete);
-		
-		notification.URL = URL;
-
-		LRESULT result = parent->SendMessage(WM_NOTIFY,
-		                                     notification.hdr.idFrom,
-											 (LPARAM)&notification);
-		
-	}
-}
-
-// Navigation/download progress
-
-void SimpleBrowser::_OnDownloadBegin()
-{
-    OnDownloadBegin();
-}
-
-void SimpleBrowser::OnDownloadBegin()
-{
-	CWnd *parent = GetParent();
-	
-	if (parent != NULL) {
-
-		Notification	notification(m_hWnd,GetDlgCtrlID(),DownloadBegin);
-		
-		LRESULT result = parent->SendMessage(WM_NOTIFY,
-		                                     notification.hdr.idFrom,
-											 (LPARAM)&notification);
-		
-	}
-}
-
-void SimpleBrowser::_OnProgressChange(long progress,long progress_max)
-{
-    OnProgressChange((int)progress,(int)progress_max);
-}
-
-void SimpleBrowser::OnProgressChange(int progress,int progress_max)
-{
-	CWnd *parent = GetParent();
-	
-	if (parent != NULL) {
-
-		Notification	notification(m_hWnd,GetDlgCtrlID(),ProgressChange);
-		
-		notification.progress     = progress;
-		notification.progress_max = progress_max;
-
-		LRESULT result = parent->SendMessage(WM_NOTIFY,
-		                                     notification.hdr.idFrom,
-											 (LPARAM)&notification);
-		
-	}
-}
-
-void SimpleBrowser::_OnDownloadComplete()
-{
-    OnDownloadComplete();
-}
-
-void SimpleBrowser::OnDownloadComplete()
-{
-	CWnd *parent = GetParent();
-	
-	if (parent != NULL) {
-
-		Notification	notification(m_hWnd,GetDlgCtrlID(),DownloadComplete);
-		
-		LRESULT result = parent->SendMessage(WM_NOTIFY,
-		                                     notification.hdr.idFrom,
-											 (LPARAM)&notification);
-		
-	}
-}
-
-// Navigation to a link has completed
-
-void SimpleBrowser::_OnNavigateComplete2(LPDISPATCH lpDisp,VARIANT *URL)
-{
-    if (lpDisp == _BrowserDispatch) {
-
-		// signal document ready
-
-		_Ready = true;
-
-		// write current content
-		
-		_ContentWrite();
-		
-		// inform user navigation complete
-		
-		CString URL_string;
-		
-		if ((URL       != NULL) &&
-            (V_VT(URL) == VT_BSTR)) {
-			URL_string = V_BSTR(URL);
-        }
-
-		OnNavigateComplete2(URL_string);
-
-    }    
-}
-
-void SimpleBrowser::OnNavigateComplete2(CString URL)
-{
-	CWnd *parent = GetParent();
-	
-	if (parent != NULL) {
-
-		Notification	notification(m_hWnd,GetDlgCtrlID(),NavigateComplete2);
-		
-		notification.URL = URL;
-
-		LRESULT result = parent->SendMessage(WM_NOTIFY,
-		                                     notification.hdr.idFrom,
-											 (LPARAM)&notification);
-		
-	}
-}
-
-// Status text has changed
-
-void SimpleBrowser::_OnStatusTextChange(BSTR bstrText)
-{
-    CString text;
-	
-	if (bstrText != NULL) {
-		text = (LPCTSTR)bstrText;
-	}
-
-    OnStatusTextChange(text);
-}
-
-void SimpleBrowser::OnStatusTextChange(CString text)
-{
-	CWnd *parent = GetParent();
-	
-	if (parent != NULL) {
-
-		Notification	notification(m_hWnd,GetDlgCtrlID(),StatusTextChange);
-		
-		notification.text = text;
-
-		LRESULT result = parent->SendMessage(WM_NOTIFY,
-		                                     notification.hdr.idFrom,
-											 (LPARAM)&notification);
-		
-	}
-}
-
-// Title text has changed
-
-void SimpleBrowser::_OnTitleChange(BSTR bstrText)
-{
-    CString text;
-	
-	if (bstrText != NULL) {
-		text = (LPCTSTR)bstrText;
-	}
-
-    OnTitleChange(text);
-}
-
-void SimpleBrowser::OnTitleChange(CString text)
-{
-	CWnd *parent = GetParent();
-	
-	if (parent != NULL) {
-
-		Notification	notification(m_hWnd,GetDlgCtrlID(),TitleChange);
-		
-		notification.text = text;
-
-		LRESULT result = parent->SendMessage(WM_NOTIFY,
-		                                     notification.hdr.idFrom,
-											 (LPARAM)&notification);
-		
-	}
-}
-
-// Print template instantiation and teardown
- 
-void SimpleBrowser::_OnPrintTemplateInstantiation(LPDISPATCH lpDisp)
-{
-	OnPrintTemplateInstantiation();
-};
-
-void SimpleBrowser::OnPrintTemplateInstantiation()
-{
-	CWnd *parent = GetParent();
-	
-	if (parent != NULL) {
-
-		Notification	notification(m_hWnd,GetDlgCtrlID(),PrintTemplateInstantiation);
-		
-		LRESULT result = parent->SendMessage(WM_NOTIFY,
-		                                     notification.hdr.idFrom,
-											 (LPARAM)&notification);
-		
-	}
-}
-
-void SimpleBrowser::_OnPrintTemplateTeardown(LPDISPATCH lpDisp)
-{
-	OnPrintTemplateTeardown();
-};
-
-void SimpleBrowser::OnPrintTemplateTeardown()
-{
-	CWnd *parent = GetParent();
-	
-	if (parent != NULL) {
-
-		Notification	notification(m_hWnd,GetDlgCtrlID(),PrintTemplateTeardown);
-		
-		LRESULT result = parent->SendMessage(WM_NOTIFY,
-		                                     notification.hdr.idFrom,
-											 (LPARAM)&notification);
-		
-	}
-}
-
-// Write deferred content
-
-void SimpleBrowser::_ContentWrite()
-{
-	if (_Ready && (!_Content.IsEmpty())) {
-	
-		// get document interface
-
-		IHTMLDocument2 *document = GetDocument();
-		
-		if (document != NULL) {
-
-			// construct text to be written to browser as SAFEARRAY
-
-			SAFEARRAY *safe_array = SafeArrayCreateVector(VT_VARIANT,0,1);
-			
-			VARIANT	*variant;
-			
-			SafeArrayAccessData(safe_array,(LPVOID *)&variant);
-			
-			variant->vt      = VT_BSTR;
-			variant->bstrVal = _Content.AllocSysString();
-			
-			SafeArrayUnaccessData(safe_array);
-
-			// write SAFEARRAY to browser document
-
-			document->write(safe_array);
-			
-			// cleanup
-			
-			document->Release();
-			document = NULL;
-
-			::SysFreeString(variant->bstrVal);
-			variant->bstrVal = NULL;
-			
-			SafeArrayDestroy(safe_array);
-		
-		}
-
-	}
-}
+/////////////////////////////////////////////////////////////////////////////
+// SimpleBrowser.cpp: Web browser control
+/////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "comdef.h"
+#include "mshtml.h"
+#include "mshtmcid.h"
+#include "mshtmhst.h"
+#include "exdispid.h"
+
+#include "SimpleBrowser.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#define Unused(parameter) parameter					// avoid compile warnings
+													// about unused parameters
+
+/////////////////////////////////////////////////////////////////////////////
+// Construction and creation
+/////////////////////////////////////////////////////////////////////////////
+
+SimpleBrowser::SimpleBrowser()
+	:	_Browser(NULL),
+		_BrowserDispatch(NULL),
+		_Ready(false),
+		_Content(_T(""))
+{
+}
+
+SimpleBrowser::~SimpleBrowser()
+{
+    // release browser interfaces
+
+	if (_Browser != NULL) {
+		_Browser->Release();
+		_Browser = NULL;
+	}
+
+	if (_BrowserDispatch != NULL) {
+		_BrowserDispatch->Release();
+		_BrowserDispatch = NULL;
+	}
+}
+
+// Standard create
+
+BOOL SimpleBrowser::Create(DWORD dwStyle, 
+                           const RECT& rect, 
+                           CWnd* pParentWnd, 
+						   UINT nID)
+{
+    BOOL results = TRUE;
+
+	_Ready      = false;
+	
+    _Browser	= NULL;
+
+    // create this window
+
+    CWnd *window = this;
+	results = window->Create(AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW),
+	                         NULL,
+							 dwStyle,
+							 rect,
+							 pParentWnd,
+							 nID);
+    if (!results) return FALSE;
+
+    // create browser control window as child of this window; 
+	// this window sinks events from control
+
+	CRect browser_window_rect(0,0,(rect.right - rect.left),(rect.bottom - rect.top));
+
+    results = _BrowserWindow.CreateControl(CLSID_WebBrowser,
+                                           NULL,
+                                           (WS_VISIBLE | WS_TABSTOP),
+                                           browser_window_rect,
+                                           this,
+                                           AFX_IDW_PANE_FIRST);
+    if (!results) {
+        DestroyWindow();
+        return FALSE;
+    }
+
+    // get control interfaces
+
+    LPUNKNOWN unknown = _BrowserWindow.GetControlUnknown();
+
+    HRESULT hr = unknown->QueryInterface(IID_IWebBrowser2,(void **)&_Browser);
+    if (SUCCEEDED(hr)) {
+        hr = unknown->QueryInterface(IID_IDispatch,(void **)&_BrowserDispatch);
+    }
+
+    if (!SUCCEEDED(hr)) {
+        _BrowserWindow.DestroyWindow();
+        DestroyWindow();
+        return FALSE;        
+    }
+
+	// navigate to initial blank page
+
+	if (_Browser != NULL) {
+		Navigate(_T("about:blank"));
+	}
+
+    return TRUE;
+}
+
+// Create in place of dialog control
+
+BOOL SimpleBrowser::CreateFromControl(CWnd *pParentWnd,UINT nID,DWORD dwStyle)
+{
+	BOOL result = FALSE;
+
+	ASSERT(pParentWnd != NULL);
+
+	CWnd *control = pParentWnd->GetDlgItem(nID);
+
+	if (control != NULL) {
+
+		// get control location
+
+		CRect		rect;
+
+		control->GetWindowRect(&rect);
+		pParentWnd->ScreenToClient(&rect);
+
+		// destroy control, since the browser will take its place
+
+		control->DestroyWindow();
+
+		// create browser
+
+		result = Create(dwStyle,
+		                rect,
+						pParentWnd,
+						nID);
+
+	}
+
+	return result;
+}
+
+// Destruction
+
+void SimpleBrowser::PostNcDestroy()
+{
+    // release browser interfaces
+
+	if (_Browser != NULL) {
+		_Browser->Release();
+		_Browser = NULL;
+	}
+
+	if (_BrowserDispatch != NULL) {
+		_BrowserDispatch->Release();
+		_BrowserDispatch = NULL;
+	}
+	
+	_Ready		= false;
+	_Content	= _T("");
+	
+	CWnd::PostNcDestroy();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Controls
+/////////////////////////////////////////////////////////////////////////////
+
+// Navigate to URL
+
+void SimpleBrowser::Copy()
+{
+	if (_Browser != NULL) {		
+
+		_Browser->ExecWB(OLECMDID_COPY, OLECMDEXECOPT_DONTPROMPTUSER, NULL, NULL);
+
+	}
+
+}
+
+void SimpleBrowser::Navigate(LPCTSTR URL)
+{
+	_Ready   = false;
+	_Content = _T("");
+
+	if (_Browser != NULL) {
+
+		CString		url(URL);
+
+		_variant_t	flags(0L,VT_I4);
+		_variant_t	target_frame_name("");
+		_variant_t	post_data("");
+		_variant_t	headers("");
+
+		_Browser->Navigate(url.AllocSysString(),
+						   &flags,
+						   &target_frame_name,
+						   &post_data,
+						   &headers);
+
+	}
+}
+
+// Navigate to HTML document in resource
+
+void SimpleBrowser::NavigateResource(int resource_ID)
+{
+	if (_Browser != NULL) {
+
+		CString resource_string;
+
+		// load HTML document from resource
+
+		HRSRC resource_handle = FindResource(AfxGetResourceHandle(),
+											 MAKEINTRESOURCE(resource_ID),
+											 RT_HTML);
+
+		if (resource_handle != NULL) {
+
+			HGLOBAL resource = LoadResource(AfxGetResourceHandle(),
+											resource_handle);
+
+			if (resource != NULL) {
+
+				LPVOID resource_memory = LockResource(resource);
+
+				if (resource_memory != NULL) {
+
+					DWORD resource_size = SizeofResource(AfxGetResourceHandle(),
+														 resource_handle);
+
+					// identify the resource document as MBCS (e.g. ANSI)
+					// or UNICODE
+
+					bool     UNICODE_document = false;
+
+					wchar_t *UNICODE_memory   = (wchar_t *)resource_memory;
+					int      UNICODE_size     = resource_size / sizeof(wchar_t);
+
+					if (UNICODE_size >= 1) {
+
+						// check for UNICODE byte order mark
+
+						if (*UNICODE_memory == L'\xFEFF') {
+							UNICODE_document = true;
+							UNICODE_memory  += 1;
+							UNICODE_size    -= 1;
+						}
+
+						// otherwise, check for UNICODE leading tag
+
+						else if (UNICODE_size >= 5) {
+
+							if ((UNICODE_memory[0]           == L'<') &&
+							    (towupper(UNICODE_memory[1]) == L'H') &&
+							    (towupper(UNICODE_memory[2]) == L'T') &&
+							    (towupper(UNICODE_memory[3]) == L'M') &&
+							    (towupper(UNICODE_memory[4]) == L'L')) {
+								UNICODE_document = true;
+							}
+
+						}
+
+						// Note: This logic assumes that the UNICODE resource document is 
+						//       in little-endian byte order, which would be typical for 
+						//       any HTML document used as a resource in a Windows application.
+
+					}
+
+					// convert resource document if required
+
+#if !defined(UNICODE)
+
+					if (UNICODE_document) {
+
+						char *MBCS_buffer = resource_string.GetBufferSetLength(resource_size + 1);
+
+						int MBCS_length = ::WideCharToMultiByte(CP_ACP,
+						                                        0,
+											                    UNICODE_memory,
+											                    UNICODE_size,
+											                    MBCS_buffer,
+											                    resource_size + 1,
+											                    NULL,
+											                    NULL);
+
+						resource_string.ReleaseBuffer(MBCS_length);
+
+					}
+
+					else {
+
+						resource_string = CString((char *)resource_memory,resource_size);
+
+					}
+
+#else
+
+					if (UNICODE_document) {
+
+						resource_string = CString(UNICODE_memory,UNICODE_size);
+
+					}
+
+					else {
+
+						wchar_t *UNICODE_buffer = resource_string.GetBufferSetLength(resource_size + 1);
+
+						int UNICODE_length = ::MultiByteToWideChar(CP_ACP,
+						                                           0,
+											                       (const char *)resource_memory,
+											                       resource_size,
+											                       UNICODE_buffer,
+											                       (resource_size + 1));
+
+						resource_string.ReleaseBuffer(UNICODE_length);
+
+					}
+
+#endif
+
+
+				}
+
+			}
+
+		}
+
+		Clear();
+		Write(resource_string);
+
+	}
+}
+
+// Append string to current document
+
+void SimpleBrowser::Write(LPCTSTR string)
+{
+	if (_Browser != NULL) {
+
+		_Content.Append(string);
+		
+		_ContentWrite();
+
+	}
+}
+
+void SimpleBrowser::Clear()
+{
+	if (_Browser != NULL) {
+
+		_Content = _T("");
+
+		// get document interface
+
+		IHTMLDocument2	*document	= GetDocument();
+		HRESULT			hr			= S_OK;
+		
+		if (document != NULL) {
+
+			// close and re-open document to empty contents
+
+			document->close();
+			
+			VARIANT		open_name;
+			VARIANT		open_features;
+			VARIANT		open_replace;
+			IDispatch	*open_window	= NULL;
+
+			::VariantInit(&open_name);
+
+			open_name.vt      = VT_BSTR;
+			open_name.bstrVal = ::SysAllocString(L"_self");
+
+			::VariantInit(&open_features);
+			::VariantInit(&open_replace);
+			
+			hr = document->open(::SysAllocString(L"text/html"),
+			                    open_name,
+			                    open_features,
+			                    open_replace,
+			                    &open_window);
+
+			if (hr == S_OK) {
+				Refresh();
+			}
+
+			if (open_window != NULL) {
+				open_window->Release();
+			}
+
+			::VariantClear(&open_name);
+			
+			document->Release();
+			document = NULL;
+		
+		}
+		
+		else {
+
+			Navigate(_T("about:blank"));
+
+		}
+		
+	}
+}
+
+// Navigation operations
+
+void SimpleBrowser::GoBack()
+{
+	if (_Browser != NULL) {
+		_Browser->GoBack();
+	}
+}
+
+void SimpleBrowser::GoForward()
+{
+	if (_Browser != NULL) {
+		_Browser->GoForward();
+	}
+}
+
+void SimpleBrowser::GoHome()
+{
+	if (_Browser != NULL) {
+		_Browser->GoHome();
+	}
+}
+
+void SimpleBrowser::Refresh()
+{
+	if (_Browser != NULL) {
+		_Browser->Refresh();
+	}
+}
+
+void SimpleBrowser::Stop()
+{
+	if (_Browser != NULL) {
+		_Browser->Stop();
+	}
+}
+
+// Print contents
+
+void SimpleBrowser::Print(LPCTSTR header,LPCTSTR footer)
+{
+	if (_Browser != NULL) {
+
+		// construct two element SAFEARRAY;
+		// first element is header string, second element is footer string
+
+		HRESULT hr;
+
+		VARIANT		header_variant;
+		VariantInit(&header_variant);
+		V_VT(&header_variant)   = VT_BSTR;
+		V_BSTR(&header_variant) = CString(header).AllocSysString();
+
+		VARIANT		footer_variant;
+		VariantInit(&footer_variant);
+		V_VT(&footer_variant)   = VT_BSTR;
+		V_BSTR(&footer_variant) = CString(footer).AllocSysString();
+
+		long index;
+
+		SAFEARRAYBOUND	parameter_array_bound[1];
+		SAFEARRAY		*parameter_array = NULL;
+
+		parameter_array_bound[0].cElements = 2;
+		parameter_array_bound[0].lLbound   = 0;
+
+		parameter_array = SafeArrayCreate(VT_VARIANT,1,parameter_array_bound);
+
+		index = 0;
+		hr    = SafeArrayPutElement(parameter_array,&index,&header_variant);
+
+		index = 1;
+		hr    = SafeArrayPutElement(parameter_array,&index,&footer_variant);
+
+		VARIANT	parameter;
+		VariantInit(&parameter);
+		V_VT(&parameter)    = VT_ARRAY | VT_BYREF;
+		V_ARRAY(&parameter) = parameter_array;
+
+		// start printing browser contents
+
+		hr = _Browser->ExecWB(OLECMDID_PRINT,OLECMDEXECOPT_DODEFAULT,&parameter,NULL);
+
+		// release SAFEARRAY
+
+		if (!SUCCEEDED(hr)) {
+			VariantClear(&header_variant);
+			VariantClear(&footer_variant);
+			if (parameter_array != NULL) {
+				SafeArrayDestroy(parameter_array);
+			}
+		}
+
+	}
+}
+
+void SimpleBrowser::PrintPreview()
+{
+	if (_Browser != NULL) {
+		_Browser->ExecWB(OLECMDID_PRINTPREVIEW,OLECMDEXECOPT_DODEFAULT,NULL,NULL);
+	}
+}
+
+// Miscellaneous
+
+bool SimpleBrowser::GetBusy()
+{
+    bool busy = false;
+
+	if (_Browser != NULL) {
+
+		VARIANT_BOOL    variant_bool;
+
+		HRESULT hr = _Browser->get_Busy(&variant_bool);
+		if (SUCCEEDED(hr)) {
+			busy = (variant_bool == VARIANT_TRUE);    
+		}
+
+	}
+
+    return busy;
+}
+
+CString SimpleBrowser::GetLocationName()
+{
+    CString location_name = _T("");
+
+	if (_Browser != NULL) {
+
+		BSTR location_name_BSTR = NULL;
+
+		HRESULT hr = _Browser->get_LocationName(&location_name_BSTR);
+		if (SUCCEEDED(hr)) {
+			location_name = location_name_BSTR;
+		}
+
+		::SysFreeString(location_name_BSTR);
+
+	}
+
+    return location_name;
+}
+
+CString SimpleBrowser::GetLocationURL()
+{
+    CString location_URL = _T("");
+
+	if (_Browser != NULL) {
+
+		BSTR location_URL_BSTR = NULL;
+
+		HRESULT hr = _Browser->get_LocationURL(&location_URL_BSTR);
+		if (SUCCEEDED(hr)) {
+			location_URL = location_URL_BSTR;
+		}
+
+		::SysFreeString(location_URL_BSTR);
+
+	}
+
+    return location_URL;
+}
+
+READYSTATE SimpleBrowser::GetReadyState()
+{
+    READYSTATE readystate = READYSTATE_UNINITIALIZED;
+
+    if (_Browser != NULL) {
+		_Browser->get_ReadyState(&readystate);
+	}
+
+    return readystate;
+}
+
+bool SimpleBrowser::GetSilent()
+{
+    bool silent = false;
+
+	if (_Browser != NULL) {
+
+		VARIANT_BOOL silent_variant;
+
+		HRESULT hr = _Browser->get_Silent(&silent_variant);
+		if (SUCCEEDED(hr)) {
+			silent = (silent_variant == VARIANT_TRUE);
+		}
+
+	}
+
+    return silent;
+}
+
+void SimpleBrowser::PutSilent(bool silent)
+{
+	if (_Browser != NULL) {
+
+		VARIANT_BOOL silent_variant;
+
+		if (silent) silent_variant = VARIANT_TRUE;
+		else        silent_variant = VARIANT_FALSE;
+
+		_Browser->put_Silent(silent_variant);
+	}
+}
+
+IHTMLDocument2 *SimpleBrowser::GetDocument()
+{
+	IHTMLDocument2 *document = NULL;
+	
+	if (_Browser != NULL) {
+	
+		// get browser document's dispatch interface
+
+		IDispatch *document_dispatch = NULL;
+
+		HRESULT hr = _Browser->get_Document(&document_dispatch);
+
+		if (SUCCEEDED(hr) && (document_dispatch != NULL)) {
+
+			// get the actual document interface
+
+			hr = document_dispatch->QueryInterface(IID_IHTMLDocument2,
+			                                       (void **)&document);
+
+			// release dispatch interface
+					
+			document_dispatch->Release();
+		
+		}
+		
+	}
+	
+	return document;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Message handlers
+/////////////////////////////////////////////////////////////////////////////
+
+BEGIN_MESSAGE_MAP(SimpleBrowser,CWnd)
+    //{{AFX_MSG_MAP(SimpleBrowser)
+	ON_WM_SIZE()
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+BOOL SimpleBrowser::PreTranslateMessage(MSG *pMsg)
+{
+	BOOL result = FALSE;
+
+	// translate keys correctly, especially Tab, Del, (Enter?)
+	
+	if (_Browser != NULL) {
+	
+		IOleInPlaceActiveObject* OleInPlaceActiveObject = NULL;
+
+		HRESULT hr = _Browser->QueryInterface(IID_IOleInPlaceActiveObject, (void**)&OleInPlaceActiveObject);
+
+		if (SUCCEEDED(hr) && (OleInPlaceActiveObject != NULL)) {
+
+			hr = OleInPlaceActiveObject->TranslateAccelerator(pMsg);
+			result = (hr == S_OK ? TRUE : FALSE);
+
+			OleInPlaceActiveObject->Release();
+
+		}
+
+	}
+
+	else {
+		result = CWnd::PreTranslateMessage(pMsg);
+	}
+
+	return result;
+}
+
+// Resize control window as this window is resized
+
+void SimpleBrowser::OnSize(UINT nType, int cx, int cy)
+{
+	CWnd::OnSize(nType, cx, cy);
+
+	if (_Browser != NULL) {
+        CRect rect(0,0,cx,cy);	
+		_BrowserWindow.MoveWindow(&rect);
+	}
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Event handlers
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef DISPID_PRINTTEMPLATEINSTANTIATION
+	#define DISPID_PRINTTEMPLATEINSTANTIATION 225
+#endif
+#ifndef DISPID_PRINTTEMPLATETEARDOWN
+	#define DISPID_PRINTTEMPLATETEARDOWN 226
+#endif
+
+BEGIN_EVENTSINK_MAP(SimpleBrowser,CWnd)
+    ON_EVENT(SimpleBrowser,AFX_IDW_PANE_FIRST,
+	         DISPID_BEFORENAVIGATE2,
+             _OnBeforeNavigate2, 
+			 VTS_DISPATCH VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PBOOL)
+    ON_EVENT(SimpleBrowser,AFX_IDW_PANE_FIRST,
+	         DISPID_DOCUMENTCOMPLETE,
+             _OnDocumentComplete, 
+			 VTS_DISPATCH VTS_PVARIANT)
+    ON_EVENT(SimpleBrowser,AFX_IDW_PANE_FIRST,
+	         DISPID_DOWNLOADBEGIN,
+             _OnDownloadBegin, 
+			 VTS_NONE)
+    ON_EVENT(SimpleBrowser,AFX_IDW_PANE_FIRST,
+	         DISPID_PROGRESSCHANGE,
+             _OnProgressChange, 
+			 VTS_I4 VTS_I4)
+    ON_EVENT(SimpleBrowser,AFX_IDW_PANE_FIRST,
+	         DISPID_DOWNLOADCOMPLETE,
+             _OnDownloadComplete, 
+			 VTS_NONE)
+    ON_EVENT(SimpleBrowser,AFX_IDW_PANE_FIRST,
+	         DISPID_NAVIGATECOMPLETE2,
+             _OnNavigateComplete2, 
+			 VTS_DISPATCH VTS_PVARIANT)
+    ON_EVENT(SimpleBrowser,AFX_IDW_PANE_FIRST,
+	         DISPID_STATUSTEXTCHANGE,
+             _OnStatusTextChange, 
+			 VTS_BSTR)
+    ON_EVENT(SimpleBrowser,AFX_IDW_PANE_FIRST,
+	         DISPID_TITLECHANGE,
+             _OnTitleChange, 
+			 VTS_BSTR)
+	ON_EVENT(SimpleBrowser,AFX_IDW_PANE_FIRST,
+	         DISPID_PRINTTEMPLATEINSTANTIATION,
+	         _OnPrintTemplateInstantiation, 
+	         VTS_DISPATCH)
+	ON_EVENT(SimpleBrowser,AFX_IDW_PANE_FIRST,
+	         DISPID_PRINTTEMPLATETEARDOWN,
+	         _OnPrintTemplateTeardown, 
+	         VTS_DISPATCH)
+END_EVENTSINK_MAP()
+
+SimpleBrowser::Notification::Notification(HWND hwnd,UINT ID,NotificationType type)
+{
+	hdr.hwndFrom	= hwnd;
+	hdr.idFrom		= ID;
+	hdr.code		= type;
+	URL				= _T("");
+	frame			= _T("");
+	post_data		= NULL;
+	post_data_size	= 0;
+	headers			= _T("");
+	progress		= 0;
+	progress_max	= 0;
+	text			= _T("");
+}
+
+SimpleBrowser::Notification::~Notification()
+{
+}
+
+// Called before navigation begins; application may cancel if required
+
+void SimpleBrowser::_OnBeforeNavigate2(LPDISPATCH lpDisp,
+                                       VARIANT FAR *URL,
+                                       VARIANT FAR *Flags,
+                                       VARIANT FAR *TargetFrameName,
+                                       VARIANT FAR *PostData,
+                                       VARIANT FAR *Headers,
+                                       VARIANT_BOOL *Cancel)
+{
+	Unused(Flags);	// Note: flags value is reserved
+
+    if (lpDisp == _BrowserDispatch) {
+
+		CString				URL_string;
+		CString				frame;
+		unsigned char		*post_data		= NULL;
+		int					post_data_size	= 0;
+		CString				headers;
+
+        if ((URL       != NULL) && 
+		    (V_VT(URL) == VT_BSTR)) {
+            URL_string = V_BSTR(URL);
+        }
+
+		if ((TargetFrameName       != NULL) &&
+            (V_VT(TargetFrameName) == VT_BSTR)) {
+			frame = V_BSTR(TargetFrameName);
+        }
+
+		if ((PostData       != NULL)                    &&
+		    (V_VT(PostData) == (VT_VARIANT | VT_BYREF))) {
+
+			VARIANT *PostData_variant = V_VARIANTREF(PostData);
+
+			if ((PostData_variant       != NULL) &&
+			    (V_VT(PostData_variant) != VT_EMPTY)) {
+
+				SAFEARRAY *PostData_safearray = V_ARRAY(PostData_variant);
+
+				if (PostData_safearray != NULL) {
+
+					char *post_data_array = NULL;
+
+					SafeArrayAccessData(PostData_safearray,(void HUGEP **)&post_data_array);
+
+					long		lower_bound = 1;
+					long		upper_bound = 1;
+
+					SafeArrayGetLBound(PostData_safearray,1,&lower_bound);
+					SafeArrayGetUBound(PostData_safearray,1,&upper_bound);
+
+					post_data_size = (int)(upper_bound - lower_bound + 1);
+
+					post_data = new unsigned char[post_data_size];
+
+					memcpy(post_data,post_data_array,post_data_size);
+
+					SafeArrayUnaccessData(PostData_safearray);
+
+				}
+
+			}
+
+		}
+
+		if ((Headers       != NULL) &&
+            (V_VT(Headers) == VT_BSTR)) {
+			headers = V_BSTR(Headers);
+        }
+
+		bool cancel = OnBeforeNavigate2(URL_string,
+		                                frame,
+										post_data,post_data_size,
+										headers);
+
+		if (Cancel != NULL) {
+			if (cancel) *Cancel = VARIANT_TRUE;
+			else        *Cancel = VARIANT_FALSE;
+		}
+
+		delete []post_data;
+
+    }    
+}
+
+bool SimpleBrowser::OnBeforeNavigate2(CString URL,
+                                      CString frame,
+									  void    *post_data,int post_data_size,
+									  CString headers)
+{
+	bool cancel = false;
+	
+	CWnd *parent = GetParent();
+	
+	if (parent != NULL) {
+
+		Notification	notification(m_hWnd,GetDlgCtrlID(),BeforeNavigate2);
+		
+		notification.URL			= URL;
+		notification.frame			= frame;
+		notification.post_data		= post_data;
+		notification.post_data_size	= post_data_size;
+		notification.headers		= headers;
+
+		LRESULT result = parent->SendMessage(WM_NOTIFY,
+		                                     notification.hdr.idFrom,
+											 (LPARAM)&notification);
+		
+		if (result) {
+			cancel = true;
+		}
+
+	}
+	
+    return cancel;
+}
+
+bool SimpleBrowser::ParsePostData(CString post_data,
+	                              CStringArray &names,
+	                              CStringArray &values)
+{
+	bool result = true;
+	
+	int size = 1;
+	
+	names.SetSize(size);
+	values.SetSize(size);
+	
+	int offset = 0;
+	
+	bool parsing_name = true;
+	
+	CString hex(_T("0123456789ABCDEF"));
+	
+	while ((offset < post_data.GetLength()) && result) {
+
+		if      (post_data[offset] == _T('%')) {
+
+			if ((offset + 2) < post_data.GetLength()) {
+
+				int digit1 = hex.Find(_totupper(post_data[offset + 1]));
+				int digit2 = hex.Find(_totupper(post_data[offset + 2]));
+
+				if ((digit1 >= 0) && (digit2 >= 0)) {
+
+					_TCHAR character = (_TCHAR)((digit1 << 4) + digit2);
+
+					if (parsing_name) names[size - 1].AppendChar(character);
+					else              values[size - 1].AppendChar(character);
+
+				}
+				
+				else {
+					result = false;
+				}
+
+				offset += 2;
+
+			}
+
+			else {
+				result = false;
+			}
+
+		}
+
+		else if (post_data[offset] == _T('+')) {
+			if (parsing_name) names[size - 1].AppendChar(_T(' '));
+			else              values[size - 1].AppendChar(_T(' '));
+		}
+
+		else if (post_data[offset] == _T('=')) {
+
+			if (parsing_name) {
+				parsing_name = false;
+			}
+			else {
+				values[size - 1].AppendChar(post_data[offset]);
+			}
+
+		}
+
+		else if (post_data[offset] == _T('&')) {
+
+			if (!parsing_name) {
+				parsing_name = true;
+				size += 1;
+				names.SetSize(size);
+				values.SetSize(size);
+			}
+
+			else {
+				values[size - 1].AppendChar(post_data[offset]);
+			}
+
+		}
+		
+		else {
+
+			if (parsing_name) names[size - 1].AppendChar(post_data[offset]);
+			else              values[size - 1].AppendChar(post_data[offset]);
+
+		}
+
+		offset++;
+		
+	}
+
+	if ((names[size - 1]  == _T("")) &&
+	    (values[size - 1] == _T(""))) {
+		names.SetSize(size - 1);
+		values.SetSize(size - 1);
+	}
+
+	return result;
+}
+
+// Document loaded and initialized
+
+void SimpleBrowser::_OnDocumentComplete(LPDISPATCH lpDisp,VARIANT *URL)
+{
+    if (lpDisp == _BrowserDispatch) {
+
+		CString URL_string;
+		
+		if ((URL       != NULL) &&
+            (V_VT(URL) == VT_BSTR)) {
+			URL_string = CString(V_BSTR(URL));
+        }
+
+        OnDocumentComplete(URL_string);
+
+    }    
+}
+
+void SimpleBrowser::OnDocumentComplete(CString URL)
+{
+	CWnd *parent = GetParent();
+	
+	if (parent != NULL) {
+
+		Notification	notification(m_hWnd,GetDlgCtrlID(),DocumentComplete);
+		
+		notification.URL = URL;
+
+		LRESULT result = parent->SendMessage(WM_NOTIFY,
+		                                     notification.hdr.idFrom,
+											 (LPARAM)&notification);
+		
+	}
+}
+
+// Navigation/download progress
+
+void SimpleBrowser::_OnDownloadBegin()
+{
+    OnDownloadBegin();
+}
+
+void SimpleBrowser::OnDownloadBegin()
+{
+	CWnd *parent = GetParent();
+	
+	if (parent != NULL) {
+
+		Notification	notification(m_hWnd,GetDlgCtrlID(),DownloadBegin);
+		
+		LRESULT result = parent->SendMessage(WM_NOTIFY,
+		                                     notification.hdr.idFrom,
+											 (LPARAM)&notification);
+		
+	}
+}
+
+void SimpleBrowser::_OnProgressChange(long progress,long progress_max)
+{
+    OnProgressChange((int)progress,(int)progress_max);
+}
+
+void SimpleBrowser::OnProgressChange(int progress,int progress_max)
+{
+	CWnd *parent = GetParent();
+	
+	if (parent != NULL) {
+
+		Notification	notification(m_hWnd,GetDlgCtrlID(),ProgressChange);
+		
+		notification.progress     = progress;
+		notification.progress_max = progress_max;
+
+		LRESULT result = parent->SendMessage(WM_NOTIFY,
+		                                     notification.hdr.idFrom,
+											 (LPARAM)&notification);
+		
+	}
+}
+
+void SimpleBrowser::_OnDownloadComplete()
+{
+    OnDownloadComplete();
+}
+
+void SimpleBrowser::OnDownloadComplete()
+{
+	CWnd *parent = GetParent();
+	
+	if (parent != NULL) {
+
+		Notification	notification(m_hWnd,GetDlgCtrlID(),DownloadComplete);
+		
+		LRESULT result = parent->SendMessage(WM_NOTIFY,
+		                                     notification.hdr.idFrom,
+											 (LPARAM)&notification);
+		
+	}
+}
+
+// Navigation to a link has completed
+
+void SimpleBrowser::_OnNavigateComplete2(LPDISPATCH lpDisp,VARIANT *URL)
+{
+    if (lpDisp == _BrowserDispatch) {
+
+		// signal document ready
+
+		_Ready = true;
+
+		// write current content
+		
+		_ContentWrite();
+		
+		// inform user navigation complete
+		
+		CString URL_string;
+		
+		if ((URL       != NULL) &&
+            (V_VT(URL) == VT_BSTR)) {
+			URL_string = V_BSTR(URL);
+        }
+
+		OnNavigateComplete2(URL_string);
+
+    }    
+}
+
+void SimpleBrowser::OnNavigateComplete2(CString URL)
+{
+	CWnd *parent = GetParent();
+	
+	if (parent != NULL) {
+
+		Notification	notification(m_hWnd,GetDlgCtrlID(),NavigateComplete2);
+		
+		notification.URL = URL;
+
+		LRESULT result = parent->SendMessage(WM_NOTIFY,
+		                                     notification.hdr.idFrom,
+											 (LPARAM)&notification);
+		
+	}
+}
+
+// Status text has changed
+
+void SimpleBrowser::_OnStatusTextChange(BSTR bstrText)
+{
+    CString text;
+	
+	if (bstrText != NULL) {
+		text = (LPCTSTR)bstrText;
+	}
+
+    OnStatusTextChange(text);
+}
+
+void SimpleBrowser::OnStatusTextChange(CString text)
+{
+	CWnd *parent = GetParent();
+	
+	if (parent != NULL) {
+
+		Notification	notification(m_hWnd,GetDlgCtrlID(),StatusTextChange);
+		
+		notification.text = text;
+
+		LRESULT result = parent->SendMessage(WM_NOTIFY,
+		                                     notification.hdr.idFrom,
+											 (LPARAM)&notification);
+		
+	}
+}
+
+// Title text has changed
+
+void SimpleBrowser::_OnTitleChange(BSTR bstrText)
+{
+    CString text;
+	
+	if (bstrText != NULL) {
+		text = (LPCTSTR)bstrText;
+	}
+
+    OnTitleChange(text);
+}
+
+void SimpleBrowser::OnTitleChange(CString text)
+{
+	CWnd *parent = GetParent();
+	
+	if (parent != NULL) {
+
+		Notification	notification(m_hWnd,GetDlgCtrlID(),TitleChange);
+		
+		notification.text = text;
+
+		LRESULT result = parent->SendMessage(WM_NOTIFY,
+		                                     notification.hdr.idFrom,
+											 (LPARAM)&notification);
+		
+	}
+}
+
+// Print template instantiation and teardown
+ 
+void SimpleBrowser::_OnPrintTemplateInstantiation(LPDISPATCH lpDisp)
+{
+	OnPrintTemplateInstantiation();
+};
+
+void SimpleBrowser::OnPrintTemplateInstantiation()
+{
+	CWnd *parent = GetParent();
+	
+	if (parent != NULL) {
+
+		Notification	notification(m_hWnd,GetDlgCtrlID(),PrintTemplateInstantiation);
+		
+		LRESULT result = parent->SendMessage(WM_NOTIFY,
+		                                     notification.hdr.idFrom,
+											 (LPARAM)&notification);
+		
+	}
+}
+
+void SimpleBrowser::_OnPrintTemplateTeardown(LPDISPATCH lpDisp)
+{
+	OnPrintTemplateTeardown();
+};
+
+void SimpleBrowser::OnPrintTemplateTeardown()
+{
+	CWnd *parent = GetParent();
+	
+	if (parent != NULL) {
+
+		Notification	notification(m_hWnd,GetDlgCtrlID(),PrintTemplateTeardown);
+		
+		LRESULT result = parent->SendMessage(WM_NOTIFY,
+		                                     notification.hdr.idFrom,
+											 (LPARAM)&notification);
+		
+	}
+}
+
+// Write deferred content
+
+void SimpleBrowser::_ContentWrite()
+{
+	if (_Ready && (!_Content.IsEmpty())) {
+	
+		// get document interface
+
+		IHTMLDocument2 *document = GetDocument();
+		
+		if (document != NULL) {
+
+			// construct text to be written to browser as SAFEARRAY
+
+			SAFEARRAY *safe_array = SafeArrayCreateVector(VT_VARIANT,0,1);
+			
+			VARIANT	*variant;
+			
+			SafeArrayAccessData(safe_array,(LPVOID *)&variant);
+			
+			variant->vt      = VT_BSTR;
+			variant->bstrVal = _Content.AllocSysString();
+			
+			SafeArrayUnaccessData(safe_array);
+
+			// write SAFEARRAY to browser document
+
+			document->write(safe_array);
+			
+			// cleanup
+			
+			document->Release();
+			document = NULL;
+
+			::SysFreeString(variant->bstrVal);
+			variant->bstrVal = NULL;
+			
+			SafeArrayDestroy(safe_array);
+		
+		}
+
+	}
+}

+ 259 - 257
SimpleBrowser.h

@@ -1,257 +1,259 @@
-/////////////////////////////////////////////////////////////////////////////
-// SimpleBrowser: Web browser control
-/////////////////////////////////////////////////////////////////////////////
-
-#if !defined(SimpleBrowser_defined)
-#define SimpleBrowser_defined
-
-#include "mshtml.h"
-
-class SimpleBrowser : public CWnd {
-
-public:
-
-	// construction and creation
-
-    SimpleBrowser();
-    virtual ~SimpleBrowser();
-
-	BOOL Create(DWORD dwStyle, 
-	            const RECT& rect, 
-				CWnd* pParentWnd, 
-				UINT nID);
-		
-		// create browser directly
-
-	BOOL CreateFromControl(CWnd *pParentWnd,UINT nID,DWORD dwStyle = WS_CHILD | WS_VISIBLE);
-
-		// create browser in place of dialog control; the dialog control 
-		// identified by nID will be destroyed, and the browser will take
-		// its place
-
-    // controls
-
-	void Navigate(LPCTSTR URL);
-	
-		// navigate to URL
-
-	void Write(LPCTSTR string);				
-	
-		// append string to current document; note that the WebBrowser control tolerates
-		// poorly formed documents, like:
-
-		// <html><body>....
-		// --- no trailing body or html tags
-
-		// <html><body>...</body></html><html><body>...</body></html>...
-		// --- multiple documents
-
-	void Clear();							
-	
-		// clear current document
-
-	void NavigateResource(int resource_ID);
-	
-		// navigate to HTML document resource
-
-	void GoBack();							// navigate backward one item
-											// in the history list
-
-    void GoForward();						// navigate forward one item
-											// in the history list
-
-    void GoHome();							// navigate to current 
-											// home or start page
-
-    void Refresh();							// refresh contents
-
-    void Stop();							// stop current activity
-
-    void Print(LPCTSTR header = _T("&w&b&b&p"),
-			   LPCTSTR footer = _T("&d &t"));
-			   
-		// start printing contents; uses same 'metacharacters' for header and
-		// footer as Internet Explorer; see IE Page Setup dialog
-
-	void PrintPreview();					// print preview
-
-    bool GetBusy();                         // returns true if browser
-                                            // busy downloading or other
-                                            // activity
-
-    CString GetLocationName();              // get name of location currently
-                                            // being browsed (title, if HTML
-                                            // page; UNC path if file)
-
-    CString GetLocationURL();               // get URL of location currently
-                                            // being browsed
-
-    READYSTATE GetReadyState();             // get browser ready state
-
-    bool GetSilent();                       // get/set silent property
-    void PutSilent(bool silent = false);	// (if true, dialog and message
-                                            //  boxes may not be shown)
-
-	IHTMLDocument2 *GetDocument();			// get document interface; returns NULL 
-											// if interface is not available 
-											// (which is the case if you've navigated to
-											//  something that's NOT an HTML document,
-											//  like an Excel spreadsheet, which the
-											//  WebBrowser control is perfectly willing
-											//  to host)
-
-    // events (overridables)
-
-    virtual bool OnBeforeNavigate2(CString	URL,
-	                               CString	frame,
-								   void		*post_data,int post_data_size,
-								   CString	headers);
-
-        // called before navigation begins; URL is destination, frame
-        // is frame name ("" if none), post_data is HTTP POST data (NULL if none),
-		// and headers are HTTP headers sent to server;
-		// return true to cancel navigation, false to continue
-
-    virtual void OnDocumentComplete(CString URL);
-
-        // navigation to document complete; URL is location
-
-    virtual void OnDownloadBegin();
-	
-		// navigation operation begins
-
-    virtual void OnProgressChange(int progress,int progress_max);
-
-         // navigation progress update
-
-    virtual void OnDownloadComplete();
-	
-	     // navigation operation completed
-
-    virtual void OnNavigateComplete2(CString URL);
-
-        // navigation to hyperlink complete; URL is location
-		// (URL = string if NavigateString or NavigateResource are used)
-
-    virtual void OnStatusTextChange(CString text);
-
-        // status text has changed
-
-    virtual void OnTitleChange(CString text);
-
-		// title has changed
-
-	virtual void OnPrintTemplateInstantiation();
-	
-		// print template has been instantiated (printing has begun)
-		
-	virtual void OnPrintTemplateTeardown();
-	
-		// print template is being destroyed (printing has completed)		
-
-	// notifications
-	
-	enum NotificationType {					// Note: SimpleBrowser does NOT support the
-											//       common notifications (NM_CLICK, etc.)
-
-		BeforeNavigate2,					// set *LRESULT=TRUE to cancel navigation
-		DocumentComplete,				
-		DownloadBegin,
-		ProgressChange,
-		DownloadComplete,
-		NavigateComplete2,
-		StatusTextChange,
-		TitleChange,
-		PrintTemplateInstantiation,
-		PrintTemplateTeardown
-
-	};
-	
-	class Notification {					// all notifications pass this structure
-
-	public:
-
-		Notification(HWND hwnd,UINT ID,NotificationType type);
-		~Notification();
-
-		NMHDR			hdr;				// hdr.hwndFrom = SimpleBrowser's HWND
-											// hdr.idFrom   = SimpleBrowser's control ID
-											// hdr.code     = <NavigationType>
-
-		CString			URL;				// BeforeNavigate2
-											// DocumentComplete
-											// NavigateComplete2
-
-		CString			frame;				// BeforeNavigate2
-		void			*post_data;			// BeforeNavigate2
-		int				post_data_size;
-		CString			headers;			// BeforeNavigate2
-
-		int				progress;			// ProgressChange
-		int				progress_max;		// ProgressChange
-
-		CString			text;				// StatusTextChange
-											// TitleChange
-
-	};
-
-	bool ParsePostData(CString post_data,		// parse URL-encoded POST data
-	                   CStringArray &names,		// string into list of names
-	                   CStringArray &values);	// and values; returns true if
-												// successful
-
-    //{{AFX_VIRTUAL(SimpleBrowser)
-	public:
-	virtual void PostNcDestroy();
-	//}}AFX_VIRTUAL
-
-protected:
-
-    //{{AFX_MSG(SimpleBrowser)
-	afx_msg void OnSize(UINT nType, int cx, int cy);
-	afx_msg BOOL PreTranslateMessage(MSG *pMsg);
-	//}}AFX_MSG
-
-    void _OnBeforeNavigate2(LPDISPATCH lpDisp,
-                            VARIANT FAR *URL,
-                            VARIANT FAR *Flags,
-                            VARIANT FAR *TargetFrameName,
-                            VARIANT FAR *PostData,
-                            VARIANT FAR *Headers,
-                            VARIANT_BOOL *Cancel);
-    void _OnDownloadBegin();
-    void _OnProgressChange(long progress,long progress_max);
-    void _OnDownloadComplete();
-    void _OnDocumentComplete(LPDISPATCH lpDisp,VARIANT FAR* URL);
-    void _OnNavigateComplete2(LPDISPATCH lpDisp,VARIANT FAR* URL);
-    void _OnStatusTextChange(BSTR bstrText);
-    void _OnTitleChange(BSTR bstrText);
-	void _OnPrintTemplateInstantiation(LPDISPATCH pDisp);
-	void _OnPrintTemplateTeardown(LPDISPATCH pDisp);
-
-    DECLARE_MESSAGE_MAP()
-    DECLARE_EVENTSINK_MAP()
-
-private:
-
-    CWnd                    _BrowserWindow;     // browser window
-
-protected:
-
-	IWebBrowser2			*_Browser;          // browser control
-
-	bool					_Ready;				// document ready
-												// (initial navigation completed)
-
-private:    
-    
-    IDispatch               *_BrowserDispatch;  // browser control 
-												// dispatch interface
-
-	CString					_Content;			// current content set via Write()/Clear()
-	
-	void _ContentWrite();
-
-};
-
-#endif
+/////////////////////////////////////////////////////////////////////////////
+// SimpleBrowser: Web browser control
+/////////////////////////////////////////////////////////////////////////////
+
+#if !defined(SimpleBrowser_defined)
+#define SimpleBrowser_defined
+
+#include "mshtml.h"
+
+class SimpleBrowser : public CWnd {
+
+public:
+
+	// construction and creation
+
+    SimpleBrowser();
+    virtual ~SimpleBrowser();
+
+	BOOL Create(DWORD dwStyle, 
+	            const RECT& rect, 
+				CWnd* pParentWnd, 
+				UINT nID);
+		
+		// create browser directly
+
+	BOOL CreateFromControl(CWnd *pParentWnd,UINT nID,DWORD dwStyle = WS_CHILD | WS_VISIBLE);
+
+		// create browser in place of dialog control; the dialog control 
+		// identified by nID will be destroyed, and the browser will take
+		// its place
+
+    // controls
+
+	void Navigate(LPCTSTR URL);
+	
+		// navigate to URL
+
+	void Write(LPCTSTR string);				
+	
+		// append string to current document; note that the WebBrowser control tolerates
+		// poorly formed documents, like:
+
+		// <html><body>....
+		// --- no trailing body or html tags
+
+		// <html><body>...</body></html><html><body>...</body></html>...
+		// --- multiple documents
+
+	void Clear();							
+	
+		// clear current document
+
+	void NavigateResource(int resource_ID);
+	
+		// navigate to HTML document resource
+
+	void GoBack();							// navigate backward one item
+											// in the history list
+
+    void GoForward();						// navigate forward one item
+											// in the history list
+
+    void GoHome();							// navigate to current 
+											// home or start page
+
+    void Refresh();							// refresh contents
+
+    void Stop();							// stop current activity
+
+    void Print(LPCTSTR header = _T("&w&b&b&p"),
+			   LPCTSTR footer = _T("&d &t"));
+			   
+		// start printing contents; uses same 'metacharacters' for header and
+		// footer as Internet Explorer; see IE Page Setup dialog
+
+	void PrintPreview();					// print preview
+
+    bool GetBusy();                         // returns true if browser
+                                            // busy downloading or other
+                                            // activity
+
+    CString GetLocationName();              // get name of location currently
+                                            // being browsed (title, if HTML
+                                            // page; UNC path if file)
+
+    CString GetLocationURL();               // get URL of location currently
+                                            // being browsed
+
+    READYSTATE GetReadyState();             // get browser ready state
+
+    bool GetSilent();                       // get/set silent property
+    void PutSilent(bool silent = false);	// (if true, dialog and message
+                                            //  boxes may not be shown)
+
+	IHTMLDocument2 *GetDocument();			// get document interface; returns NULL 
+											// if interface is not available 
+											// (which is the case if you've navigated to
+											//  something that's NOT an HTML document,
+											//  like an Excel spreadsheet, which the
+											//  WebBrowser control is perfectly willing
+											//  to host)
+
+    // events (overridables)
+
+    virtual bool OnBeforeNavigate2(CString	URL,
+	                               CString	frame,
+								   void		*post_data,int post_data_size,
+								   CString	headers);
+
+        // called before navigation begins; URL is destination, frame
+        // is frame name ("" if none), post_data is HTTP POST data (NULL if none),
+		// and headers are HTTP headers sent to server;
+		// return true to cancel navigation, false to continue
+
+    virtual void OnDocumentComplete(CString URL);
+
+        // navigation to document complete; URL is location
+
+    virtual void OnDownloadBegin();
+	
+		// navigation operation begins
+
+    virtual void OnProgressChange(int progress,int progress_max);
+
+         // navigation progress update
+
+    virtual void OnDownloadComplete();
+	
+	     // navigation operation completed
+
+    virtual void OnNavigateComplete2(CString URL);
+
+        // navigation to hyperlink complete; URL is location
+		// (URL = string if NavigateString or NavigateResource are used)
+
+    virtual void OnStatusTextChange(CString text);
+
+        // status text has changed
+
+    virtual void OnTitleChange(CString text);
+
+		// title has changed
+
+	virtual void OnPrintTemplateInstantiation();
+	
+		// print template has been instantiated (printing has begun)
+		
+	virtual void OnPrintTemplateTeardown();
+	
+		// print template is being destroyed (printing has completed)		
+
+	void Copy();
+
+	// notifications
+	
+	enum NotificationType {					// Note: SimpleBrowser does NOT support the
+											//       common notifications (NM_CLICK, etc.)
+
+		BeforeNavigate2,					// set *LRESULT=TRUE to cancel navigation
+		DocumentComplete,				
+		DownloadBegin,
+		ProgressChange,
+		DownloadComplete,
+		NavigateComplete2,
+		StatusTextChange,
+		TitleChange,
+		PrintTemplateInstantiation,
+		PrintTemplateTeardown
+
+	};
+	
+	class Notification {					// all notifications pass this structure
+
+	public:
+
+		Notification(HWND hwnd,UINT ID,NotificationType type);
+		~Notification();
+
+		NMHDR			hdr;				// hdr.hwndFrom = SimpleBrowser's HWND
+											// hdr.idFrom   = SimpleBrowser's control ID
+											// hdr.code     = <NavigationType>
+
+		CString			URL;				// BeforeNavigate2
+											// DocumentComplete
+											// NavigateComplete2
+
+		CString			frame;				// BeforeNavigate2
+		void			*post_data;			// BeforeNavigate2
+		int				post_data_size;
+		CString			headers;			// BeforeNavigate2
+
+		int				progress;			// ProgressChange
+		int				progress_max;		// ProgressChange
+
+		CString			text;				// StatusTextChange
+											// TitleChange
+
+	};
+
+	bool ParsePostData(CString post_data,		// parse URL-encoded POST data
+	                   CStringArray &names,		// string into list of names
+	                   CStringArray &values);	// and values; returns true if
+												// successful
+
+    //{{AFX_VIRTUAL(SimpleBrowser)
+	public:
+	virtual void PostNcDestroy();
+	//}}AFX_VIRTUAL
+
+protected:
+
+    //{{AFX_MSG(SimpleBrowser)
+	afx_msg void OnSize(UINT nType, int cx, int cy);
+	afx_msg BOOL PreTranslateMessage(MSG *pMsg);
+	//}}AFX_MSG
+
+    void _OnBeforeNavigate2(LPDISPATCH lpDisp,
+                            VARIANT FAR *URL,
+                            VARIANT FAR *Flags,
+                            VARIANT FAR *TargetFrameName,
+                            VARIANT FAR *PostData,
+                            VARIANT FAR *Headers,
+                            VARIANT_BOOL *Cancel);
+    void _OnDownloadBegin();
+    void _OnProgressChange(long progress,long progress_max);
+    void _OnDownloadComplete();
+    void _OnDocumentComplete(LPDISPATCH lpDisp,VARIANT FAR* URL);
+    void _OnNavigateComplete2(LPDISPATCH lpDisp,VARIANT FAR* URL);
+    void _OnStatusTextChange(BSTR bstrText);
+    void _OnTitleChange(BSTR bstrText);
+	void _OnPrintTemplateInstantiation(LPDISPATCH pDisp);
+	void _OnPrintTemplateTeardown(LPDISPATCH pDisp);
+
+    DECLARE_MESSAGE_MAP()
+    DECLARE_EVENTSINK_MAP()
+
+private:
+
+    CWnd                    _BrowserWindow;     // browser window
+
+protected:
+
+	IWebBrowser2			*_Browser;          // browser control
+
+	bool					_Ready;				// document ready
+												// (initial navigation completed)
+
+private:    
+    
+    IDispatch               *_BrowserDispatch;  // browser control 
+												// dispatch interface
+
+	CString					_Content;			// current content set via Write()/Clear()
+	
+	void _ContentWrite();
+
+};
+
+#endif

+ 32 - 6
ToolTipEx.cpp

@@ -275,10 +275,11 @@ BOOL CToolTipEx::Show(CPoint point)
 
 	m_saveWindowLockout = true;
 	MoveWindow(rect);
-	ShowWindow(SW_SHOWNA);
-	this->Invalidate();
-	this->UpdateWindow();
 	MoveControls();
+	ShowWindow(SW_SHOWNA);
+	//this->Invalidate();
+	//this->UpdateWindow();
+	
 
 	m_saveWindowLockout = false;
 
@@ -301,10 +302,15 @@ BOOL CToolTipEx::Hide()
 	delete m_imageViewer.m_pGdiplusBitmap;
 	m_imageViewer.m_pGdiplusBitmap = NULL;
 
-	SaveWindowSize();
-
+	SaveWindowSize();	
 	ShowWindow(SW_HIDE);
 
+	if (m_browser.m_hWnd != NULL &&
+		::IsWindow(m_browser.m_hWnd))
+	{
+		m_browser.DestroyWindow();
+	}
+
 	m_csRTF = "";
 	m_csText = "";
 	m_html = "";
@@ -454,6 +460,18 @@ BOOL CToolTipEx::OnMsg(MSG *pMsg)
         case WM_KEYDOWN:
             {
                 WPARAM vk = pMsg->wParam;
+
+				if(vk == 'C')
+				{
+					if (GetKeyState(VK_CONTROL) & 0x8000)
+					{
+						if (::IsWindow(m_browser.m_hWnd))
+						{
+							m_browser.Copy();
+							return TRUE;
+						}
+					}
+				}
                 
                 if(vk == VK_TAB)
                 {
@@ -777,7 +795,15 @@ void CToolTipEx::SetHtmlText(const CString &html)
 		}
 		else
 		{
-			m_html = html;
+			int pos = html.Find(_T("<HTML"));
+			if (pos >= 0)
+			{
+				m_html = html.Mid(pos);
+			}
+			else
+			{
+				m_html = html;
+			}
 		}
 
 		COLORREF c = g_Opt.m_Theme.DescriptionWindowBG();