为什么调用IHTMLELEMENT的click方法会出异常? 为什么调用IHTMLELEMENT的click方法会出异常? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 还有我如何获得<a href="http://www.google.com">测试</a>这个链接中,“测试”二字如何能获得 】异常是你的Element是否正确取得· 象下面这样执行就会出异常CComQIPtr<IHTMLDocument2> pDoc2(GetHtmlDocument()); if ( pDoc2 ) { IHTMLElementCollection * pAllElem = NULL; IHTMLElement *pElem = NULL; pDoc2->get_links(&pAllElem); if( pAllElem != NULL ) { long p = 0; BSTR bstr; pAllElem->get_length(&p); for( int i = 0; i < p; i++) { if( pAllElem->item(_variant_t(0), _variant_t(0), (LPDISPATCH*)&pElem) == S_OK ) { pElem->click(); break; if( pElem != NULL ) { pElem->Release(); pElem = NULL; } } } pAllElem->Release(); pAllElem = NULL; } } name.lVal = i;IDispatch * pDispatch = NULL;objAllElement->item(name, name, &pDispatch);IHTMLElement* spElement = NULL;pDispatch->QueryInterface(IID_IHTMLElement, (void**)&spElement); 正常得很啊, 没异常啊<HTML> <HEAD> <TITLE> New Document </TITLE> </HEAD> <BODY> <a href="http://www.csdn.com" target="_blank">www.csdn.com</a> <br/> <a href="http://www.csdn.net" target="_blank">www.csdn.net</a> </BODY></HTML> CComQIPtr<IHTMLDocument2> pDoc2(GetHtmlDocument()); if( pDoc2 ) { CComPtr<IHTMLElementCollection> pColl; pDoc2->get_links(&pColl); LONG lCount = 0L; pColl->get_length(&lCount); for( LONG lIndex = 0L; lIndex < lCount; lIndex++) { _variant_t vIndex(0); _variant_t vOut; CComPtr<IDispatch> pDispatch; pColl->item( vIndex, vIndex, &pDispatch); CComQIPtr<IHTMLElement> pElem(pDispatch); if( pElem ) { pElem->click(); } } } 获取文字使用innerText属性 CComQIPtr<IHTMLDocument2> pDoc2(GetHtmlDocument()); if( pDoc2 ) { CComPtr<IHTMLElementCollection> pColl; pDoc2->get_links(&pColl); LONG lCount = 0L; pColl->get_length(&lCount); for( LONG lIndex = 0L; lIndex < lCount; lIndex++) { _variant_t vIndex(lIndex); _variant_t vOut; CComPtr<IDispatch> pDispatch; pColl->item( vIndex, vIndex, &pDispatch); CComQIPtr<IHTMLElement> pElem(pDispatch); if( pElem ) { CComBSTR bstrInnerText; pElem->get_innerText(&bstrInnerText); AfxMessageBox((LPCTSTR)bstrInnerText); } } } pAllElem->item(_variant_t(0), _variant_t(0), (LPDISPATCH*)&pElem) 语句获取的永远是集合中第一项,循环没有作用。异常的真正原因是,第一次循环得到第一个a元素,然后执行click方法,此时浏览器将会发生导航操作(通常情况下是这样,除非脚本截获了onclick事件,或者在新窗口打开链接),也就是说浏览器已经离开了当前页面,页面document对象会被锁定,后续的循环无法再次操作DOM。 CComPtr<IDispatch> pDispatch; pColl->item( vIndex, vIndex, &pDispatch);这样跟我写的有啥区别呢?为什么要用pDispatch获取呢? 你的item里面索引一直都是0,没有变化name.lVal = i; //i是for循环的值IDispatch * pDispatch = NULL;objAllElement->item(name, name, &pDispatch); 进入新浪的邮箱里,然后点击 写信 ,我怎么获得不了 邮件主题的的ihtmlElement元素呢?th>主题</th> <td><input name="subj" type="text" class="input inp_base" /></td> </tr> <tr> CComQIPtr<IHTMLDocument2> pDoc2(GetHtmlDocument()); if( pDoc2 ) { CComPtr<IHTMLElementCollection> pColl; pDoc2->get_links(&pColl); LONG lCount = 0L; pColl->get_length(&lCount); for( LONG lIndex = 0L; lIndex < lCount; lIndex++) { _variant_t vIndex(lIndex ); CComPtr<IDispatch> pDispatch; pColl->item( vIndex, vIndex, &pDispatch); CComQIPtr<IHTMLInputTextElement> pElem(pDispatch); if( pElem ) { pElem->click(); } } }我这获得,从来没有进入这条语句pElem->click();不知道为什么 右边的页面是在另一个iframe里面的 你这样获取是获取不到的。首先需要找到右边页面的框架 再在那个框架的窗口内去查找 晕,进不去不代表这是异常。IE的DOM中有很多集合类是不保险的,比如window.frames、document.links可能获取不到正确的结果,保险的做法是IHTMLDocument3::getElementsByTagName("A") wangjia184 为什么我获得不了 邮件 正文的元素呢? 下载个IE Development Toolbar, 看看它整个网页的结构吧。楼主又不给出代码,怎么知道你的代码出了什么问题呢? wangjia184 你好,跟我代码没关系,这个好像sina做的限制,你可否自己测试一下,确实获得不到,你可以在正文里输入 aaaaaaa然后看能否获得,我是获得不了,因为它不在textarea里生成的,是动态的 先去了解一下iframe框架再来下结论吧 iframe框架我都懂,网页结构不复杂,只是它的邮件正文是动态生成的,获取不了,不通过COM,我都获取不到,实验了,如果有高手可以尝试尝试 不管页面怎么用JS耍花枪, 最终如果要显示出来,必须符合HTML规范。JS也是createElement一个结点再将这个结点加入DOM树的也就是说, 你能看见的东西就一定是在DOM树里面。如果要限制的话,是不可能在JS里面实现的。因为必须是符合HTML要求的网页才能在浏览器里面显示检查你的代码:1. 你的代码执行的时候此元素是否已经创建了?2. 你的代码搜索结点是正确了吗?3. 你的代码取值是正确了吗? 谢谢楼上对我的帮助和支持,我是这样做的,我首先得到这个页面所有iframe,一共4个,然后我每个都去遍历,获取元素,设置元素的值,象邮件的标题和发件人等我都能找到和设置,但是邮件正文我怎么也获取不到,我发现邮件正文也是一个iframe,只是它是script动态生成的,我没有获取到这个元素,然后我又做了一个实验,我把邮件正文写成aaaaaa,然后我遍历4个iframe,然后获取body,再获取innerHTML、outHTML都没有获得aaaaaa这个值,所以邮件正文信息肯定不在这4个iframe里,那我该怎么做呢?请高手指教 找个DOM探测工具,一把就能探测出来,或者自己写一个,不复杂。 1. 那个iframe可能是嵌套在其它iframe里面的, 理论上iframe可以无限嵌套下去, 所以你可以用IE Development Toolbar查看一下文档结构。 你遍历iframe是采用递归遍历吗???2. 你的代码调用的时机可能不对,必须等到iframe加载完成后,里面有内容了 你才能取到。 你说的这些我都测试过,我遍历第2层iframe了,如果有时间就自己做做实验,如果那个高手能实现了,另送500分,期待jiangsheng帮忙 CComQIPtr<IHTMLDocument2> pDoc2(GetHtmlDocument()); CComQIPtr<IHTMLDocument3> pIframeMainBodyDoc3; CComQIPtr<IHTMLDocument2> pIframeMainBodyDoc2; if( pDoc2 ) { CComPtr<IHTMLFramesCollection2> pColl2; pDoc2->get_frames(&pColl2); if( pColl2 ) { LONG lCount = 0L; pColl2->get_length(&lCount); if( lCount > 0 ) { _variant_t vID(L"mainbody"); _variant_t vOut(NULL); pColl2->item( &vID, &vOut); CComQIPtr<IHTMLWindow3> pWnd3(vOut.pdispVal); CComQIPtr<IHTMLWindow2> pWnd2(vOut.pdispVal); if( pWnd3 ) { CComPtr<IHTMLDocument2> pIframeDoc2; pWnd2->get_document(&pIframeDoc2); pIframeMainBodyDoc3 = pIframeDoc2; pIframeMainBodyDoc2 = pIframeDoc2; } } } if( pIframeMainBodyDoc3 && pIframeMainBodyDoc2 ) { CComPtr<IHTMLElement> pElemSinaEditor; pIframeMainBodyDoc3->getElementById(_bstr_t("SinaEditor"), &pElemSinaEditor); CComQIPtr<IHTMLElement2> pElemSinaEditor2(pElemSinaEditor); if( pElemSinaEditor2 ) { CComPtr<IHTMLElementCollection> pIframeColl; pElemSinaEditor2->getElementsByTagName( _bstr_t("iframe"), &pIframeColl); if( pIframeColl ) { LONG lCount = 0L; pIframeColl->get_length(&lCount); for( int i = 0; i < lCount; i++) { _variant_t vIndex(i); CComPtr<IDispatch> pDispatch; pIframeColl->item( vIndex, vIndex, &pDispatch); CComQIPtr<IHTMLElement> pElem(pDispatch); if( pElem ) { CComBSTR bstrClassName; HRESULT hr = pElem->get_className(&bstrClassName); LPCTSTR lpszClsName = (LPCTSTR)bstrClassName; if( SUCCEEDED(hr) && lpszClsName && CString(_T("iframe")).CompareNoCase(lpszClsName) == 0 ) { CComBSTR bstrId; pElem->get_id(&bstrId); pColl2 = NULL; pIframeMainBodyDoc2->get_frames(&pColl2); if( pColl2 ) { _variant_t vID((LPCTSTR)bstrId); _variant_t vOut(NULL); pColl2->item( &vID, &vOut); CComQIPtr<IHTMLWindow2> pWnd2(vOut.pdispVal); CComQIPtr<IHTMLWindow3> pWnd3(vOut.pdispVal); if( pWnd2 && pWnd2 ) { CComPtr<IHTMLDocument2> pFinalIframeDoc2; pWnd2->get_document(&pFinalIframeDoc2); if( pFinalIframeDoc2 ) { m_pFinalIframeDoc2 = pFinalIframeDoc2; CComPtr<IHTMLElement> pBodyElem; m_pFinalIframeDoc2->get_body(&pBodyElem); if( pBodyElem ) { pBodyElem->put_innerHTML(_bstr_t(_T("<span style=\"color:red\">HAHAHAHA</span>"))); } } } } } } } } } } } 上面这段代码别放在 OnDocumentComplete 里面执行因为Sina的编辑器在加载后要进行初始化, 需要等待它初始化完成后 再设置否则你设置了,它会闪一下,然后被初始化代码冲掉了。你可以挂接框架里面的onload 事件,在事件到达后 再启动一个定时器,定时器去触发这个设置邮件正文的操作。你这程序再改改 就可以发垃圾邮件了。 用VC 如何获得 本机 Sqlserver 2000 的当前实例名称?? VC程序重启问题 窗口背景透明的方法 请问怎么检查一个时间字符串是正确的时间格式 菜鸟的问题~~~~~~~~~~~ 请教:非模态对话框的问题 急!!!! 怎样读写一个ini文件?? 如何实现可增长的内存映射文件 深圳的冬天,今天第一次感觉到拿着鼠标都觉得冷 居然直接从MSDN上拿下来的示范代码也会不好使?(解释必送分) 图形编程入门 vc++6.0补丁sp6的安装问题
CComQIPtr<IHTMLDocument2> pDoc2(GetHtmlDocument()); if ( pDoc2 )
{
IHTMLElementCollection * pAllElem = NULL;
IHTMLElement *pElem = NULL;
pDoc2->get_links(&pAllElem);
if( pAllElem != NULL )
{
long p = 0;
BSTR bstr;
pAllElem->get_length(&p);
for( int i = 0; i < p; i++)
{
if( pAllElem->item(_variant_t(0), _variant_t(0), (LPDISPATCH*)&pElem) == S_OK )
{
pElem->click();
break; if( pElem != NULL )
{
pElem->Release();
pElem = NULL;
}
}
}
pAllElem->Release();
pAllElem = NULL;
}
}
IDispatch * pDispatch = NULL;
objAllElement->item(name, name, &pDispatch);
IHTMLElement* spElement = NULL;
pDispatch->QueryInterface(IID_IHTMLElement, (void**)&spElement);
<HTML>
<HEAD>
<TITLE> New Document </TITLE>
</HEAD> <BODY>
<a href="http://www.csdn.com" target="_blank">www.csdn.com</a>
<br/>
<a href="http://www.csdn.net" target="_blank">www.csdn.net</a>
</BODY>
</HTML> CComQIPtr<IHTMLDocument2> pDoc2(GetHtmlDocument());
if( pDoc2 )
{
CComPtr<IHTMLElementCollection> pColl;
pDoc2->get_links(&pColl);
LONG lCount = 0L;
pColl->get_length(&lCount); for( LONG lIndex = 0L; lIndex < lCount; lIndex++)
{
_variant_t vIndex(0);
_variant_t vOut;
CComPtr<IDispatch> pDispatch;
pColl->item( vIndex, vIndex, &pDispatch); CComQIPtr<IHTMLElement> pElem(pDispatch);
if( pElem )
{
pElem->click();
}
}
}
CComQIPtr<IHTMLDocument2> pDoc2(GetHtmlDocument());
if( pDoc2 )
{
CComPtr<IHTMLElementCollection> pColl;
pDoc2->get_links(&pColl);
LONG lCount = 0L;
pColl->get_length(&lCount); for( LONG lIndex = 0L; lIndex < lCount; lIndex++)
{
_variant_t vIndex(lIndex);
_variant_t vOut;
CComPtr<IDispatch> pDispatch;
pColl->item( vIndex, vIndex, &pDispatch); CComQIPtr<IHTMLElement> pElem(pDispatch);
if( pElem )
{
CComBSTR bstrInnerText;
pElem->get_innerText(&bstrInnerText);
AfxMessageBox((LPCTSTR)bstrInnerText);
}
}
}
pColl->item( vIndex, vIndex, &pDispatch);
这样跟我写的有啥区别呢?为什么要用pDispatch获取呢?
IDispatch * pDispatch = NULL;
objAllElement->item(name, name, &pDispatch);
th>主题</th>
<td><input name="subj" type="text" class="input inp_base" /></td>
</tr>
<tr>
if( pDoc2 )
{
CComPtr<IHTMLElementCollection> pColl;
pDoc2->get_links(&pColl);
LONG lCount = 0L;
pColl->get_length(&lCount); for( LONG lIndex = 0L; lIndex < lCount; lIndex++)
{
_variant_t vIndex(lIndex );
CComPtr<IDispatch> pDispatch;
pColl->item( vIndex, vIndex, &pDispatch); CComQIPtr<IHTMLInputTextElement> pElem(pDispatch);
if( pElem )
{
pElem->click();
}
}
}我这获得,从来没有进入这条语句pElem->click();不知道为什么
IHTMLDocument3::getElementsByTagName("A")
JS也是createElement一个结点再将这个结点加入DOM树的
也就是说, 你能看见的东西就一定是在DOM树里面。如果要限制的话,是不可能在JS里面实现的。因为必须是符合HTML要求的网页才能在浏览器里面显示检查你的代码:
1. 你的代码执行的时候此元素是否已经创建了?
2. 你的代码搜索结点是正确了吗?
3. 你的代码取值是正确了吗?
1. 那个iframe可能是嵌套在其它iframe里面的, 理论上iframe可以无限嵌套下去, 所以你可以用IE Development Toolbar查看一下文档结构。
你遍历iframe是采用递归遍历吗???2. 你的代码调用的时机可能不对,必须等到iframe加载完成后,里面有内容了 你才能取到。
CComQIPtr<IHTMLDocument2> pDoc2(GetHtmlDocument());
CComQIPtr<IHTMLDocument3> pIframeMainBodyDoc3;
CComQIPtr<IHTMLDocument2> pIframeMainBodyDoc2;
if( pDoc2 )
{
CComPtr<IHTMLFramesCollection2> pColl2;
pDoc2->get_frames(&pColl2); if( pColl2 )
{
LONG lCount = 0L;
pColl2->get_length(&lCount); if( lCount > 0 )
{
_variant_t vID(L"mainbody");
_variant_t vOut(NULL);
pColl2->item( &vID, &vOut);
CComQIPtr<IHTMLWindow3> pWnd3(vOut.pdispVal);
CComQIPtr<IHTMLWindow2> pWnd2(vOut.pdispVal); if( pWnd3 )
{
CComPtr<IHTMLDocument2> pIframeDoc2;
pWnd2->get_document(&pIframeDoc2);
pIframeMainBodyDoc3 = pIframeDoc2;
pIframeMainBodyDoc2 = pIframeDoc2;
}
}
}
if( pIframeMainBodyDoc3 && pIframeMainBodyDoc2 )
{
CComPtr<IHTMLElement> pElemSinaEditor;
pIframeMainBodyDoc3->getElementById(_bstr_t("SinaEditor"), &pElemSinaEditor);
CComQIPtr<IHTMLElement2> pElemSinaEditor2(pElemSinaEditor);
if( pElemSinaEditor2 )
{
CComPtr<IHTMLElementCollection> pIframeColl;
pElemSinaEditor2->getElementsByTagName( _bstr_t("iframe"), &pIframeColl); if( pIframeColl )
{
LONG lCount = 0L;
pIframeColl->get_length(&lCount); for( int i = 0; i < lCount; i++)
{
_variant_t vIndex(i);
CComPtr<IDispatch> pDispatch;
pIframeColl->item( vIndex, vIndex, &pDispatch);
CComQIPtr<IHTMLElement> pElem(pDispatch); if( pElem )
{
CComBSTR bstrClassName;
HRESULT hr = pElem->get_className(&bstrClassName);
LPCTSTR lpszClsName = (LPCTSTR)bstrClassName; if( SUCCEEDED(hr) &&
lpszClsName &&
CString(_T("iframe")).CompareNoCase(lpszClsName) == 0 )
{
CComBSTR bstrId;
pElem->get_id(&bstrId); pColl2 = NULL;
pIframeMainBodyDoc2->get_frames(&pColl2);
if( pColl2 )
{
_variant_t vID((LPCTSTR)bstrId);
_variant_t vOut(NULL);
pColl2->item( &vID, &vOut);
CComQIPtr<IHTMLWindow2> pWnd2(vOut.pdispVal);
CComQIPtr<IHTMLWindow3> pWnd3(vOut.pdispVal);
if( pWnd2 && pWnd2 )
{
CComPtr<IHTMLDocument2> pFinalIframeDoc2;
pWnd2->get_document(&pFinalIframeDoc2); if( pFinalIframeDoc2 )
{
m_pFinalIframeDoc2 = pFinalIframeDoc2; CComPtr<IHTMLElement> pBodyElem;
m_pFinalIframeDoc2->get_body(&pBodyElem); if( pBodyElem )
{
pBodyElem->put_innerHTML(_bstr_t(_T("<span style=\"color:red\">HAHAHAHA</span>")));
}
}
}
}
}
}
} }
}
}
}
因为Sina的编辑器在加载后要进行初始化, 需要等待它初始化完成后 再设置
否则你设置了,它会闪一下,然后被初始化代码冲掉了。你可以挂接框架里面的onload 事件,在事件到达后 再启动一个定时器,定时器去触发这个设置邮件正文的操作。
你这程序再改改 就可以发垃圾邮件了。