пятница, 26 сентября 2008 г.

как получить элементы созданные JavaScript из DOM VC++

Сегодня столкнулся с такой вот проблемой - надо было получить элемент на web-страничке созданный javascript-ом из DOM VC++ кода.

Потратив уйму времени на поиски ответа в интернете, я уже было отчаялся, но
на самом деле всё оказолось намного проще, чем я ожидал :) В общем, что бы получить элемент в своё управление надо его получать через id, так как и сам скрипт обращается к созданым им элементам через их id.

Наглядный пример доступа к элемнету в javascript:


function Paste(text)
{
element = document.getElementById("message");
element.focus();
element.text = "какой то текст";
}


Тогда для vc++ будет:

// результат
IHTMLDocument2* pHtmlDoc2=NULL;

// интерфейс диспатча
LPDISPATCH lpDispatch=NULL;
if (!pBrowser)
lpDispatch=pHtmlCtrl->GetHtmlDocument();
else
{
HRESULT hr=pBrowser->get_Document(lpDispatch);

// Получим интерфейс докуменрта
HRESULT hr=lpDispatch->QueryInterface(IID_IHTMLDocument2, (void**)pHtmlDoc2);

// осовободим
lpDispatch->Release();
lpDispatch=NULL;

// получим список всех элементов документа
IHTMLElementCollection* pAllElements=NULL;
HRESULT hr=pHtmlDoc2->get_all( pAllElements );

pHtmlDoc2->Release();
pHtmlDoc2=NULL;

// получим количество элементов
long iCount;
pAllElements->get_length( &iCount );

// это тот самый элемент, который мы ищем
IHTMLElement* pElement=NULL;

// или вот этот диспатч
LPDISPATCH lpDispatch=NULL;
VARIANT bstrValue;
// пройдемся циклом по всем элементам
long i;
CString sID;
bool bFound =false;
for( i=0; iitem( i, i, &lpDispatch );
if (!lpDispatch)
continue;


// Получим интерфейс докуменрта
HRESULT hr=lpDispatch->QueryInterface(IID_IHTMLElement, (void**&pElement);

if (!pElement)
continue;

// получим id i-того элемента
CString strAt="id";
BSTR bstrAt = strAt.AllocSysString();
pElement->getAttribute(bstrAt,1,&bstrValue );

CString strNameVal ="";
if ( bstrValue.vt!=1 )
{
BSTR reVal = bstrValue.bstrVal;
sID=CString(reVal);
SysFreeString(bstrAt);
SysFreeString(reVal);
}

if(sID==sInputID) //sInputID - это id по которому мы и ищем элемент

// в нашем случае (message)
{
bFound =true;
break;
}

pElement->Release();
pElement =NULL;
}

// осовбодим интерфейсы если ничего не нашли
if (!bFound)
{
lpDispatch->Release();
lpDispatch=NULL;

pElement->Release();
pElement =NULL;

// в зависимости от того что вам надо на выходе

// вы можете использовать или lpDispatch элемента

// или же сам элемент как IHTMLElement интерфейс (pElement)

// но надо помнить что из lpDispatch мы можем получить конечный интерфейс

// элемента например IHTMLInputElement если это INPUT элемент
}

pAllElements->Release();
pAllElements=NULL;


// установим текст в элемент message
pElement->put_innerText(BSTR str);


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

2 комментария:

Анонимный комментирует...

Я тоже этим вопросом очень интересуюсь!
Только хочется что-то более серверное.
Я думаю может возможно получить самим же JS созданную страницу.
Если у вас остались подборки материалов по этой теме, поделитесь плиз.
pocketdevil{а}gmail{.}com

Игорь комментирует...

>Я думаю может возможно получить самим же JS созданную страницу.
в С++ получить сам документ очень просто

// получим интерфейс документа
IDispatch* pDocDisp = GetHtmlDocument();
if (!pDocDisp)
return;

и вот тут получаем дальше IHTMLDocument или IHTMLDocument2 что вам будет угодно

// получим IHTMLDocument2
IHTMLDocument2* pDoc2Disp = NULL;
pDocDisp->QueryInterface(IID_IHTMLDocument2, (void**)&pDoc2Disp);
pDocDisp->Release();