Алекс Jenter - Программирование на Visual C++. Архив рассылки
- Название:Программирование на Visual C++. Архив рассылки
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Алекс Jenter - Программирование на Visual C++. Архив рассылки краткое содержание
РАССЫЛКА ЯВЛЯЕТСЯ ЧАСТЬЮ ПРОЕКТА RSDN, НА САЙТЕ КОТОРОГО ВСЕГДА МОЖНО НАЙТИ ВСЮ НЕОБХОДИМУЮ РАЗРАБОТЧИКУ ИНФОРМАЦИЮ, СТАТЬИ, ФОРУМЫ, РЕСУРСЫ, ПОЛНЫЙ АРХИВ ПРЕДЫДУЩИХ ВЫПУСКОВ РАССЫЛКИ И МНОГОЕ ДРУГОЕ.
Программирование на Visual C++. Архив рассылки - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
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.
Интерфейс 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 визуализацией ясно, а как же теперь обеспечить интерактивность? Как избавиться от ненужных клавишных комбинаций и меню? Как получить доступ из скриптов к внутренней модели объектов нашей программы?
Компания Microsoft предоставила возможность расширения объектной модели через механизм window.external. Приложение, использующее web-browser control может реализовывать собственную логику через переопределение объекта external. Естественно, чтобы иметь возможноть работать со своим приложением из скрипта, программа должна реализовывать dispatch-интерфейсы. При помощи ClassWizard, добавить поддержку автоматизации к своим объектам не составляет труда. Единственным замечанием здесь может служить лишь то, что объекты должны наследоваться от CCmdTarget. Чтобы передать указатель на свой объект самому объекту webbrowser, а заодно установить целую кучу дополнительных параметров, необходимо реализовать cлужебный интерфейс IDocHostUIHandler, который описан в mshtmhst.h. Этот интерфейс представляет собой некий call-back, или интерфейс обратной связи, к которому обращается webbrowser в следующих случаях:
• Необходимо показать контекстное меню. Как раз здесь можно заменить стандартное меню Internet-explorer на свое собственное. Либо вообще сделать так, чтобы меню не показывалось.
• Есть возможность подменить элементы пользовательского интерфейса браузера.
• Нужно обработать нажатие горячей клавиши.
• Нужно обработать URL, по которому совершается переход.
• Нужно обработать события drag-and-drop.
• Необходимо получить указатель на объект window.external.
После реализации этого call-back объекта, его можно "инсталлировать", используя метод интерфейса ICustomDoc SetUIHandler. Интерфейс IСustomDoc экспортируется обычно реализуется тем же объектом, что реализует IHTMLDocument2.
// код из OnNavigateComplete
CComQIPtr m_pBrowserCustomDoc;
CComQIPtr pADocument;
CDocHostUIHandler m_DocHostImpl;
m_DocHostImpl.AddRef();
m_DocHostImpl.m_pAppDisp = m_pApp->GetIDispatch(FALSE);
m_pBrowserCustomDoc = pADocument;
m_pBrowserCustomDoc->SetUIHandler((IDocHostUIHandler*)&m_DocHostImpl);
В данном коде фигурирует класс CDocHostUIHandler, который реализует все методы интерфейса IDocHostUIHandler (и конечно же AddRef, QueryInterface и Release от IUnknown). В базовом варианте, реализация этого объекта сводится лишь к созданию процедур-заглушек для каждого метода IDocHostUIHandler, возвращающих E_NOTIMPL. А если хочется, чтобы Internet Explorer не показывал своего конекстного меню, нужно возвращать из метода ShowContextMenu S_OK.
Если наш объект CDocHostUIHandler возвращает указатель в методе get_External, то этот указатель и используется как объект расширения и тогда где-нибудь внутри самой html странички можно будет написать такие строки:
function ShowSettingsDialog() {
if (window.external.ShowSettings() == true) {
document.body.bgcolor = window.external.BackColor;
}
}
Settings
В приведенном примере, функция ShowSettings и свойство BackColor запрашиваются из недр нашего собственного приложения.
Где хранить свои HTML
В ресурсах! К счастью, Internet explorer умеет грузить из ресурсов, нужно только в качестве префикса URL написать res://<���путь к модулю>/<���название ресурса>. Я привожу реализацию этого метода, выдранную из исходного текста CHTMLView.
HINSTANCE hInstance = AfxGetResourceHandle();
CString strResourceURL;
BOOL bRetVal = TRUE;
LPTSTR lpszModule = new TCHAR[_MAX_PATH];
if (GetModuleFileName(hInstance, lpszModule, _MAX_PATH)) {
// lpszResource - строкое название ресурса
strResourceURL.Format(_T("res://%s/%s"), lpszModule, lpszResource);
Интервал:
Закладка: