求教取得基于frame结构的网页中控件的IHTMLDocument2接口并对控件进行某些操作(比如取文本域中的文本值)

信阳毛尖 许昌学院 码农、程序猿  2010-08-26 11:14:37
如题

对于form结构的,大致代码如下:
void CAboutIHTMLDocument2Dlg::OnBnClickedOk()
{
// TODO: 在此添加控件通知处理程序代码
HWND HWin = NULL;
USES_CONVERSION;

HWin=::FindWindowEx( NULL, NULL, "IEFrame", "2010年河南省高校门户网站评选 - Microsoft Internet Explorer"); //
if(HWin==NULL)
{
DWORD err=::GetLastError();
::AfxMessageBox("找不到指定窗口");
}


CoInitialize( NULL );
HINSTANCE hInst = ::LoadLibrary(_T("OLEACC.DLL"));
if ( hInst != NULL )
{
if( qqMailWin != NULL )
{
HWND hWndChild = NULL;
::EnumChildWindows(qqMailWin,EnumChildProc, (LPARAM)&hWndChild );
if ( hWndChild )
{
CComPtr<IHTMLDocument2> spDoc;
LRESULT lRes;

UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") );
::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*)&lRes );

LPFNOBJECTFROMLRESULT pfObjectFromLresult = (LPFNOBJECTFROMLRESULT)::GetProcAddress( hInst, (LPCSTR)"ObjectFromLresult" );
if( pfObjectFromLresult !=NULL )
{
HRESULT hr;
hr = pfObjectFromLresult( lRes,IID_IHTMLDocument2,0,(void**)&spDoc );


if ( SUCCEEDED(hr) )
{
// 获取各个控件
CComQIPtr < IHTMLElementCollection > spElementCollection;
hr = spDoc->get_forms(&spElementCollection);

long nFormCount=0; //取得表单数目
hr = spElementCollection->get_length( &nFormCount );
if (nFormCount==0)
::AfxMessageBox("表单数目为0");

for( long i=0;i<nFormCount;i++ )
{
IDispatch *pDisp = NULL; //取得第 i 项表单
hr = spElementCollection->item( CComVariant( i ), CComVariant(), &pDisp );
if ( FAILED( hr ) ) continue;

CComQIPtr < IHTMLFormElement > spFormElement = pDisp;
pDisp->Release();

long nElemCount=0; //取得表单中 域 的数目
hr = spFormElement->get_length( &nElemCount );
if ( FAILED( hr ) ) continue;


for(long j=0; j <nElemCount; j++)
{
CComDispatchDriver spInputElement; //取得第 j 项表单域
hr = spFormElement->item( CComVariant( j ), CComVariant(), &spInputElement );
if ( FAILED( hr ) ) continue;

CComVariant vName,vVal,vType; //取得表单域的 名,值,类型
hr = spInputElement.GetPropertyByName( L"name", &vName );
if( FAILED( hr ) ) continue;
hr = spInputElement.GetPropertyByName( L"value", &vVal );
if( FAILED( hr ) ) continue;
hr = spInputElement.GetPropertyByName( L"type", &vType );
if( FAILED( hr ) ) continue;

LPCTSTR strTextType= _T("text");


LPCTSTR strElementType = vType.bstrVal ? OLE2CT( vType.bstrVal ) : _T("NULL");
LPCTSTR strElementName = vName.bstrVal ? OLE2CT( vName.bstrVal ) : _T("NULL");
LPCTSTR strValue = vVal.bstrVal ? OLE2CT(vVal.bstrVal) : _T("NULL");

if( StrCmp( strTextType,strElementType) == 0)
{
if( StrCmp( strElementName, _T("UserName")))
{
::AfxMessageBox("找到指定输入框!!");
CComBSTR str = NULL;
CComQIPtr < IHTMLInputTextElement > spGetText(spInputElement); hr = spGetText->get_value(&str);
if( SUCCEEDED(hr) )
{
if( str.Length() != 0 )
{
CComBSTR msg=_T("输入框类容是:");
msg += str;
CString s( str );
::AfxMessageBox( s );
}
}
}
else
::AfxMessageBox("没有找到指定输入框!!");
}

}//for j


}//for i
}
}

}

}
::BringWindowToTop(qqMailWin);
::FreeLibrary( hInst );
}
CoUninitialize();
OnOK();
}

但是基于frame结构的我探索了很久,没有实现功能,
大致需要把上文红色字体的两句改为:
//CComQIPtr < IHTMLElementCollection > spElementCollection; 把原来的这一句换成下一句
CComQIPtr < IHTMLFramesCollection2 > spElementCollection;
//hr = spDoc->get_forms(&spElementCollection); 把原来的这一句换成下一句
hr = spDoc->get_frames(&spElementCollection);

接下来的..........
望高手们教我,谢谢

...全文
210 点赞 收藏 17
写回复
17 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
信阳毛尖 2010-08-29
[Quote=引用 11 楼 wy24789 的回复:]
怎么没用IHTMLFramesCollection2
[/Quote]

IHTMLFramesCollection2 是IHTMLDocument2::get_frames 函数的参数之一,这里根据大伙们的建议不需要用这种方法来访问嵌套的frame或者iframe,直接用getElementById()方法访问指定id的frame(iframe),返回的接口是IHTMLElement接口,把这个接口转化成IHTMLDocument2接口,最后通过这个frame(iframe)的IHTMLDocument2 访问frame(iframe)框架中的form中的控件即可
回复
信阳毛尖 2010-08-28
顺便再问一下:
IHTMLElement接口转化IHTMLDocument2接口可不可以直接这样:
CComQIPtr<IHTMLElement> pElem;
CComQIPtr<IHTMLDocument2> pDoc2;
pElem->QueryInterface(IID_IHTMLDocument,(void**)&pDoc2);

中间还需不需要什么过度?比如先转化到IHTMLWindow2接口,再用IHTMLWindow2接口的get_document()方法?

回复
信阳毛尖 2010-08-28
[Quote=引用 10 楼 jameshooo 的回复:]
多试几种方式。
既然iframe有name和id属性,就直接用IHTMLDocument2::getElementById方法。
如果还不行,就得检查这个IHTMLDocument2是不是所需页面的文档对象。
[/Quote]

谢谢提醒,用getElementById方法直接了当,一步到位了!现在我在想啊,用getElementById方法获取指定id的iframe 的IHTMLElement接口,再把IHTMLElement接口转化到此iframe的IHTMLDocument2接口,接下来是不是要通过此iframe的IHTMLDocument2接口寻找form呢?关于网页的知识不怎么懂,大侠们见笑啦
回复
信阳毛尖 2010-08-28
我觉得这样自己太不厚道了,决定对于最后一个问题重新发帖,新帖地址:http://topic.csdn.net/u/20100821/15/c637356b-7e25-4d3f-b27a-a47cb3b3e33f.html?64248
回复
信阳毛尖 2010-08-28
[Quote=引用 14 楼 jameshooo 的回复:]
不能直接转换,要经过中间转换:
IHTMLElement::QueryInterface ==> IHTMLFrameBase2
IHTMLFrameBase2::get_contentWindow ==> IHTMLWindow2
IHTMLWindow2::get_document ==> IHTMLDocument2
[/Quote]

感谢你的指导,整个问题已基本解决,可以实现功能了!!!好激动啊,呵呵,准备开溜到操场上和同学打球去。
再请教一个问题:如何判断用户单击了网页上的“submit”按钮??
回复
jameshooo 2010-08-28
不能直接转换,要经过中间转换:
IHTMLElement::QueryInterface ==> IHTMLFrameBase2
IHTMLFrameBase2::get_contentWindow ==> IHTMLWindow2
IHTMLWindow2::get_document ==> IHTMLDocument2
回复
信阳毛尖 2010-08-27
纠正:上文中的HWND HWin = NULL; 改为 HWND qqMailWin = NULL (测试网页就为qq写信那个网页)
回复
wy24789 2010-08-27
怎么没用IHTMLFramesCollection2
回复
hankcs 2010-08-27
感兴趣,等高人吧
回复
信阳毛尖 2010-08-27
等待......再等待.......
回复
jameshooo 2010-08-27
多试几种方式。
既然iframe有name和id属性,就直接用IHTMLDocument2::getElementById方法。
如果还不行,就得检查这个IHTMLDocument2是不是所需页面的文档对象。
回复
信阳毛尖 2010-08-27
翻了个错误,估计是坐在电脑边上时间长了,呵呵
应该是getElementsByTagName,函数记错了
回复
freelaxy 2010-08-27
研究FRAMESET/FRAME/IFRAME, CSDN是最好的去处了, 论坛主页是FRAMESET/FRAME结构的, 贴子窗口多个IFRAME.




=======================================================
FreeLaxy, your backup.
=======================================================
回复
信阳毛尖 2010-08-27
[Quote=引用 6 楼 jameshooo 的回复:]
get_frames不可靠,取不到东西是正常的
改成用IHTMLDocument3::getElementsByTagName来取,参数用"iframe"或者"frame"
[/Quote]

void CAboutIHTMLDocument2Dlg::OnBnClickedOk()
{
// TODO: 在此添加控件通知处理程序代码
HWND HWin = NULL;
USES_CONVERSION;

HWin=::FindWindowEx( NULL, NULL, "IEFrame", "2010年河南省高校门户网站评选 - Microsoft Internet Explorer"); //
if(HWin==NULL)
{
DWORD err=::GetLastError();
::AfxMessageBox("找不到指定窗口");
}


CoInitialize( NULL );
HINSTANCE hInst = ::LoadLibrary(_T("OLEACC.DLL"));
if ( hInst != NULL )
{
if( qqMailWin != NULL )
{
HWND hWndChild = NULL;
::EnumChildWindows(qqMailWin,EnumChildProc, (LPARAM)&hWndChild );
if ( hWndChild )
{
CComPtr<IHTMLDocument2> spDoc;
LRESULT lRes;

UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") );
::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*)&lRes );

LPFNOBJECTFROMLRESULT pfObjectFromLresult = (LPFNOBJECTFROMLRESULT)::GetProcAddress( hInst, (LPCSTR)"ObjectFromLresult" );
if( pfObjectFromLresult !=NULL )
{
HRESULT hr;
hr = pfObjectFromLresult( lRes,IID_IHTMLDocument2,0,(void**)&spDoc );


if ( SUCCEEDED(hr) )
{
CComPtr <IHTMLDocument3> pDoc3;
hr = spDoc->QueryInterface(IID_IHTMLDocument3,(void**)&pDoc3);
if ( hr == S_OK )
{
CComBSTR bstrName("iframe");
CComQIPtr<IHTMLElementCollection> pElemCollFrame;
hr = pDoc3->getElementsByName(bstrName,&pElemCollFrame);
if ( hr != S_OK ) return ;

long IframeLength;
hr = pElemCollFrame->get_length(&IframeLength);
}

单步执行的时候IframeLength的值为0,网页的源代码中:
<iframe src="/cgi-bin/today?sid=5_D7eHNtfpXiASBs" name="mainFrame" id="mainFrame" frameborder="no" scrolling="yes" hidefocus></iframe></div> <iframe name="leftFrame" id="leftFrame" src="javascript:'';" style="display:none"></iframe>
应该有两个,这是怎么回事呢?
回复
jameshooo 2010-08-27
get_frames不可靠,取不到东西是正常的
改成用IHTMLDocument3::getElementsByTagName来取,参数用"iframe"或者"frame"
回复
信阳毛尖 2010-08-26
大侠们快过来看看啊......
回复
jasonM2008 2010-08-26
没玩过,帮顶!
回复
相关推荐
发帖
VC/MFC
创建于2007-09-28

1.5w+

社区成员

VC/MFC相关问题讨论
申请成为版主
帖子事件
创建了帖子
2010-08-26 11:14
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……