На главную

Библиотека Интернет Индустрии I2R.ru

Rambler's Top100

Малобюджетные сайты...

Продвижение веб-сайта...

Контент и авторское право...

Забобрить эту страницу! Забобрить! Блог Библиотека Сайтостроительства на toodoo
  Поиск:   
Рассылки для занятых...»
I2R » И2Р Программы » Программирование » C, C++

Автоматизация и моторизация приложения. Браузер в каждом окне.

Помните, какой революцией был Windows 95, с его новыми элементами: list view, tree view, sliders, tabs ? Радикально отличаясь от своего предшественника, он представлял дизайнерам пользовательского интерфейса новые гибкие возможности. Сегодня требования к программному обеспечению растут, информации становится больше, информация становится разнообразнее. Теперь, древовидными списками с закладками не обойтись. И вот, выходит Windows 98, где папки можно просматривать в режиме web, работая с наглядной информации. Круговая диаграмма, дополнительная информация о папке, Outlook today – все это на самом деле реализовано в HTML, а еще точнее, в DHTML (т.е. Dynamic HTML, оживший, при помощи скриптов, HTML). Все help системы Windows 98/2000 уже представлены в HTML виде.

Зачастую оказывается, что web-интерфейсы значительно дружественнее, чем обычные диалоговые окна, ведь они ориентированы больше на документ, нежели на приложение. Да и разработчику они обходятся дешевле, чем поддержание многозакладочных информационных диалогов. Дизайн приложений в стиле Web предлагает множество преимуществ, такие как богатая визуализация и концепция навигации через гиперссылки. Хорошо сконструированный пользовательский интерфейс не только приносит эстетическое удовлетворение, но и является ключом к успеху всего приложения.. И все это вызывает энтузиазм, до тех пор, пока дело не доходит до реализации. Красота дело тонкое, потому сегодня я попытаюсь рассказать о некоторых аспектах реализации web-интерфейсов.

В каком виде это делается

Довольно редко web-интефейсы используются cами по себе, чаще они входят в состав какой-либо схемы, скомбинированной из DHTML и обычных windows элементов. Вот некоторая выборка наиболее часто встречающихся схем:

Схема А

Схема А

Дополнительные элементы управления встраиваются в HTML компонент через тэг

<OBJECT>. Преимущества такого решения в том, что дополнительные элементы позиционируются на странице так, как это описано в HTML, также элементы могут управляться через скрипт. А недостатком решения – необходимость реализации дополнительных компонентов как ActiveX. На Схеме А, таким компонентом является список файлов.

Схема Б

Схема Б

В этой схеме реализация интерфейса полностью выполнена на DHTML, с использованием web-browser control. Преимущество такого подхода состоит в масшабируемости решения, возможности применения любых дизайнерских техник. К недостаткам же можно отнести не слишком высокое быстродействие.

Схема В

Схема В

Cовмещенная гибкая реализация, использующая как HTML элемент, так и дерево, наиболее удобна для приложений, которые работают с обширными структурами данных. Навигация проста и эффективна: может выполняться не только с помощью HTML элемента, но и при помощи древовидного списка. К недостаткам отнесу некоторую громоздкость такого дизайна.

Схема Г

Схема Г

Cовмещенная жесткая реализация – наиболее оптимальная схема для небольших приложений и диалоговых окон.

Можно было бы выделить еще и пятую схему – запуск приложения внутри браузера, но я считаю, что это уже бросок в сторону интернет решений.

Как это работает

Internet Explorer (c версии 4.0 и позже) предоставляет технологии, при помощи которых программисты могут встраивать всю функциональность браузера в свои приложения. Эти технологии реализуются в ActiveX компонентах, как визуальных так и невидимых. Основной компонент, представляющий элемент web-browser control, содержится в библиотеке shdocvw.dll, использующей средства парсинга и рендринга HTML кода, а также выполнение DHTML скриптов от другого компонента - mshtml.dll. По сути, web-browser control является обычным ActiveX компонентом, с множеством стандартных свойств. Тем не менее, каждая загруженная страничка внутри такого элемента представляется в виде объектной модели документа HTML. Это значит, что любой элемент HTML, такой как параграф или ячейка таблицы, доступен разработчику в виде COM-объекта, со множеством свойств и методов.

По-правде говоря, библиотеки 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 в MFС, реализованной в классе CHTMLView. При создании приложений по схеме В, я рекомендую пользоваться именно им. Встроенные визарды Visual Studio уже содержат все средства для начальной генерации таких приложений. Ежели все-таки душе роднее тернистый путь, то внедрение компонента будет выглядит следующим образом:

<p>CRect rectClient(10,10,200,200); CWnd m_wndBrowser; CComQIPtr<IWebBrowser2, &IID_IWebBrowser2> 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); } </p>

Замечу, что 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:

<p>// Web browser event sink DECLARE_EVENTSINK_MAP() virtual void OnDownloadComplete(); virtual void DocumentComplete(LPDISPATCH pDisp, VARIANT* URL); </p>

А в .cpp файле добавим строки:

<p>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() </p>

Для полной реализации механизма отлова событий этим путем, лучше всего обратиться к исходным текстам CHTMLView.

Модель объектов DHTML

Интерфейс DWebBrowserEvents2 при помощи события DISPID_NAVIGATECOMPLETE позволяет определить тот момент, когда HTML документ полностью сгенерирован внутри webbrowser control. После того, как это происходит, весь HTML документ доступен через функцию IWebBrowser2::get_Document. Также, как и webbrowser control, HTML документ поддерживает события, такие как click, mouseover. Для того, чтобы использовать объектную модель DHTML, нужно подключить заголовок mshtml.h.

<p>CComQIPtr<IHTMLDocument2,&IID_IHTMLDocument2> pADocument; IDispatch* pdispTmpVal; m_pBrowserApp->get_Document(&pdispTmpVal); pADocument = pdispTmpVal; pdispTmpVal->Release();</P>

Интерфейс IHTMLDocument2 предоставляет возможность получать и модифицировать содержимое документа. Вы можете использовать множество методов, таких как get_body, get_all, get_activeElement чтобы извлекать элементы или коллекции элементов внутри документа. Базовой основой для любого тэга внутри HTML-документа является интерфейс IHTMLElement. Меняя содержимое тэга при помощи свойств innerHTML и outerHTML мы реализуем принцип динамического содержания, который нами и преследовался. К любому элементу можно адресоваться при помощи идентификатора id через вызов IHTMLElementCollection::Item. Итак, c визуализацией ясно, а как же теперь обеспечить интерактивность? Как избавиться от ненужных клавишных комбинаций и меню? Как получить доступ из скриптов к внутренней модели объектов нашей программы?

Расширение объектной модели DHTML

Компания 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.

<p>// код из OnNavigateComplete CComQIPtr<ICustomDoc, &IID_ICustomDoc> m_pBrowserCustomDoc; CComQIPtr<IHTMLDocument2,&IID_IHTMLDocument2> pADocument; CDocHostUIHandler m_DocHostImpl; m_DocHostImpl.AddRef(); m_DocHostImpl.m_pAppDisp = m_pApp->GetIDispatch(FALSE); m_pBrowserCustomDoc = pADocument; m_pBrowserCustomDoc-> SetUIHandler((IDocHostUIHandler*)&m_DocHostImpl); </p>

В данном коде фигурирует класс CDocHostUIHandler, который реализует все методы интерфейса IDocHostUIHandler (и конечно же AddRef, QueryInterface и Release от IUnknown). В базовом варианте, реализация этого объекта сводится лишь к созданию процедур-заглушек для каждого метода IDocHostUIHandler, возвращающих E_NOTIMPL. А если хочется, чтобы Internet Explorer не показывал своего конекстного меню, нужно возвращать из метода ShowContextMenu S_OK.

Если наш объект CDocHostUIHandler возвращает указатель в методе get_External, то этот указатель и используется как объект расширения и тогда где-нибудь внутри самой html странички можно будет написать такие строки:

<p><script language=”JavaScript”> <BR>function ShowSettingsDialog()<BR>{<BR>  if (window.external.ShowSettings() == true) <BR> {<BR>   document.body.bgcolor = window.external.BackColor;<BR>  }<BR>}<BR> </script><P></P> <P><body><BR>  <a href=”javascript:ShowSettingsDialog()”>Settings</a><BR></body></P> </p>

В приведенном примере, функция ShowSettings и свойство BackColor  запрашиваются из недр нашего собственного приложения.

Где хранить свои HTML

В ресурсах! К счастью, Internet explorer умеет грузить из ресурсов, нужно только в качестве префикса URL написать res://<путь к модулю>/<название ресурса>. Я привожу реализацию этого метода, выдранную из исходного текста CHTMLView.

<p> 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); m_pBrowserApp-> Navigate(strResourceURL, NULL, NULL, NULL, NULL); } else bRetVal = FALSE; delete [] lpszModule; return bRetVal; </p>

HTML ресурсы можно вынести в отдельный подкаталог, например html. Тогда в файле описания ресурсов (например, myapp.rc) необходимо добавить строки следующего вида:

<p> IDR_MAIN HTML DISCARDABLE "html\\main.html" DEL.GIF HTML DISCARDABLE "html\\del.gif" LEFTARR.GIF HTML DISCARDABLE "html\\leftarr.gif" RIGHTARR.GIF HTML DISCARDABLE "html\\rightarr.gif" TITLE.GIF HTML DISCARDABLE "html\\title.gif" NEWMSG.GIF HTML DISCARDABLE "html\\newmsg.gif" </p>

Реализация доступа к ресурсам в IE достаточно умна, чтобы автоматически найти все необходимые объекты в ресурсах, на которые ссылается страничка, поэтому достаточно знать лишь ресурс-имя основной странички.

В следующей статье раздела я обращусь к проблеме встраивания скрипт-процессора в свое приложение, чтобы обеспечить внутреннюю автоматизацию без поддержки IE.

Николай Куртов
Софтерра

Другие разделы
C, C++
Java
PHP
VBasic, VBS
Delphi и Pascal
Новое в разделе
Базы данных
Общие вопросы
Теория программирования и алгоритмы
JavaScript и DHTML
Perl
Python
Active Server Pages
Программирование под Windows
I2R-Журналы
I2R Business
I2R Web Creation
I2R Computer
рассылки библиотеки +
И2Р Программы
Всё о Windows
Программирование
Софт
Мир Linux
Галерея Попова
Каталог I2R
Партнеры
Amicus Studio
NunDesign
Горящие путевки, идеи путешествийMegaTIS.Ru

2000-2008 г.   
Все авторские права соблюдены.
Rambler's Top100