原文:
atl所自帶響應event的類有兩個
idispevent******impl
idispeventimpl
它們的區別是乙個是否帶型別庫,現在看看他們的模板引數
template
class atl_no_vtable idispevent******impl : public _idispeventlocator
; template
const guid* plibid = &guid_null, word wmajor = 0, word wminor = 0, class tihclass = ccomtypeinfoholder>
class atl_no_vtable idispeventimpl : public idispevent******impl
; 可以看到idispeventimpl的引數太多,居然連pdiid都可以預設引數。
區別:idispeventimpl能從iunknow裡queryinte***ce出它的型別庫,得到event函式的詳細結構,使下面sink結構構造簡單。而idispevent******impl不使用型別庫,使用手工打造,sink結構自然要麻煩一些。
引數說明:
nid:控制項id,如果所有父類不是對話方塊類,這個值,可以隨便設乙個。但必須跟下面的sink結構的id相一致。
t:父類
pdiid:event的iid。如果sink結構是使用sink_entry_ex或sink_entry_info,裡面的iid必須跟這裡一致。
plibid:libid。如果pdiid用預設值iid_null,這個值最好用預設值。原因下面再解析。
wmajor和wminor:版本資訊。其用法跟plibid一樣。
一、使用:
連線:可供選擇兩個函式。
hresult dispeventadvise(iunknown* punk, const iid* piid)
hresult advise(iunknown *punk)
dispeventadvise:
適用於不是預設連線的情況(只要com物件提供有event就可以連線),這種情況由指定的piid進行連線。
但前提idispeventimpl或idispevent******impl必須有指定引數,不能採用預設引數,否則很可能會工作不正常。
advise:
僅適用於預設連線的情況,這個函式用起來很舒服。它裡面使呼叫atlgetobjectsourceinterf
ace獲得預設型別資訊,並存起來。僅適用於idispeventimpl。
如果idispevent******impl會因為在invoke時候發現有型別資訊,但又不能處理型別資訊而產生錯誤
斷開:hresult unadvise(iunknown *punk);
hresult dispeventunadvise(iunknown* punk, const iid* piid);
最好跟連線的相配套,但unadvise最終會呼叫dispeventunadvise,所以也可以直接dispeventunadvise。
idispeventimpl如果使用預設值的情況下,也就是使用advise的情況下,其模板的構造版本,使不使用預設值,不重要,因為它會使用atlgetobjectsourceinterf
ace獲得iid,libid,及版本資訊。
但如果使用dispeventadvise,idispeventimpl的構造就相對麻煩很多,全部引數,都需要老老實實地填 ,而且不能錯。iid,libid一般都能從頭檔案裡得到,但版本呢?可以使用atlgetobjectsourceinterf
ace執行一次,檢視一下,得到具體值,再構造這個模板。
二、sink結構:
下面再看一下sink結構吧。
[cpp] view plaincopy
begin_sink_map(classname)
sink_entry(idc_a171, 1, texta171)
sink_entry_ex(2,__uuidof(htmldocumentevents ),dispid_htmldocumentevents_onmousedown,func)
sink_entry_info(1,__uuidof(_itt3events) , 1, onmyfunc, &statuschangeinfo)
end_sink_map
sink結構與傳統的map結構類似,也是begin-end結構,上面的結構是所有idispevent******impl和idispeventimpl共用。
從上面**可以看到最簡單是sink_entry,接著是sink_entry_ex, sink_entry_info,現在再來看看這三個結構的關係
[cpp] view plaincopy
#define sink_entry_info(id, iid, dispid, fn, info) ,
#define sink_entry_ex(id, iid, dispid, fn) sink_entry_info(id, iid, dispid, fn, null)
#define sink_entry(id, dispid, fn) sink_entry_ex(id, iid_null, dispid, fn)
sink_entry會從sink_entry_ex逐步演變為sink_entry_info,複雜的**不多說,光說應用吧。
引數說明:
id:控制項id,與前面的event類的id相一致
dispid:event裡函式或屬性的dispatch id
iid:event的iid
fn:函式名字
info:函式引數結構,是最複雜的一項。(這裡暫不解析,由於麻煩,一般不採用這種方式)
sink_entry:
所以在event模板引數的pdiid必須為iid_null,否則只能使用sink_entry_ex或sink_entry_info,但如果在idispevent******impl使用iid_null作為idd引數,儘管可以使用sink_entry通過編譯,但最終執行的時候,沒有型別資訊的函式,所以最後還是執行錯誤。簡單的話說,這個巨集只能用於idispeventimpl,而且pdiid==iid_null的情況。
sink_entry_ex:
也只能用於idispeventimpl,需要iid引數
sink_entry_info:
是最複雜的情況,可以用於idispeventimpl和idispevent******impl,但要要構造麻煩info引數,這不一是一件爽事。
Event類的簡單實現
寫乙個event類,實現事件的繫結 on方法 呼叫 trigger方法 解綁 off方法 on可以多次繫結事件,每個事件都可以被單獨觸發,被單獨解綁,請手寫 class event on name,callback else trigger name else off name else const...
Linux 新的事件等待 響應機制eventfd
常用的程序 執行緒間通訊機制有管道 訊號量 訊息佇列 訊號 共享記憶體 socket等等,其中主要作為程序 執行緒間通知 等待的有管道pipe和socket。從linux 2.6.27版本開始增加了eventfd,主要用於程序或者執行緒間的通訊 如通知 等待機制的實現 注 eventfd用於程序 執...
14 說說ATL常用包裝類的用法和坑
atl提供了很多複雜資料型別的包裝類,使用這些包裝類可以大大減小開發工作量,但是他們使用起來也有許多坑,需要注意,本文就atl常用包裝類的用法和坑詳細說明,力圖說明產生這些坑的原因和使用注意事項。本文基於vs2008 atl,這一版修復了一些之前的bug。先說通用的注意事項,所有的幫助類都類似智慧型...