VS2010 WEBBROWSER控制元件探索(一)
最近研究如何在視覺化程式中進行網路操作,對已有網頁進行些許控制,發現webbrowser控制元件是一個不錯的選擇,於是開始動手
一: 首先新建一個MFC對話方塊程式,新增webbrowser控制元件,其過程是在工具箱中右擊,點選選擇項按鈕
然後在COM元件中選擇Microsoft Web browser控制元件即可
這樣工具箱中就有了webbrowser 控制元件,將其拖放在對話方塊程式中即可,並生成了explorer1.h和explorer1.cpp檔案
二:現在開始對webbrowser控制元件進行操作
新增一個按鈕進行事件觸發,
這樣我們就可以瀏覽一個網頁了,但是對於網頁中內容進行操作,則必須在網頁載入完成之後進行,不能呼叫Navigate2之後,直接進行,這樣的操作是無效的!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之後使用!!!!!!!!!!!!!!! }
三:為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類中進行編輯,這樣是符合軟體工程原則的,具有較好的耦合性?