这段代码有什么问题吗? 关于IHTMLLinkElement的。
以下使用的是www.youkuaiyun.com/expert的网页.
void CLeftView::GetAllRoom(IHTMLDocument2Ptr pDoc)
{
USES_CONVERSION;
IDispatchPtr pDisp;
IHTMLElementCollectionPtr pItems;
_variant_t vIndex, vDummy;
HRESULT hr;
long p(0);
pDoc->get_all(&pItems);
pItems->get_length(&p);
vIndex.vt = VT_I4;
try
{
hr = pDoc->get_all(&pItems);
if (FAILED(hr))
return;
pItems->get_length(&p);
long i(0);
for (; i < p; ++i)
{
vIndex.lVal = i;
IDispatchPtr pDisp;
if (SUCCEEDED(pItems->item(vIndex, vDummy, &pDisp)))
{
IHTMLLinkElementPtr pLink;
_bstr_t link;
if (SUCCEEDED(pDisp->QueryInterface(&pLink)))
{
TRACE("Get a link element/n"); // 只输出一次,不会只有一个吧???
if (SUCCEEDED(pLink->get_href((BSTR*)&link)))
{
;
}
}
}
}
}
catch (_com_error &e)
{
CString error = W2T(e.Description());
TRACE("exception : %s/n", error);
}
catch (...)
{
TRACE("Get Exception : unknow excpetion/n");
}
//-------
// Log it
//-------
CFile file;
int _count(0);
file.Open("c://test.txt", CFile::modeCreate | CFile::modeReadWrite);
for (_count = 0; _count < m_strRoom.GetSize(); ++_count)
{
file.Write(m_strRoom[_count], m_strRoom[_count].GetLength());
file.Write("/r/n", 4);
}
file.Close();
}
问题点数:120、回复次数:15Top
1 楼ttzzgg_80713(身无立锥地,常有四海心---老子有条命)回复于 2002-09-15 23:09:39 得分 0
为什么我的总是没有人回答,Top
2 楼xghome(东楼)回复于 2002-09-15 23:10:37 得分 0
gzTop
3 楼ccat(智拙)回复于 2002-09-15 23:28:21 得分 30
这个是用的IE的内核吗?我对VC不懂,见笑了。Top
4 楼ttzzgg_80713(身无立锥地,常有四海心---老子有条命)回复于 2002-09-15 23:30:43 得分 0
。原来兄台是位牛兄。失敬。。。失敬。Top
5 楼papaya_stone(^_^)shentong(^_^)回复于 2002-09-15 23:50:29 得分 0
你想要得到什么?网页上的所有链接吗?Top
6 楼ttzzgg_80713(身无立锥地,常有四海心---老子有条命)回复于 2002-09-16 00:06:54 得分 0
yeah.Top
7 楼ttzzgg_80713(身无立锥地,常有四海心---老子有条命)回复于 2002-09-16 00:20:33 得分 0
我头发都 快白了。Top
8 楼onestab()回复于 2002-09-16 00:31:39 得分 30
why don't you use IHTMLDocument2::get_anchors Method
to retrieve an interface pointer to a zero-based collection of all the A objects in an HTML document.Top
9 楼ttzzgg_80713(身无立锥地,常有四海心---老子有条命)回复于 2002-09-16 00:43:51 得分 0
let's try.Top
10 楼ttzzgg_80713(身无立锥地,常有四海心---老子有条命)回复于 2002-09-16 01:11:44 得分 0
if (SUCCEEDED(pDoc->get_anchors(&pItems)))
{
pItems->get_length(&p); // p == 0 ???
....
}Top
11 楼onestab()回复于 2002-09-16 01:54:28 得分 0
I neglect the Notes from MSDN:
The collection returns only anchor objects that have a
***name or id attribute *** value. If duplicate names are found, a collection of those named items is returned. Collections of duplicate names must be referenced subsequently by ordinal position.
it seems you have to get all elements and examine the anchors individualy.
Top
12 楼onestab()回复于 2002-09-16 01:55:39 得分 0
a useful link:
http://www.experts-exchange.com/Programming/Programming_Languages/MFC/Q_11654078.htmlTop
13 楼cker(〖烟波浩淼三千里、人鬼殊途五百年〗)回复于 2002-09-17 01:13:30 得分 30
if(pHTMLDocument)
{
IHTMLElementCollection *pAnchors = NULL;
if(SUCCEEDED(pHTMLDocument->get_all(&pAnchors)))
{
long ilHrefCount = 0;
if(SUCCEEDED(pAnchors->get_length(&ilHrefCount)))
{
long ilHrefIndex = 0;
for(; ilHrefIndex < ilHrefCount; ilHrefIndex++)
{
_variant_t vIndex;
vIndex.vt = VT_I4;
vIndex.lVal = ilHrefIndex;
IDispatch *pItem = NULL;
pAnchors->item(vIndex, vIndex, &pItem);
if(pItem != NULL)
{
IHTMLAnchorElement *pAnchor = NULL;
if(SUCCEEDED(pItem->QueryInterface(IID_IHTMLAnchorElement,
(LPVOID*)&pAnchor)))
{
_bstr_t bURL;
if(SUCCEEDED(pAnchor->get_href(&bURL)))
{
string s = W2A(bURL);
vector<string>::iterator it = find(vstrings.begin(),vstrings.end(),s);
if (it == vstrings.end() && s.length()>0)
vstrings.push_back(s);
}
pAnchor->Release();
}
pItem->Release();
}
}
}
pAnchors->Release();
}
}Top
14 楼congling(congling)回复于 2002-09-17 02:03:20 得分 30
一个使用JScript的方法,大可不必写VC的程序而且可以作为发布扩展和修改,虽然比较复杂,但是灵活掌握可以做到高扩展性,
文档中除了JSArrayToElementArray是从其他网站上,摘抄下来,其他都是我自己写的,其中JSObjectToAttributes花了我一天
的时间方试出来,这个函数我曾经花了200分在优快云上询问,无奈无人知晓
我打算专门为JScript和VC的互通性写一套库
本文档仅能使用在VS7.0的版本
VC-JScript:
HRESULT ExecuteScript(IHTMLWindow2* spWin,BSTR bstrScript,VARIANT *pvarRet)
{
HRESULT hr;
VARIANT var;
VariantInit(&var);
if(FAILED(hr=spWin->execScript(CComBSTR("eval(/"/");"),CComBSTR("javascript"),&var)))
return hr;
VariantClear(&var);
DISPID dispid;
CComBSTR bstrName("eval");
if(FAILED(hr=spWin->GetIDsOfNames(IID_NULL,
&bstrName,
1,
LOCALE_SYSTEM_DEFAULT,
&dispid))) return hr;
DISPPARAMS params;
CComVariant varRet;
memset(¶ms,0,sizeof(params));
params.cArgs=1;
params.rgvarg=&var;
var.vt=VT_BSTR;
var.bstrVal=bstrScript;
hr=spWin->Invoke(dispid,IID_NULL,0,DISPATCH_METHOD,¶ms,pvarRet,NULL,NULL);
return hr;
}
HRESULT ExecuteScript(IHTMLWindow2* spWin,LPCTSTR lpszScript,VARIANT *pvarRet)
{
return ExecuteScript(IHTMLWindow2* spWin,CComBSTR(lpszScript),VARIANT *pvarRet)
}
HRESULT ExecuteScript(IHTMLDocument2* spDoc,BSTR bstrScript,VARIANT *pvarRet)
{
HRESULT hr;
CComPtr<IHTMLWindow2> spWin;
if(FAILED(hr=spDoc->get_parentWindow(&spWin)))
return hr;
return ExecuteScript(spWin,bstrScript,pvarRet);
}
HRESULT ExecuteScript(IHTMLDocument2* spDoc,LPCTSTR lpszScript,VARIANT *pvarRet)
{
return ExecuteScript(spDoc,CComBSTR(lpszScript),pvarRet);
}
typedef CSimpleMap<CComBSTR,CComVariant> MapAttr;
HRESULT JSObjectToAttributes(IDispatch* pDisp,MapAttr& map)
//这个函数可以解释动态生成的JSObject的属性
{
CComPtr<ITypeInfo> spInfo;
HRESULT hr;
hr=pDisp->GetTypeInfo(0,LOCALE_SYSTEM_DEFAULT,&spInfo);
if(hr!=S_OK)return hr;
TYPEATTR* pTypeAttr;
hr=spInfo->GetTypeAttr(&pTypeAttr);
if(hr!=S_OK) return hr;
WORD cVars=pTypeAttr->cVars;
spInfo->ReleaseTypeAttr(pTypeAttr);
for(WORD i=0;i<cVars;i++)
{
VARDESC* pVarDesc;
if(spInfo->GetVarDesc(i,&pVarDesc)==S_OK)
{
MEMBERID memid=pVarDesc->memid;
spInfo->ReleaseVarDesc(pVarDesc);
UINT count;
CComBSTR bstrName;
if(spInfo->GetNames(memid,&bstrName,1,&count)==S_OK)
{
CComVariant var;
DISPPARAMS param;
memset(¶m,0,sizeof(param));
hr=pDisp->Invoke(memid,
IID_NULL,
LOCALE_SYSTEM_DEFAULT,
DISPATCH_PROPERTYGET,
¶m,
&var,
NULL,
NULL);
if(SUCCEEDED(hr))
map.Add(bstrName,var);
}
}
}
return S_OK;
}
HRESULT JSArrayToArray(IDispatch* pDisp,CSimpleArray<CComVariant>& arr)
//这个函数获取JSArray元素的函数,其实也可以从JSObjectToAttributes获得
{
HRESULT hr;
DISPPARAMS dispArgs= { NULL, NULL, 0, 0 };
CComVariant var;
hr = pDisp->Invoke( DISPID_NEWENUM,
IID_NULL,
LOCALE_SYSTEM_DEFAULT,
DISPATCH_PROPERTYGET,
&dispArgs,
&var,
NULL,
NULL );
if( FAILED( hr ))
return NULL;
if (var.vt != VT_UNKNOWN && var.vt != VT_DISPATCH)
return NULL;
CComQIPtr<IEnumVARIANT> pEnum( var.punkVal );
if( !pEnum )
return NULL;
hr = S_OK;
while( hr == S_OK )
{
CComVariant elemV;
hr = pEnum->Next( 1, &elemV, NULL );
if( elemV.vt != VT_EMPTY )// correct for dispproxy bug 19307
arr.Add(elemV);
else
hr=S_FALSE;
}
return S_OK;
}
针对你的问题
Javascript文件内容:
var hrefArray=new Array();
var col=document.all.tags("A");
for(var i=0;i<col.length;i++)
hrefArray[hrefArray.length]=col[i].href;
hrefArray
VC内容:
void CLeftView::GetAllRoom(IHTMLDocument2Ptr pDoc)
{
BSTR bstrScript=GetAllRoomScript();
CComVariant varJSArray;
if(SUCCEEDED(ExecuteScript(pDoc,bstrScript,&varJSArray)) && varJSArray.vt==VT_DISPATCH)
{
CSimpleArray<CComVariant> arrHref;
if(SUCCEEDED(JSArrayToArray(varJSArray.pdispVal,arrHref)))
{
//do what ever you want
}
}
}
本文讨论了如何使用VC++通过IHTMLDocument2接口遍历并获取HTML文档中的所有链接元素。涉及使用IHTMLLinkElement和IHTMLAnchorElement接口来处理链接,并提供了一种利用JScript进行元素收集的替代方案。
7616

被折叠的 条评论
为什么被折叠?



