BHO開發中的IE事件響應原理

2021-05-23 08:58:34 字數 2462 閱讀 1570

ps:本文適合於對虛表、模板等語法特性熟悉的朋友。

atl的idispeventimpl簡化了事件響應的編碼流程。一般需要3個步驟:

1、  繼承idispeventimpl:

public

idispeventimpl<1, csayhello, &diid_dwebbrowserevents2>  

2、  新增sink_entry_ex:

sink_entry_ex

(1, diid_dwebbrowserevents2,dispid_documentcomplete, ondocumentcomplete)

3、  在setsite中建立連線和取消連線:

hresult

stdmethodcalltype csayhello::setsite(iunknown * punksite)

} }

else

m_spwebbrowser2.release(); }

return iobjectwithsiteimpl::setsite(punksite); }

這些步驟都完成之後,每當乙個頁面載入完成後都會呼叫我們自定義的ondocumentcomplete。

但是,具體的呼叫流程又是什麼? ie事件的通知流程如下:

1、取出已經註冊的bho的iunknown介面指標;

2、  在每個iunknown介面指標上呼叫queryinte***ce(iid_idispatch,(void**)&pdisp)獲取idispath介面指標;

3、  在所有的idispatch介面指標上呼叫invoke。bho物件會在內部通過型別庫輔助類將invoke的呼叫**至ondocumentcomplete。

ie必須要儲存各個bho的iunknown指標,否則就無法通知bho。那麼ie是通過什麼方式獲取這些iunknown指標呢?ie當然無法知道誰要掛接它,因此必須是bho自己將iunknown指標傳給ie,ie在內部儲存它的備份。我們的程式通過呼叫dispeventadvise將自己的iunknown指標傳給ie。由於我們的bho沒有定義這個成員函式,因此最終呼叫的是idispevent******impl:: dispeventadvise。該函式原始碼如下:

hresult

dispeventadvise(iunknown* punk, const iid* piid)

atladvise又是atl提供的函式,原始碼如下:

atlinline

atlapi atladvise(iunknown*punkcp, iunknown*punk, const iid& iid, lpdword pdw)

實際的事件訂閱工作由:hres

= pcp->advise(punk, pdw);這句**完成。ie儲存的iunknown指標就是punk,而punk又等於(iunknown*)this,this指標又指向bho物件的idispevent******impl子物件。因此,ie儲存的iunknown指標指向bho物件的idispevent******impl。對於ie而言,它才不管你具體指向哪個物件,,只是簡單地呼叫queryinte***ce。由於queryinte***ce是虛函式,因此,

punk->queryinte***ce(iid_idispatch, (void**)&pdisp);

被編譯器轉換成:

(*(punk)) (iid_idispatch, (void**)&pdisp);

即取出punk指向的記憶體空間的值,並強制轉換成與queryinte***ce原型一致的函式指標。而punk實際上指向idispevent******impl子物件,以上呼叫轉換成idispevent******impl子物件的第乙個虛函式的呼叫。idispevent******impl的前幾個虛函式分別為:

_locdequeryinte***ce

addref

release

gettypeinfocount

gettypeinfo

getidsofnames

invoke

所以,最終呼叫的是_locdequeryinte***ce。這就是queryinte***ce能成功的原因。

_locdequeryinte***ce的源**如下:

stdmethod

(_locdequeryinte***ce)(refiid riid, void ** ppvobject)

else

return e_nointe***ce; }

其實就是直接返回this指標,也就是ie儲存的iunknown指標。

接下來,ie會呼叫pdisp->invoke(…);

由於invoke也是虛函式,所以該呼叫會被轉換成對idispevent******impl第7個虛函式的呼叫(因為invoke就是idispatch介面的第7個虛函式),也就是呼叫idispevent******impl::invoke。invoke內部根據內建的對映表呼叫使用者自定義的documentcomplete函式。

iOS開發中的事件處理 二 事件傳遞,響應者鏈條

ios開發中的事件處理 二 事件傳遞,響應者鏈條 不接收使用者互動 userinteractionenabled no 隱藏hidden yes 透明alpha 0.0 0.01 主視窗會在檢視層次結構中找到乙個最合適的檢視來處理觸控事件,但是這僅僅是整個事件處理過程的第一步 找到合適的檢視控制項後...

ie 透明元素遮擋的元素仍能響應滑鼠事件

如果乙個元素被另乙個元素遮蓋,不論遮蓋元素的背景色是否是 transparent 也不論遮蓋元素的透明度是否為全透明,被遮蓋元素是不能響應使用者的滑鼠事件的。關於 background color 請參考 w3c css 2.1 規範 14.2.1 background color 中的內容。關於 ...

Vue中的響應式原理

vue最獨特的特性之一,是其非侵入性的響應式系統。響應式原理 資料變,頁面變 vue實現資料雙向繫結主要是 採用資料劫持結合發布者 訂閱者模式的方式 當把乙個普通的js物件傳入vue例項作為data選項時,vue將遍歷此物件的所有屬性,並使用object.defineproperty把這些屬性全部轉...