MFC利用webbrowser控件实现简单的自动登陆

本文介绍如何在MFC应用中利用WebBrowser控件进行网页自动登录和交互。关键在于引入Mshtml.h头文件,通过GetHTMLElemCollDispatch获取元素Dispatch,执行click事件进行按钮点击,使用put_innerText设置输入框文字。同时,文章还提及了在网页加载完成后获取当前地址的方法,以及如何阻止新窗口的打开,实现链接点击后在当前窗口内导航。

用MFC 新建一个对话框工程,在界面上加入webbrowsr控件。

关键是要利用这个头文件 Mshtml.h


声明这几个函数:

    IHTMLElement*       GetHTMLElement(const CString& strID); //获取网页元素,通过ID  主要用来获得 button 和 text 控件
    IHTMLSelectElement* GetHTMLSelectElement(const CString& strID); //获取select 控件 元素
    IDispatch*          GetHTMLElemCollDispatch(const CString& strID);  //获取收集所有网页元素的Dispatch

这个函数具体实现

IDispatch* CHtmlClickDlg::GetHTMLElemCollDispatch(const CString& strID)
{
    HRESULT hr = S_OK;
    IDispatch* pDispath = NULL;
    IHTMLElement* pElem = NULL;

    pDispath = m_web.get_Document();         //m_web是CExplorer 也就是webbrowser控件

    if (pDispath == NULL)
    {
        TRACE(L"pDispath = m_web.get_Document() = NULL"); 
    }

    IHTMLDocument2* pDoc = NULL;
    hr = pDispath->QueryInterface(IID_IHTMLDocument2,(void**)&pDoc);
    pDispath->Release();
    pDispath = NULL;

    if(pDoc == NULL || hr != S_OK)
    {
        TRACE(L"IHTMLDocument2 pDoc  NULL or hr != S_OK");
        return NULL;
    }

    IHTMLElementCollection* pColl = NULL;
    hr = pDoc->get_all(&pColl);
    pDoc->Release();
    pDoc = NULL;

    ASSERT(pColl!=NULL);
    if( pColl==NULL || hr != S_OK)
    {
        TRACE(L"IHTMLElementCollection pColl = NULL or hr != S_OK");
        return NULL;
    }

    IDispatch* pDispath2 = NULL;

    VARIANT index = {0};
    V_VT(&index) = VT_I4;
    V_I4(&index) = 0;

    VARIANT varID = {0};
    VariantInit(&varID);
    varID.vt = VT_BSTR;

    varID.bstrVal = strID.AllocSysString();

    hr = pColl->item(varID,index,&pDispath2);
    pColl->Release();
    pColl = NULL;

    if(hr != S_OK)
    {
        TRACE(L"");
        pDispath2 = NULL;
    }

    return pDispath2;
}


这就可以通过GetHTMLElemCollDispatch函数来获得指定元素的Dispatch,用它来给定元素的接口

查询到IID_IHTMLElement的接口,把这个接口返回,后续用于执行click ,或者设置文字,这个可用于button,text控件,其他的可以查看那个头文件。

IHTMLElement* CHtmlClickDlg::GetHTMLElement(const CString& strID)
{
    HRESULT hr = S_OK;
    IDispatch* pDispath = NULL;
    IHTMLElement* pElem = NULL;

    pDispath = GetHTMLElemCollDispatch(strID);

    if(pDispath != NULL)
    {
        hr = pDispath->QueryInterface(IID_IHTMLElement,(void**)&pElem); // 查询到IID_IHTMLElement的接口,把这个接口返回,后续用于执行click ,或者设置文字

        if( hr != S_OK )
        {
            pElem = NULL;
        }
        pDispath->Release();
        
    }
    return pElem;
}


//这个可以用来获得select 下拉菜单控件的接口,当然都得使用到GetHTMLElemCollDispatch,有了接口就可以执行它内含的事件了。

IHTMLSelectElement* CHtmlClickDlg::GetHTMLSelectElement(const CString& strID)
{
    HRESULT hr = S_OK;
    IDispatch* pDispath = NULL;
    IHTMLSelectElement* pSelectElem = NULL;

    pDispath = GetHTMLElemCollDispatch(strID);

    if(pDispath != NULL)
    {
        hr = pDispath->QueryInterface(IID_IHTMLSelectElement,(void**)&pSelectElem);
        if( hr != S_OK )
        {
            pSelectElem = NULL;
        }
        pDispath->Release();
    }

    return pSelectElem;
}

这几个函数具体实例操作。

button 按钮点击 , 传入参数可以是控件的 id 或者 name,就用查询到的接口,调用它里面的click事件就可以实现自动点击了

void CHtmlClickDlg::OnWebClick(const CString& strID)
{
    HRESULT hr = S_OK;
    IHTMLElement* pElem = NULL;
    pElem = GetHTMLElement(strID);
    if (pElem != NULL)
    {
        hr = pElem->click();
        pElem->Release();
    }
    pElem = NULL;
}

设置text 控件中的文字, 用的是put_innerText这个事件。需要text控件的 id 或name,已经要填入的文本。

void CHtmlClickDlg::SetWebEditText(const CString& strID,const CString& strText)
{
    HRESULT hr = S_OK;
    IHTMLElement* pElem = NULL;
    pElem = GetHTMLElement(strID);
    if (pElem != NULL)
    {
        hr = pElem->put_innerText(strText.AllocSysString());
        pElem->Release();
    }
    pElem = NULL;
}


下拉菜单 select 控件的自动选择,控件id 或 name 是必须知道其中一个的,lindex 就是要选择下拉菜单的哪一项的编号,
void CHtmlClickDlg::OnWebSelect(const CString& strID, long lIndex)
{
    HRESULT hr = S_OK;
    IHTMLSelectElement* pSelectElem = NULL;
    pSelectElem = GetHTMLSelectElement(strID);
    if (pSelectElem != NULL)
    {
        hr = pSelectElem->put_selectedIndex(lIndex);
        pSelectElem->Release();
    }
    pSelectElem = NULL;
}

这里只是一个简单的介绍和应用,局限性很大。


补充一些内容:

m_strWebAddr = m_web.get_LocationURL();  //获取当前网页地址

这个可以放在webbrowser控件的事件 DocumentCompleteExplorer(LPDISPATCH pDisp, VARIANT* URL)  中来完成,这个事件是网页加载完毕后会调用,但是如果网页是动态一部分一部分加载的该函数就会被调用很多次。

在控件上点击一个连接,不去打开新的网页窗口的办法可以尝试用这个。

在webbrowser控件中添加事件,NewWindow3Explorer

void CHtmlClickDlg::NewWindow3Explorer(LPDISPATCH* ppDisp, BOOL* Cancel, unsigned long dwFlags, LPCTSTR bstrUrlContext, LPCTSTR bstrUrl)
{
    m_web.Navigate(bstrUrl,NULL,NULL,NULL,NULL);
    *Cancel = TRUE;
}

这里让控件去打开连接网站,并且避免打开新的窗口,就是给Cancel赋值为TRUE,即可实现,本地测试的是IE9

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值