亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

掛接瀏覽器事件

系統(tǒng) 1754 0

前幾天在《 一個(gè)基于 MFC 的自動(dòng)化 (Automation) 實(shí)例 》上說(shuō)最近會(huì)發(fā)一個(gè)關(guān)于如何掛接瀏覽器事件的教程,現(xiàn)在如期兌現(xiàn)承諾啦。說(shuō)實(shí)話,解決這個(gè)問(wèn)題花了我近一年的時(shí)間,雖然期間不是每天都在想這個(gè)問(wèn)題,但無(wú)論如何這聽起來(lái)絕對(duì)是一段不短的時(shí)間!也許因?yàn)槲沂巧锵档陌桑荒芟裼?jì)算機(jī)系的朋友那樣有那么多現(xiàn)成的資源可以利用,一切都靠自學(xué),碰到不懂的問(wèn)題就在浩瀚的網(wǎng)絡(luò)世界中尋找答案,有時(shí)候的確感到很孤獨(dú)!

人生最大的痛苦莫過(guò)于有了問(wèn)題沒(méi)有答案,有了答案又沒(méi)有 Money !毫不客氣的說(shuō)一句,中國(guó)在“開源”方面做的的確不咱的 ~ 一點(diǎn)點(diǎn)小的成就就希望把它轉(zhuǎn)變成大把大把的金錢,結(jié)果呢,正如大家看到的,中國(guó)菜鳥的死亡率要明顯高于美國(guó)(因?yàn)橹袊?guó)的菜鳥在成長(zhǎng)為肉鳥的過(guò)程中需要付出太多的 ¥,嘿嘿 ~ )。

當(dāng)然,我并不崇洋媚外,相反,我覺得自己更像是個(gè)“憤青”。我說(shuō)中國(guó)的“開源”做的不好那是事實(shí),沒(méi)什么好爭(zhēng)論的。而我之所以沒(méi)有淪落為“崇洋派”是因?yàn)槲易⒁獾搅似渲械臐撆_(tái)詞:“在當(dāng)前國(guó)情下, ….. ”。現(xiàn)在的中國(guó)人雖然早已不像六七十年代時(shí)那么貧苦,但也不見得就衣食無(wú)憂。既如此,那么想掙點(diǎn)錢養(yǎng)家糊口的想法也就很正常拉。這就是中國(guó)開源做的不好的原因。而如果我本身就有 1000 萬(wàn),我又怎么會(huì)在乎那么個(gè)小程序所帶來(lái)的利潤(rùn)?這就是美國(guó)的開源為什么做的好的原因。有些朋友可能會(huì)反駁,美國(guó)人最近也不好過(guò)啊,金融危機(jī)弄的人心慌慌的 ~ 哈,對(duì)啊,這就是“沃爾瑪”踩踏事件發(fā)生的原因。前些天還在看網(wǎng)友對(duì)“重慶家樂(lè)福踩踏事件”的評(píng)論呢,哎呀,說(shuō)什么中國(guó)人劣根性啊,中國(guó)人愛貪小便宜的啊,那叫一個(gè)多 ~ 當(dāng)然,中國(guó)人民一向勤勞、善良,而我做為一個(gè)自豪于祖國(guó)五千年?duì)N爛文明的普通中國(guó)人自然是不會(huì)去說(shuō)美國(guó)人怎么劣根性啦,我只是想揭露這樣一個(gè)事實(shí):人與人,種族與種族,國(guó)家與國(guó)家之間是沒(méi)有什么本質(zhì)上的區(qū)別的,全民素質(zhì)的不同是基于不同的基本國(guó)情的。當(dāng)把所有人都置入一個(gè)相同的環(huán)境中,其基本表現(xiàn)是相同的。正如這次金融危機(jī),不就是近似的把中國(guó)人和美國(guó)人置入了一個(gè)同等的環(huán)境?那么,他們的表現(xiàn)有不同嗎?

時(shí)刻記住這句潛臺(tái)詞,那么你對(duì)國(guó)家的現(xiàn)狀將會(huì)有一個(gè)理性的解讀。就拿“開源”這件事來(lái)說(shuō),人家肯免費(fèi)給你那自然是人家的深明大意,而人家要收費(fèi)呢那很正常,沒(méi)什么可以值得批判的。如果你真的對(duì)此看不過(guò)去,那么你就應(yīng)該踏踏實(shí)實(shí)的多為國(guó)家做點(diǎn)事,幫助國(guó)家快速發(fā)展。等國(guó)家富裕了,開源自然也就做好了。正如我上面所說(shuō),基本國(guó)情將決定全名素質(zhì)。而我決定免費(fèi)公開我的文章,那并不是說(shuō)我有多高尚,而是因?yàn)槲也辉诤踹@么點(diǎn)錢(哈,是虛擬幣啦),如果有一天,我混到流落街頭了,大家說(shuō)我還會(huì)這么偉大嗎?必竟連都說(shuō)人的基本需求之一是生理需求啊(說(shuō)白了就是民以食為天嘛 ~ 嘿嘿)。

扯哪去都不知道了 哈哈 也不知道今天哪來(lái)這么多感慨,回歸正題吧 ~ 當(dāng)你決定看這篇文章的時(shí)候我已假設(shè)你具備了以下知識(shí): ①掌握了 COM 的一些基本知識(shí),如連接點(diǎn),接收器等 ; ②具有一定的 MFC 編程經(jīng)驗(yàn),了解 MFC 接收器( Sink )的內(nèi)部實(shí)現(xiàn) ; ③了解 HTML 的基礎(chǔ)知識(shí) ; ④對(duì) IE 內(nèi)部接口有一定的了解 ( IWebBrowser2, IHTMLDocument2 )

本文通過(guò)一個(gè) MFC 對(duì)話框程序?qū)崿F(xiàn)的接收器達(dá)到掛接 IE 事件的目的。在 Visual stdio2008 IE 8.0 下測(cè)試通過(guò)。用 VC6.0 的朋友需將 Microsoft SDK 更新成 6.0

另外,推薦大家看一篇 MSDN 上的文章 ( Handling HTML Element Events ) ,雖然是英文,看起來(lái)會(huì)有點(diǎn)吃力,但大家一定要學(xué)會(huì)看 MSDN ,有什么人會(huì)比生產(chǎn)商更了解產(chǎn)品的內(nèi)部實(shí)現(xiàn)呢?看完之后,你就會(huì)底氣十足的說(shuō) ”I CAN DO IT!” 。別猶豫拉,我四級(jí)都考 N 次拉 ( 不知道這次有沒(méi)有過(guò), a meng~~~) ,不照樣看 ~

首先給大家介紹一下程序?qū)崿F(xiàn)的流程 : 利用 MFC 完成接收器 (CSink) 的編寫 -> 獲得 IWebBrowser2 接口 ->…-> 獲得 IHTMLElement 接口指針 -> 調(diào)用 AfxConnectionAdvise 實(shí)現(xiàn)接收器與連接點(diǎn)的連接 -> 響應(yīng)事件。

接下來(lái)一步步實(shí)現(xiàn)上述步驟 :

第一步: 建立一個(gè) MFC 對(duì)話框工程,工程名為 HandleEvent ,注意選上自動(dòng)化支持 -> 添加新類 CSink 使其繼承自 CCmdTarget( 此基類實(shí)現(xiàn)了 IDispatch), 并選上自動(dòng)化支持 (Automation) 。完成這些之后這個(gè)類其實(shí)就是一個(gè) Sink 啦,當(dāng)然,到目前為止它不具有任何的功能。

下面為這個(gè)接收器添加事件處理函數(shù),分兩步:

1. sink.cpp 中的 BEGIN_DISPATCH_MAP(CSink, CCmdTarget) END_DISPATCH_MAP() 之間間加入 DISP_FUNCTION_ID(CSink,"onclick",DISPID_HTMLELEMENTEVENTS2_ONCLICK,OnClick,VT_VARIANT,VTS_DISPATCH)

2. sink.h 中加入 OnClick 的實(shí)現(xiàn) :

BOOL CSink::OnClick(IHTMLEventObj *pEvtObj)

{

::AfxMessageBox(L "Button clicked!" );

return TRUE;

}

注意:請(qǐng)?jiān)? sink.h 中包含 :mshtml.h mshtmdid.h

至此我們已經(jīng)完成了一個(gè)接收器該做的所有事,下面說(shuō)說(shuō)這兩步的內(nèi)含 : 前面已經(jīng)說(shuō)過(guò), CCmdTarget 類已經(jīng)實(shí)現(xiàn)了 IDispatch 接口,當(dāng)通過(guò) AfxConnectionAdvise() 將連接點(diǎn)和接收器連接之后,當(dāng)有事件發(fā)生時(shí),連接點(diǎn)將調(diào)用 CCmdTarget CSink )的 Invoke() 函數(shù),這是在外部。而在內(nèi)部, CCmdTarget Invoke 的調(diào)用映射到 DISPATCH_MAP 上,在其上查找有無(wú)與當(dāng)前事件的 DISPID 對(duì)應(yīng)的處理函數(shù)。比如當(dāng)發(fā)生 onclick 事件時(shí),連接點(diǎn)將調(diào)用 Invoke(..,DISPID_HTMLELEMENTEVENTS2_ONCLICK,…) ,而在 CCmdTarget 內(nèi)部,它會(huì)在 DISPATCH_MAP 上尋找有沒(méi)有 DISPID= DISPID_HTMLELEMENTEVENTS2_ONCLICK 的處理函數(shù)。如果有則再將事件映射到 OnClick 上。

MSDN 中有這么一段供參考:

Handling Events using MFC

* The MFC CCmdTarget class implements the IDispatch interface, which means that any class derived from this class can implement an event sink. The IDispatch feature requires a call to the CCmdTarget::EnableAutomation method.

* The MFC AfxConnectionAdvise and AfxConnectionUnadvise functions find a specified connection point and then advise or unadvise appropriately.

* The DECLARE_DISPATCH_MAP, BEGIN_DISPATCH_MAP, DISP_FUNCTION, DISP_FUNCTION_ID and END_DISPATCH_MAP macros are used to map each event method to your event handler function.

* When handling events from a Microsoft ActiveX control you are hosting in your MFC applications, use the DECLARE_EVENTSINK_MAP, BEGIN_EVENTSINK_MAP, ON_EVENT and END_EVENTSINK_MAP macros.

* If you are hosting the WebBrowser Control on a dialog box, you can use the Microsoft Visual C++ ClassWizard to map events to event handlers.

* The MFC CHtmlView class hosts the WebBrowser Control and provides overridable methods for the WebBrowser Control events.

第二步: 獲得 IWebBrowser2 接口。能看這篇文章的朋友不應(yīng)該不熟悉這個(gè)接口吧?它的獲取有多種方式,如果真的不知道,那就直接用基于 CHtmlView 的單文檔程序,嘿嘿,夠直接了吧 ~ 在本例中,通過(guò)一個(gè)對(duì)話框程序獲得 IE 瀏覽器中的 IWebBrowser2 接口的,由于實(shí)現(xiàn)較復(fù)雜,用到了 ”oleacc.dll” ,如果討論太多會(huì)偏離主題,因此在第三步中只將代碼貼出,有興趣的朋友可以研究一下,如有不懂,我或許可以再出一篇教程。

第三步: 通過(guò)函數(shù) GetIHTMLElement(IWebBrowser2 *pwb2) 獲得 IHTMLElement 接口指針,由于這些都是平時(shí) IE 編程的基礎(chǔ)這里就不多說(shuō)拉:

本例中使用到的 html 文件的代碼如下 :

<button>CLICK ME!</button>

哈哈,別懷疑撒,就是這么一句話 ~ 當(dāng)然這是為了測(cè)試的方便,否則我就太對(duì)不起我 PHP 程序員的稱號(hào)啦 ~~

以下是 GetIHTMLElement 的實(shí)現(xiàn)代碼,注意 獲取 Internet Explorer_Server 句柄 這部分是針對(duì) IE8.0 的,如果是另外瀏覽器當(dāng)然也可以,不過(guò)就請(qǐng)你自己獲取吧,過(guò)程差不多啦!另外請(qǐng)?jiān)? HandleEventDlg.h 中包含 :atlbase.h,oleacc.h

IHTMLElement* CHandleEventDlg::GetIHTMLElementPoint()

{

// 獲取 Internet Explorer_Server 句柄

HWND hIEFrame=::FindWindow("IEFrame",NULL);

HWND hFrameTab=::FindWindowEx(hIEFrame,NULL,"Frame Tab",NULL);

HWND hTabWindowClass=::FindWindowEx(hFrameTab,NULL,"TabWindowClass",NULL);

HWND hShellDocObjectView=::FindWindowEx(hTabWindowClass,NULL,"Shell DocObject View",NULL);

HWND hExplorer_Server=::FindWindowEx(hShellDocObjectView,NULL,"Internet Explorer_Server",NULL);

//CString str;

//str.Format("%d",hExplorer_Server);

//::AfxMessageBox(str);

// 獲取 IHTMLDocument2 接口

CComQIPtr<IHTMLDocument2>hd2;

UINT uMsg;

uMsg=::RegisterWindowMessage(_T("WM_HTML_GETOBJECT"));

LRESULT lRes;

::SendMessageTimeout(hExplorer_Server,uMsg,0L,0L,SMTO_ABORTIFHUNG,1000,(DWORD*)&lRes);

HINSTANCE hDll=::LoadLibrary(_T("OLEACC.dll"));

LPFNOBJECTFROMLRESULT pfObjectFromLresult=(LPFNOBJECTFROMLRESULT)::GetProcAddress(hDll,"ObjectFromLresult");

pfObjectFromLresult(lRes,IID_IHTMLDocument2,0,(LPVOID*)&hd2);

CComVariant color("black");

hd2->put_bgColor(color);

::FreeLibrary(hDll);

///////////////////////////////////////////////////////////////////////////////////////

CComQIPtr<IHTMLElementCollection>hec;

LRESULT hr=NULL;

CComQIPtr<IHTMLElementCollection>pElemColl;

hd2->get_all(&pElemColl);

IDispatch* pElemDisp = NULL;

IHTMLElement* pElem = NULL;

VARIANT varID,varIdx;

varID.vt=VT_I4;

varID.lVal=0;

varIdx.vt=VT_I4;

varIdx.lVal=0;

hr = pElemColl->item(varID, varIdx, &pElemDisp);

hr = pElemDisp->QueryInterface(IID_IHTMLElement, (void**)&pElem);

return pElem;

}

第四步: 調(diào)用 AfxConnectionAdvise 實(shí)現(xiàn)接收器與連接點(diǎn)的連接。在對(duì)話框中加入一個(gè) Button, 添加 LBUTTONDOWN 事件,我們將在這里實(shí)現(xiàn)兩者的連接,請(qǐng)?jiān)? HandleEventDlg.h 中加入 CSink *m_pSink,DWORD m_dwCookie 代碼如下:

void CHandleEventDlg::OnConnect()

{

m_pElem=GetIHTMLElementPoint();

m_pSink=new CSink();

LPUNKNOWN pUnkSink=m_pSink->GetIDispatch(FALSE);

if(!::AfxConnectionAdvise(m_pElem,DIID_HTMLElementEvents2,pUnkSink,FALSE,&m_dwCookie))

{

::AfxMessageBox(" 連接失敗! ");

}

else

{

::AfxMessageBox(" 連接成功!請(qǐng)點(diǎn)擊按鈕測(cè)試! ");

}

}

第五步: OnDestroy() 進(jìn)行垃圾回收:

void CHandleEventFromIEDlg::OnDestroy()

{

CDialog::OnDestroy();

// TODO: 在此處添加消息處理程序代碼

LPUNKNOWN pUnkSink=m_pSink->GetIDispatch(FALSE);

if(::AfxConnectionUnadvise(pElem,DIID_HTMLElementEvents2,pUnkSink,FALSE,m_dwCookie))

{

if(m_pSink!=NULL)

{

delete m_pSink;

m_pSink=NULL;

m_dwCookie=NULL;

}

}

}

這里嘮叨一下,在 AfxConnectionAdvise 內(nèi)部會(huì)調(diào)用 QueryInterface(IID_IConnectionPointContainer,..) FindConnectionPoint(), 因此只需要把 m_pSink 直接傳進(jìn)去即可,要是在外部調(diào)用這兩個(gè)函數(shù)再傳進(jìn)去就明顯會(huì)出錯(cuò)拉!

哈,結(jié)束拉,現(xiàn)在點(diǎn)擊測(cè)試吧 ~ 注意先把網(wǎng)頁(yè)打開哦,為了方便沒(méi)有做異常處理,如果先運(yùn)行程序的話會(huì)使程序崩潰的呀 ~

最后,我會(huì)在近期把工程 文件上傳 ,如果你是在別處看到此文章的,那么請(qǐng)回到我的博客,這里將會(huì)有下載的鏈接: http://blog.csdn.net/xiaodao1986/archive/2008/12/31/3672062.aspx ,也歡迎在我的博客留言, 或也可以給我發(fā)郵件 zhangwenbo_1986@163.com 。想轉(zhuǎn)載的朋友當(dāng)然也歡迎拉,本來(lái)就是想為大家做點(diǎn)事,不過(guò)請(qǐng)保留原文出處,這是對(duì)作者基本的禮貌吧?嘿嘿

掛接瀏覽器事件


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 色综合一本到久久亚洲91 | 日韩伦理一区 | 天天色色色 | 波多野结衣乳巨码无在线观看 | 久久精品国产波多野结衣 | 福利视频在线播放 | 久久免费视频6 | 四虎影视成人精品 | 国产成人久久综合二区 | 国产精品不卡在线 | 亚洲国产精品久久久天堂 | 欧美亚洲国产成人精品 | 精品国产一区二区三区不卡 | 色噜噜狠狠色综合免费视频 | 毛片一级 | 黄页成人免费网站 | 美女一级毛片免费不卡视频 | 欧美日韩色| 777kkk亚洲综合欧美色老头 | 夜夜欢视频 | 久久这里只有精品视频99 | 黄色在线免费观看网站 | 在线播放国产精品 | 久久综合香蕉久久久久久久 | 久久久久夜 | 深夜免费在线视频 | 亚洲七七久久精品中文国产 | 国产精品午夜免费福利视频 | 欧美在线观看高清一二三区 | 国产福利视频网站 | 一级毛片看看 | 亚洲欧美在线一区 | 国产天天操 | 久久婷婷综合中文字幕 | 毛片链接 | 欧美日韩亚洲综合在线一区二区 | 香蕉久久夜色精品国产小说 | 99久久中文字幕伊人 | 国产成人v片视频在线观看 国产成人爱片免费观看视频 | 亚洲欧洲国产精品你懂的 | 亚洲精品视频免费观看 |