На этом шаге мы рассмотрим пример программы, иллюстрирующей доступ к объектной модели DHTML.
Как Вы помните, доступ к DHTML-объектам, таким, как window или document, очень прост, если сценарий размещен непосредственно в HTML-документе. Ссылаться на эти объекты разрешается просто по имени, как показано в следующем коде на JavaScript:
document.bgColoг = "hotpink";
Такая возможность обусловлена тем, что интерпретатор сценариев Internet Explorer анализирует строки Вашего сценария и преобразует их в вызовы интерфейсов Internet Explorer Automation. В C++ к объектной модели DHTML обращаются напрямую, вызывая соответствующие интерфейсы Automation.
Объектная модель DHTML доступна через набор СОМ-интерфейсов, имена которых начинаются с префикса IHTML (IHTMLDocument, IHTMLWindow, IHTMLElement и т. п.). Класс CHtmlView предоставляет функцию GetHtmlDocument(), возвращающую указатель IDispatch на текущий HTML-документ. Зная его, Вы можете вызвать QueryInterface() и получить указатели на IHTML-интерфейсы. А это в свою очередь позволит Вам управлять документом, работая со свойствами и методами этих интерфейсов.
Ниже мы посмотрим, как обращаться к элементам HTML-страницы, отображенной в приложении MyHtmlApp. Мы напишем код, создающий в отдельном диалоговом окне список всех анкеров (ссылок) текущей страницы со значениями их HREF-атрибутов (URL или пути к файлу). Пользователь сможет открыть любую из этих ссылок в браузере.

Рис.1. Диалоговое окно View Links

Рис.2. Создание класса CLinkDialog
| Идентификатор | Категория | Тип переменной | Имя переменной ресурса |
|---|---|---|---|
| IDC_LINK_LIST | Переменная | CString | m_strLink |
| IDC_LINK_LIST | Элемент управления | CListBox | m_lbLinkList |

Рис.3. Результат добавления переменных

Рис.4. Перегрузка функции OnInitDialog()
BOOL CLinkDialog::OnInitDialog()
{
CDialog::OnInitDialog();
// Получаем указатель на вид
CFrameWnd * pFrame = dynamic_cast<CFrameWnd *>( AfxGetMainWnd());
ASSERT_VALID( pFrame );
CHtmlView * pHtmlView = dynamic_cast<CHtmlView *>
( pFrame->GetActiveView());
ASSERT_VALID( pHtmlView );
// Получаем указатель на диспетчерский интерфейс
// объекта документа
IDispatch * pDisp = pHtmlView->GetHtmlDocument();
if( pDisp != NULL )
{
// Получаем указатель на интерфейс IHTMLDocument2
// для доступа к свойствам и методам объекта
IHTMLDocument2 * pHTMLDocument2;
HRESULT hr;
hr = pDisp->QueryInterface( IID_IHTMLDocument2,
(void**)&pHTMLDocument2 );
if( hr == S_OK )
{
// Получаем указатель на набор анкеров
IHTMLElementCollection * pColl = NULL;
hr = pHTMLDocument2->get_anchors( &pColl );
if( hr == S_OK && pColl != NULL )
{
LONG nElem;
hr = pColl->get_length( &nElem );
if( hr == S_OK )
{
// Просматриваем набор анкеров
for( long i = 0; i < nElem; i++ )
{
_variant_t vIndex( i );
_variant_t vName = vIndex;
IDispatch * pDisp2;
hr = pColl->item( vName, vIndex, &pDisp2 );
if( hr == S_OK )
{
// Получаем указатель на каждый
// из элементов <Anchor> для
// получения URL-адреса и его
// включения в список
HTMLAnchorElement * pAnchElem;
hr = pDisp2->QueryInterface(
IID_IHTMLAnchorElement,(void**) &pAnchElem );
if( hr == S_OK )
{
BSTR bstrHref = 0;
pAnchElem->get_href( &bstrHref );
CString strLink( bstrHref );
if( !strLink.IsEmpty() )
m_lbLinkList.AddString( strLink );
SysFreeString( bstrHref );
pAnchElem->Release();
}
pDisp2->Release();
}
}
}
pColl->Release();
}
pHTMLDocument2->Release();
}
pDisp->Release();
}
return TRUE;
// Возвращаем TRUE, если только фокус
// не на элементе управления
// ИСКЛЮЧЕНИЕ: OCX-страницы свойств
// должны возвращать FALSE
}
#include <mshtml.h> #include <comdef.h>

Рис.5. Создание функции-обработчика CMyHtmlAppView::OnViewLinks
void CMyHtmlAppView::OnViewLinks() { CLinkDialog aDlg; if(aDlg.DoModal() == IDOK) // (Кнопка "Go to link") { // Если в списке есть выбранная ссылка - переходим на нее if (! aDlg.m_strLink.IsEmpty()) Navigate2(aDlg.m_strLink, NULL, NULL); } }
#include "LinkDialog.h"

Рис.6. Пример работы приложения

Рис.7. Установка флажка Enable Run-Time Type Information (RTTI)
Созданное приложение можно взять здесь (45,3 Кб).
На следующем шаге мы рассмотрим ресурсы HTML.