1. 程式人生 > >VS2010 WEBBROWSER控制元件探索(一)

VS2010 WEBBROWSER控制元件探索(一)

最近研究如何在視覺化程式中進行網路操作,對已有網頁進行些許控制,發現webbrowser控制元件是一個不錯的選擇,於是開始動手

一:   首先新建一個MFC對話方塊程式,新增webbrowser控制元件,其過程是在工具箱中右擊,點選選擇項按鈕


    然後在COM元件中選擇Microsoft  Web browser控制元件即可


這樣工具箱中就有了webbrowser 控制元件,將其拖放在對話方塊程式中即可,並生成了explorer1.h和explorer1.cpp檔案

二:現在開始對webbrowser控制元件進行操作

        新增一個按鈕進行事件觸發,

void CVS_ONLINE_PAGEDlg::OnBnClickedTest()
{
	//測試使用函式	
	m_ie.Navigate2(COleVariant(L"http://www.trovigo.com/?ctid=CT3314958&octid=EB_ORIGINAL_CTID&SearchSource=55&CUI=&UM=2&UP=SP6345EA24-9871-452D-AACB-5426C0BE3743&SSPV="),NULL,NULL,NULL,NULL);//get_Document函式必須在網頁載入完成之後使用,也就是說不能直接在Navigate2之後使用!!!!!!!!!!!!!!!
}
這樣我們就可以瀏覽一個網頁了,但是對於網頁中內容進行操作,則必須在網頁載入完成之後進行,不能呼叫Navigate2之後,直接進行,這樣的操作是無效的!  

三:為webbrowser控制元件新增事件觸發處理程式,比如文件載入完成之後,進行某些操作,有兩種方式,一是利用嚮導來進行的

並選擇相應的事件進行處理


這樣就添加了事件處理過程可以做自己想要的操作,例項如下:



void CExplorer1::DocumentCompleteExplorer1(LPDISPATCH pIDisp, VARIANT* URL)
{
IWebBrowser2* pWb;
IHTMLDocument2* pDoc=NULL;
IDispatch* pDis;
HRESULT hr=pIDisp->QueryInterface(IID_IWebBrowser2,(void**)&pWb);
hr=pWb->get_Document(&pDis);
hr=pDis->QueryInterface(IID_IHTMLDocument2,(void**)&pDoc);
if(SUCCEEDED(hr))
{
long lCount=0;
IHTMLElementCollection*pCollection=NULL;
pDoc->get_all(&pCollection);
pCollection->get_length(&lCount);
for(long i=0;i<lCount;i++)
{
IHTMLElement*pElement=NULL;
VARIANT vItem;
vItem.vt=VT_I4;
vItem.intVal=i;
pCollection->item(vItem,CComVariant(),&pIDisp);
hr=pIDisp->QueryInterface(IID_IHTMLElement,(void**)&pElement);
if(SUCCEEDED(hr))
{
//設定編輯框內容
BSTR bstrId;
pElement->get_id(&bstrId);
if(bstrId!=NULL)
{
if(wcsstr(bstrId,L"q_top"))
{
pElement->put_innerText(L"DSADA");
MessageBox(L"找到編輯框了",L"提示",0);
}
}
//模擬點選按鈕

pElement->get_id(&bstrId);
if(bstrId!=NULL)
{
if(wcscmp(bstrId,L"button")==0)
{
MessageBox(L"找到按鈕了",L"提示",0);
pElement->click();
}
}

pElement->Release();
}
pIDisp->Release();
}
pIDisp->Release();
}

}

或者也可以進行手動操作,只是該方法是在Dlg中進行的

3.1首先在Dlg.h檔案中新增宣告DECLARE_EVENTSINK_MAP()

3.2在Dlg.cpp檔案中新增EVENT巨集BEGIN_EVENTSINK_MAP(CVS_ONLINE_PAGEDlg, CDialog)
{{AFX_EVENTSINK_MAP(CMFCHtmlDlg)
ON_EVENT(CVS_ONLINE_PAGEDlg, IDC_EXPLORER1, 259 /* DocumentComplete */, OnDocumentCompleteExplorerMain, VTS_DISPATCH VTS_PVARIANT)
}}AFX_EVENTSINK_MAP
END_EVENTSINK_MAP()

3.3新增事件處理函式

void CVS_ONLINE_PAGEDlg::OnDocumentCompleteExplorerMain(LPDISPATCH pDisp, VARIANT FAR* URL) 
{
	// TODO: Add your control notification handler code here
	HRESULT hr=0;
	IDispatch*				pIDisp			= NULL;
	pIDisp = m_ie.get_Document();
	IHTMLDocument2* pDoc=NULL;
	hr=pIDisp->QueryInterface(IID_IHTMLDocument2,(void**)&pDoc);
	if(SUCCEEDED(hr))
	{
		long lCount=0;
		IHTMLElementCollection*pCollection=NULL;
		pDoc->get_all(&pCollection);
		pCollection->get_length(&lCount);
		for(long i=0;i<lCount;i++)
		{
			IHTMLElement*pElement=NULL;
			VARIANT vItem;
			vItem.vt=VT_I4;
			vItem.intVal=i;
			pCollection->item(vItem,CComVariant(),&pIDisp);
			hr=pIDisp->QueryInterface(IID_IHTMLElement,(void**)&pElement);
			if(SUCCEEDED(hr))
			{
				//設定編輯框內容
				BSTR bstrId;
				pElement->get_id(&bstrId);
				if(bstrId!=NULL)
				{
					if(wcsstr(bstrId,L"q_top"))
					{
						pElement->put_innerText(L"DSADA");
						MessageBox(L"找到編輯框了",L"提示",0);
					}					
				}
				//模擬點選按鈕
				
				pElement->get_id(&bstrId);
				if(bstrId!=NULL)
				{
					if(wcscmp(bstrId,L"button")==0)
					{
						MessageBox(L"找到按鈕了",L"提示",0);
						pElement->click();
					}
				}
				
				pElement->Release();
			}
			pIDisp->Release();
		}
		pIDisp->Release();
	}

}

這樣基本過程就已經完了,現在說下原理,其實利用嚮導,和手動是一樣的,只是巨集過程的新增有程式來完成,

DECLARE_EVENTSINK_MAP巨集

使用DECLARE_EVENTSINK_MAP巨集在類宣告的末尾處,然後在定義.cpp檔案該成員為類函式,使用BEGIN_EVENTSINK_MAP巨集,將通知每個項
的巨集,事件,並宣告接收器末尾的END_EVENTSINK_MAP巨集的列表
BEGIN_EVENTSINK_MAP(CExplorer1, CWnd)//第二個是基類名稱


ON_EVENT(theClass,id,dispid,pfnHandler,vtsParam)
END_EVENTSINK_MAP()


theClass此事件接收器所對映所屬的類
id  OLE控制元件的ID
dispid 激發控制元件事件處理函式的訊息ID
pfnHandler 對該dispid事件處理的函式
vtsParam為時間指定引數序列

到此完成!

筆者覺得對於事件處理函式應該是在explorer.cpp或者說在CExplorer類中進行編輯,這樣是符合軟體工程原則的,具有較好的耦合性?