По-правде говоря, библиотеки shdocvw.dll, а особенно mshtml.dll не такие уж и легковесные относительно памяти. Тем не менее следует учитывать, что обычно webbrowser control подгружается системой на запуске, а все повторные запросы на загрузку этих библиотек перенаправляются на уже загруженные ранее модули. Таким образом использование webbrowser control не влечет чрезмерного расходования системных ресурсов, если конечно, ваш html документ не имеет сверхсложной структуры и гигантстких размеров.
Internet Explorer версии 5.5 предоставляет поистине громадное количество новых возможностей для разработчика, что позволяет создавать мультимедийные системы на основе браузера. Подробное описание нововведений можно найти в последних выпусках MSDN.
Web browser control
Прежде, чем приступать к реализации, отмечу, что буду использовать в примерах классы MFC. Естественно, существует множество путей для внедрения web-компонента в приложения на Visual Basic, C++ ATL или Delphi. Я надеюсь, пользователи этих средств, найдут эту статью столь же полезной, сколь и пользователи MFC.
Вставка компонента
Использовать компонент можно "напрямую", вставляя OLE-объект на форму, или косвенно, через вызов к CWnd::CreateControl. Важным фактом является наличие уже созданной обертки для webbrowser в MFC, реализованной в классе CHTMLView. При создании приложений по схеме В, я рекомендую пользоваться именно им. Встроенные визарды Visual Studio уже содержат все средства для начальной генерации таких приложений. Ежели все-таки душе роднее тернистый путь, то внедрение компонента будет выглядит следующим образом:
CRect rectClient(10,10,200,200);
CWnd m_wndBrowser;
CComQIPtr m_pBrowserApp;
if (!m_wndBrowser.CreateControl(CLSID_WebBrowser, _T("Window"), WS_VISIBLE | WS_CHILD, rectClient, this, AFX_IDW_PANE_FIRST)) {
DestroyWindow();
}
if (m_pBrowserApp = m_wndBrowser.GetControlUnknown()) {
CComBSTR bstrURL = _T("http://www.microsoft.com");
m_pBrowserApp->Navigate(bstrURL, NULL, NULL, NULL, NULL);
}
Замечу, что CLSID_WebBrowser — идентификатор объекта webbrowser, описанный в файле comdef.h. Этот файл имеет ключевое значение, поскольку в нем отражены идентификаторы основных интерфейсов объектной модели Windows, в частности WebBrowser и объектной модели HTML. Для большинства элементов объявлены smart-pointers, что особенно актуально для работы с DHTML из приложения, где просто море различных интерфейсов. Помимо стандартных для ActiveX элементов интерфейса, webbrowser компонент экспортирует также два собственных интерфейса:
• IWebBrowser2. Этот интерфейс реализует управление элементом: внешним видом, параметрами, а также позволяет производить навигацию.
• DWebBrowserEvents2. Объект webbrowser использует события для уведомления приложения о состоянии компонента. Например, перед навигацией на новый URL, вызывается событие BeforeNavigate2.
Описание этих интерфейсов exdisp.h/ exdispid.h. Оглядываясь на практический опыт, замечу, что ссылки на все описанные файлы лучше прописывать в stdafx.h.
Подключение событий
Механизм подключения событий через точки соединения стандартный, поэтому не имеет смысла его здесь описывать. Тем более, что MFC предоставляет более удобный способ для отлова событий webbrowser через DECLARE_EVENTSINK_MAP макрос.
Запишем в заголовочном файле класса, содержащего webbrowser control:
// Web browser event sink
DECLARE_EVENTSINK_MAP()
virtual void OnDownloadComplete();
virtual void DocumentComplete(LPDISPATCH pDisp, VARIANT* URL);
А в .cpp файле добавим строки:
BEGIN_EVENTSINK_MAP(CChatChannelDialog, CDialog)
ON_EVENT(CChatChannelDialog, AFX_IDW_PANE_FIRST, DISPID_NAVIGATECOMPLETE, OnDownloadComplete, VTS_NONE)
ON_EVENT(CChatChannelDialog, AFX_IDW_PANE_FIRST, DISPID_DOCUMENTCOMPLETE, DocumentComplete, VTS_DISPATCH, VTS_PVARIANT)
END_EVENTSINK_MAP()
Для полной реализации механизма отлова событий этим путем, лучше всего обратиться к исходным текстам CHTMLView.
Модель объектов DHTML
Интерфейс DWebBrowserEvents2 при помощи события DISPID_NAVIGATECOMPLETE позволяет определить тот момент, когда HTML документ полностью сгенерирован внутри webbrowser control. После того, как это происходит, весь HTML документ доступен через функцию IWebBrowser2::get_Document. Также, как и webbrowser control, HTML документ поддерживает события, такие как click, mouseover. Для того, чтобы использовать объектную модель DHTML, нужно подключить заголовок mshtml.h.
CComQIPtr pADocument;
IDispatch* pdispTmpVal;
m_pBrowserApp->get_Document(&pdispTmpVal);
pADocument = pdispTmpVal;
pdispTmpVal->Release();
Интерфейс IHTMLDocument2 предоставляет возможность получать и модифицировать содержимое документа. Вы можете использовать множество методов, таких как get_body, get_all, get_activeElement чтобы извлекать элементы или коллекции элементов внутри документа. Базовой основой для любого тэга внутри HTML-документа является интерфейс IHTMLElement. Меняя содержимое тэга при помощи свойств innerHTML и outerHTML мы реализуем принцип динамического содержания, который нами и преследовался. К любому элементу можно адресоваться при помощи идентификатора id через вызов IHTMLElementCollection::Item. Итак, c визуализацией ясно, а как же теперь обеспечить интерактивность? Как избавиться от ненужных клавишных комбинаций и меню? Как получить доступ из скриптов к внутренней модели объектов нашей программы?
Читать дальше