新建一个对话框程序,在上面放置一个WebBrowser的ActiveX控件,
该控件自动导航到下面这个网页:
<html>
<head>
<meta http-equiv=content-type content="text/html; charset=gb2312">
<title>个人中心登录</title>
</head>
<body>
<form action="https://passport.xxx.com/?login" method="POST">    <input type="hidden" name="tpl_ok" value="">
    <input type="hidden" name="next_target" value="">    <td width="56" class="f14">用户名:</td>
    <td width="156">
    <input type="text" name="username" id="username" value=""  class="ip"/>
    </td>    <td class="f14">密 码:</td>
    <td>
    <input type="password" name="password" value="" class="ip"/>
    </td>    <td class="f14">时间:</td>
    <td>
    <select name="time" id="time" >
          <option value="1d">一天</option>
          <option value="1w">一周</option>
          <option value="1m">一月</option>
          <option value="1s">一季</option>
    </select>
    </td>    <input type="submit" value=" 登录 "/></body>
</html>现在想把 姓名:王五
         密码:123
        时间:一天
用DOM自动赋值给表单,并操作表单自动提交。
请哪位前辈愿意花点时间帮我把完整的代码写一下,
网上的信息倒是不少,不过都是支离破碎的,对我这样的菜鸟来说真是难得看懂,
所以希望求得一个系统的sample。
万谢,明天再追加100分!!!

解决方案 »

  1.   

    webbrower应该有个大概叫GetDocument()的方法可以拿到IHtmlDocument2接口,然后看msdn吧,具体拿到每个元素后应该有set_value或是PutValue之类的方法
      

  2.   

    goto define WebBrowser
    看看有哪个接口适合你的要求
      

  3.   

    void CBroDlg::OnBnClickedButton1()
    {
    // TODO: 在此添加控件通知处理程序代码
    HRESULT hr;
    IWebBrowser2 *m_pBrowser;
    IUnknown *pUnknown= m_Bro.GetControlUnknown();
    pUnknown->QueryInterface(&m_pBrowser);
      
    CComPtr < IDispatch > spDispDoc;
    m_pBrowser->get_Document(&spDispDoc); CComQIPtr< IHTMLDocument2 > spDocument2 = spDispDoc; //spDocument2->put_bgColor( CComVariant( "green" ) );
        CComQIPtr< IHTMLElement > spElement ;
    hr = spDocument2->get_body(&spElement); CComQIPtr< IHTMLElementCollection > spElementCollection;
    hr = spDocument2->get_forms( &spElementCollection ); //取得表单集合
    if ( FAILED( hr ) )
    {
    MessageBox(_T("获取表单的集合 IHTMLElementCollection 错误"));
    return;
    }    long nFormCount=0; //取得表单数目
    hr = spElementCollection->get_length( &nFormCount );
    if ( FAILED( hr ) )
    {
    MessageBox(_T("获取表单数目错误"));
    return;
    }

    CString xx(_T(""));
    for(long i=0; i<nFormCount; i++)
    {
    IDispatch *pDisp = NULL; //取得第 i 项表单
    hr = spElementCollection->item( CComVariant( i ), CComVariant(), &pDisp );
    if ( FAILED( hr ) ) continue; // CComQIPtr< IHTMLElement > spElement = pDisp;
    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 lpName = vName.bstrVal?
    OLE2CT( vName.bstrVal ) : _T("NULL"); //未知域名
    LPCTSTR lpVal  = vVal.bstrVal?
    OLE2CT( vVal.bstrVal  ) : _T("NULL"); //空值,未输入
    LPCTSTR lpType = vType.bstrVal?
    OLE2CT( vType.bstrVal ) : _T("NULL"); //未知类型 // LPCTSTR aaa;
    //…… DWORD dwMinSize;
    dwMinSize = WideCharToMultiByte(CP_ACP,NULL,lpName,-1,NULL,0,NULL,FALSE); //计算长度
    char *bbb= new char[dwMinSize]; WideCharToMultiByte(CP_OEMCP,NULL,lpName,-1,bbb,dwMinSize,NULL,FALSE); CString xxx=_T("_fmm.j._0.l");
                
                  //      DWORD dwMinSize;
    dwMinSize = WideCharToMultiByte(CP_ACP,NULL,xxx,-1,NULL,0,NULL,FALSE); //计算长度
    char *ccc= new char[dwMinSize]; WideCharToMultiByte(CP_OEMCP,NULL,xxx,-1,ccc,dwMinSize,NULL,FALSE); int x=strcmp(bbb,ccc);
    if(x==0)
    {
    CComVariant v;
    v=CComVariant( _T("BillGates"));
    hr = spInputElement.PutPropertyByName( L"value", &v );
    if( FAILED( hr ) ) continue; LPCTSTR lpVal  = vVal.bstrVal?
    OLE2CT( vVal.bstrVal  ) : _T("NULL");
    MessageBox(lpVal);
    }
      
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    dwMinSize = WideCharToMultiByte(CP_ACP,NULL,lpType,-1,NULL,0,NULL,FALSE); //计算长度
    char *ppp= new char[dwMinSize]; WideCharToMultiByte(CP_OEMCP,NULL,lpType,-1,ppp,dwMinSize,NULL,FALSE); CString qqq=_T("submit");
                
                  //      DWORD dwMinSize;
    dwMinSize = WideCharToMultiByte(CP_ACP,NULL,qqq,-1,NULL,0,NULL,FALSE); //计算长度
    char *ooo= new char[dwMinSize]; WideCharToMultiByte(CP_OEMCP,NULL,qqq,-1,ooo,dwMinSize,NULL,FALSE); int xy=strcmp(ppp,ooo);
    if(xy==0)
    {
    // CComDispatchDriver spSubmitElement; //取得第 j 项表单域
    //  hr = spElement->item( CComVariant( j ), CComVariant(), &spSubmitElement );
    spElement=spFormElement;
    if ( FAILED( hr ) ) continue;
     spElement->click(); ////////////////////////////////为什么没起作用????????????????????
    } CString yy(_T(""));
    yy.Format(_T("[ %s ]  %s = %s \r\n"),lpType,lpName,lpVal );
    xx+=yy;

    }
    MessageBox(xx); //想提交这个表单吗?删除下面语句的注释吧
    //spFormElement->submit();
    }
    }
    大家帮我看看我写的代码有什么问题,问号那个地方为什么没起作用??
      

  4.   

    spElement=spFormElement;
    spElement->click();
    ====================
    Form元素点击是没有意义的,可以找到Submit元素执行click,或者直接调用Form.submit方法
      

  5.   

    谢谢你仔细地帮我检查,之后我也发现了,调整后就OK了。然后我把上面OnButton1()里的代码全部换成下面的,也就是不用IHTMLDocument2,而用了IHTMLDocument3,但是在getElementByID之后,不知道怎么复制给value,也没有PutPropertyByName方法,不知道还怎么弄?
    另外IHTMLDociment2和IHTMLDocument3有什么区别呢? HRESULT hr;
    IWebBrowser2 *m_pBrowser;
    IUnknown *pUnknown= m_Bro.GetControlUnknown();
    pUnknown->QueryInterface(&m_pBrowser);
      
    CComPtr < IDispatch > spDispDoc;
    m_pBrowser->get_Document(&spDispDoc); CComQIPtr< IHTMLDocument3 > spDoc3 = spDispDoc;    CComQIPtr< IHTMLElement > spElement ; BSTR ID;
    ID=_T("usrname");
    hr=spDoc3->getElementById(ID,&spElement);
    if( FAILED(hr)) return;
    CComVariant v;
    v=CComVariant( _T("BillGates"));
    hr = spElement.PutPropertyByName( L"value", &v );//试图在这里赋值,但是IHTMLElement没有PutPropertyByName这个方法,该怎么办呢? ID=_T("submit");
    hr=spDoc3->getElementById(ID,&spElement); if( FAILED(hr)) return;
    spElement->click();
      

  6.   

    CComDispatchDriver与CComPtr/CComQIPtr是不同的封装,前者是MFC对IDispatch的封装类,后两者是智能指针封装,PutPropertyByName是MFC封装类提供的方法,不适用于智能指针,可以使用spElement->put_value/put_name来代替。
    IHTMLDocument3是对IHTMLDocument2的扩展,添加了一些新的属性和方法,此外还有IHTMLDocument4,这些接口直接可以互相查询得到。
      

  7.   

    但是编译器提示spElement没有put_value/put_name两个方法啊?
      

  8.   

    这要看编译器是如何生成所有接口的包装类的,可能是put_value,也可能是Putvalue,也可能是Setvalue,查查包装类中接口的方法定义
      

  9.   


    我做了下面的调整就OK了,但是遇到了个诡异的问题:如果只声明一个spElement,只能使用一次,后面的再使用就报错,但是分别声明一个来用,就没有问题,这是为何,怎么解决?
        HRESULT hr;
    CComQIPtr< IHTMLDocument3 > spDoc3 = m_Bro.get_Document();
        CComQIPtr< IHTMLElement > spElement ,spSubElement ,sp; //这个地方为什么必须声明三个,依次对应下面三项ID,为什么只用一个spElement就会运行时报错?
    CComQIPtr< IHTMLInputElement > spInputElement ; BSTR ID,v;
    //////////////////////////////////////////////////////////////////////////////
    ID=_T("loginid");
    v=_T("BillGates"); hr=spDoc3->getElementById(ID,&spElement);
    if( FAILED(hr)) return;
    spInputElement=spElement;
    spInputElement->put_value(v);
    /////////////////////////////////////////////////////////////////////////////
    ID=_T("password");
    v=_T("123456"); hr=spDoc3->getElementById(ID,&sp);
    if( FAILED(hr)) return;
    spInputElement=sp;
    spInputElement->put_value(v);
    /////////////////////////////////////////////////////////////////////////////
    ID=_T("submit"); hr=spDoc3->getElementById(ID,&spSubElement);
    if( FAILED(hr)) return;
    spSubElement->click();
      

  10.   

    在循环里面吗?如果是,可以把变量申明到循环体里面去,或者每次循环中要使用前先执行Release释放旧的接口指针。
      

  11.   

    噢,对的,用Release释放就没问题了。