Login dark
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>