📄 simplebrowser.cpp
字号:
/////////////////////////////////////////////////////////////////////////////
// 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)
{
}
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;
_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 blank page; wait for document creation
if (_Browser != NULL) {
Navigate(_T("about:blank"));
IHTMLDocument2 *document = NULL;
HRESULT hr = S_OK;
while ((document == NULL) && (hr == S_OK)) {
Sleep(0);
IDispatch *document_dispatch = NULL;
hr = _Browser->get_Document(&document_dispatch);
// if dispatch interface available, retrieve document interface
if (SUCCEEDED(hr) && (document_dispatch != NULL)) {
// retrieve document interface
hr = document_dispatch->QueryInterface(IID_IHTMLDocument2,(void **)&document);
document_dispatch->Release();
}
}
if (document != NULL) {
document->Release();
}
}
return TRUE;
}
// Create in place of dialog control
BOOL SimpleBrowser::CreateFromControl(CWnd *pParentWnd,UINT nID)
{
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((WS_CHILD | WS_VISIBLE),
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;
}
}
/////////////////////////////////////////////////////////////////////////////
// Controls
/////////////////////////////////////////////////////////////////////////////
// Navigate to URL
void SimpleBrowser::Navigate(LPCTSTR URL)
{
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) {
// 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 = CString(string).AllocSysString();
SafeArrayUnaccessData(safe_array);
// write SAFEARRAY to browser document
document->write(safe_array);
document->Release();
document = NULL;
}
}
}
void SimpleBrowser::Clear()
{
if (_Browser != NULL) {
// if document interface available, close/re-open document to clear display
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();
}
}
// otherwise, navigate to about:blank and wait for document ready
else {
Navigate(_T("about:blank"));
IHTMLDocument2 *document = NULL;
HRESULT hr = S_OK;
while ((document == NULL) && (hr == S_OK)) {
Sleep(0);
IDispatch *document_dispatch = NULL;
hr = _Browser->get_Document(&document_dispatch);
// if dispatch interface available, retrieve document interface
if (SUCCEEDED(hr) && (document_dispatch != NULL)) {
// retrieve document interface
hr = document_dispatch->QueryInterface(IID_IHTMLDocument2,(void **)&document);
document_dispatch->Release();
}
}
if (document != NULL) {
document->Release();
}
}
}
}
// 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -