author: 零贰
title: vc自动填写表单应用
date: 2009-04-05 10:42:28
category: [编程代码]
tags: [VC,WEB,代码,源码,表单]
<p>文章中所讨论的技术应用范围其实还是比较广的,除了投票这种比较阴的应用,还可以完成比如自动填写表单、邮箱自动申请、网站注册等功能。</p>
这里提供的方法有两种: <!--more-->
feature: http://image.cool02.com/blogimages/code.jpg
方法1: 通过IE控件提供的COM接口实现。这种方法是通过IHTMLDocument2接口编辑网页表单(有时得修改网页代码),然后触发一个事件提交网页。 这种方法由于使用了IE控件,打开网页时会下载很多与应用无关的数据,如图片等(当然你可以在IE中把图片之类的选项关掉),效率很低,而且每投一票就得开一个IE控件,如果你的机子差些,等着按Reset吧~~。另外,这种方法编码比较多,挺烦。
方法2: 通过WinInet API来实现表单提交的工作。这种方法要比前面那种方法高明多了,不但执行效率高,耗资源少,而且具体实现起来也比上一种简单。
下面分别把两种方法介绍一下:
方法1:通过IE控件提供的COM接口实现
1、我的程序是基于对话框的,不是用的HtmlView,所以要先在对话框上放一个IE控件(Insert ActiveX Control,里面有一个Microsoft Web浏览器),给这个IE控件起个名字,比如m_ctrlWeb。另外要记着加上<mshtml.h>头文件,IE COM接口的东西都在里面放着。<comdef.h>和<atlbase.h>如果没有的话也要加上。
2、用ClassWizard加入DownloadComplete事件的响应,这样网页下载完了你就可以做填表单之类的工作了。当然你也可以在ProgressChange之类的事件中作这些操作了,不过这样你就得判断网页是不是差不多下载到合适的位置了,要图省事,直接用DownloadComplete算了。
3、下一步就是用这个控件打开目标网页了,什么时候打开你自己看着办,我是在InitDialog里面打开的,代码如下:
COleVariant vaUrl="http://www.onlytest.net";
m_ctrlWeb.Navigate2(&vaUrl, &vtMissing, &vtMissing, &vtMissing, &vtMissing);
其中那个vtMissing是用作缺省参数的。
4、然后就是主要的操作了。这些操作都放在OnDownloadCompleteExplorer里。为了方便,我写了几个函数用来完成特定的功能,在具体说明OnDownloadCompleteExplorer中进行的操作之前,先把这几个函数解释一下。
//功能:判断网页里是不是有strName指定的元素
//参数: pobjAllElement:网页中所有元素的集合
// strName:网页中元素的id或name
bool HasItem(IHTMLElementCollection pobjAllElement,CString strName)
{
CComPtr<IDispatch>pDisp;
pobjAllElement->item(COleVariant(strName),COleVariant((long)0),&pDisp);
if(pDisp==NULL)
return false;
else
return true;
}
//功能:在网页的文本框中输入字符串
//参数: pobjAllElement:网页中所有元素的集合
// strName:要编辑的文本框的id或name
// strText:要在文本框中写入的内容
void PutIEText(IHTMLElementCollection pobjAllElement,CString strName,CString strText)
{
CComPtr pDisp;
pobjAllElement->item(COleVariant(strName),COleVariant((long)0),&pDisp);
CComQIPtr pElement;
if(pDisp==NULL)
{
AfxMessageBox(strName + "没有找到!");
}
else
{
pElement=pDisp;
pElement->put_value(strText.AllocSysString());
}
}
//功能:提交一个网页的Form
//参数: pobjAllElement:网页中所有元素的集合
// strName:可以提交Form的按钮的id或name(也可以直接Form的submit提交)
void SubmitPage(IHTMLElementCollection pobjAllElement,CString strName)
{
CComPtrpDisp;
pobjAllElement->item(COleVariant(strName),COleVariant((long)0),&pDisp);
CComQIPtrpElement;
if(pDisp==NULL)
{
AfxMessageBox(strName + "没有找到!");
}
else
{
pElement=pDisp;
pElement->click();
}
}
//功能:选中网页中的一个CheckBox (其实就是点击)
//参数: pobjAllElement:网页中所有元素的集合
// strName:要选中的CheckBox的id或name
void CheckItem(IHTMLElementCollection pobjAllElement,CString strName)
{
CComPtr pDisp;
pobjAllElement->item(COleVariant(strName),COleVariant((long)0),&pDisp);
CComQIPtr<IHTMLElement, &IID_IHTMLElement>pElement;
if(pDisp==NULL)
{
AfxMessageBox(strName + "没有找到!");
}
else
{
pElement=pDisp;
pElement->click();
}
}
使用这几个函数可以很轻松地完成投票操作。下面列出OnDownloadCompleteExplorer中的代码。
另假设投票页面为http://www.onlytest.com/vote.htm,数据提交到http://www.onlytest.com /vote2.asp
void CVoteDlg::OnDownloadCompleteExplorer()
{
// TODO: Add your control notification handler code here
IHTMLElementCollection objAllElement=NULL;
IHTMLDocument2 objDocument=NULL;
CString strUrl,strTemp;
strUrl=m_ctrlWeb.GetLocationURL();//得到当前网页的URL
if(strUrl.IsEmpty())
return;
objDocument=(IHTMLDocument2 *)m_ctrlWeb.GetDocument(); //由控件得到IHTMLDocument2接口指针
objDocument->get_all(&objAllElement); //得到网页所有元素的集合
//由于所有页面下载完后都会执行这个函数,所以必须根据URL判断消息来源网页
if(strUrl=="http://www.onlytest.com/vote.htm")
{
CComPtr<IDispatch>pDisp;
if(HasItem(objAllElement,"voteform")==true) //voteform为投票选项所在的Form
{
objAllElement->item(COleVariant("voteform"),COleVariant((long)0),&pDisp);
CComQIPtr<IHTMLFormElement , &IID_IHTMLFormElement >pElement;
if(pDisp==NULL)
{
//接口指针获取失败,结束程序,不另外作处理,原因见后
EndDialog(IDOK);
return;
}
else
{
//如果投票结果在新窗口打开,则应该修改网页代码,让结果在本控件中显示
pElement=pDisp;
pElement->put_target(CComBSTR("_self")); //等效于target="_self"
pElement->put_action(CComBSTR("vote2.asp"));//等效于action="vote2.asp"
}
CheckItem(objAllElement,"chk2"); //将form中id为chk2的CheckBox选中
SubmitPage(objAllElement,"vote"); //提交网页,vote为submit按钮的id或name
}
}
else if(strUrl=="http://www.onlytest.com/vote2.asp")
{
EndDialog(IDOK); //如果投票处理页面已经下载完毕,则结束程序,原因见后。
}
} </p>