IDispEventSimpleImplおよびIDispEventImplアプリケーション分析


ATLが持つレスポンスイベントのクラスは2つあります
IDispEventSimpleImpl
IDispEventImpl
これらの違いは、タイプライブラリがあるかどうかです.テンプレートパラメータを見てみましょう.
template <UINT nID, class T, const IID* pdiid>
class ATL_NO_VTABLE IDispEventSimpleImpl : public _IDispEventLocator<nID, pdiid>
{
};
template <UINT nID, class T, const IID* pdiid = &IID_NULL,
 const GUID* plibid = &GUID_NULL, WORD wMajor = 0, WORD wMinor = 0, class tihclass = CComTypeInfoHolder>
class ATL_NO_VTABLE IDispEventImpl : public IDispEventSimpleImpl<nID, T, pdiid>
{
};

 
IDispEventImplのパラメータが多すぎて、意外にもp diidさえデフォルトのパラメータを見ることができます.
違い:
IDispEventImplはIUnknowからQueryInterfaceからそのタイプライブラリを出すことができ、Event関数の詳細な構造を得ることができ、次のSINK構造の構造を簡単にすることができます.IDispEventSimpleImplはタイプライブラリを使用せず、手作業で作成すると、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と同じです.
 
一、使用:
接続:
2つの関数を選択できます.
HRESULT DispEventAdvise(IUnknown* pUnk, const IID* piid)
HRESULT Advise(IUnknown *punk)
DispEventAdvise:
デフォルト接続でない場合(COMオブジェクトにEVENTがあれば接続可能)に適用され、指定されたpiidで接続されます.
ただし、IDispEventImplまたはIDispEventSimpleImplには指定したパラメータが必要であり、デフォルトのパラメータは使用できません.そうしないと、正常に動作しない可能性があります.
Advise:
この関数は、デフォルトの接続の場合にのみ使用できます.AtlGetObjectSourceInterfaceを呼び出してデフォルトのタイプ情報を取得し、併存させます.IDispEventImplのみに適用されます.
IDispEventSimpleImplでは、invokeでタイプ情報が発見されたが、タイプ情報を処理できないためエラーが発生する
切断:
HRESULT Unadvise(IUnknown *punk);
HRESULT DispEventUnadvise(IUnknown* pUnk, const IID* piid);
接続されているセットに合うのが望ましいが、Unadviseは最終的にDispEventUnadviseを呼び出すので、直接DispEventUnadviseを呼び出すこともできる.
 
IDispEventImplデフォルト値を使用する場合、つまりAdviseを使用する場合、そのテンプレートの構造バージョンは、AtlGetObjectSourceInterfaceを使用してIID、LIBID、およびバージョン情報を取得するため、デフォルト値を使用しないようにすることは重要ではありません.
しかしDispEventAdviseを使用すると、IDispEventImplの構造は比較的面倒で、すべてのパラメータは、正直に記入する必要があり、間違いはありません.IID、LIBIDは一般的にファイルから入手できますが、バージョンは?AtlGetObjectSourceInterfaceを使用して一度実行し、確認して、具体的な値を得て、このテンプレートを構築することができます.
 
 
 
二、SINK構造:
SINKの仕組みを見てみましょう.
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構造でもあり、上記の構造はすべてのIDispEventSimpleImplとIDispEventImplが共用している.
上のコードから見ると一番簡単なのはSINK_ですENTRY、続いてSINK_ENTRY_EX, SINK_ENTRY_INFO、この3つの構造の関係を見てみましょう.
#define SINK_ENTRY_INFO(id, iid, dispid, fn, info) {id, &iid, (int)(INT_PTR)(static_cast<ATL::_IDispEventLocator<id, &iid>*>((_atl_event_classtype*)8))-8, dispid, (void (__stdcall _atl_event_classtype::*)())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、ただしIDispEventSimpleImplでIID_を使用する場合NULLはIDDパラメータとしてSINK_を使用できますがENTRYはコンパイルされていますが、最終的に実行する場合、タイプ情報の関数がないので、最後にはエラーが発生します.簡単に言えば、このマクロはIDispEventImplにのみ使用でき、pdiid=IID_NULLの場合.
SINK_ENTRY_EX:
IDispEventImplにしか使用できません.IIDパラメータが必要です.
SINK_ENTRY_INFO:
最も複雑な場合で、IDispEventImplとIDispEventSimpleImplに使用できますが、面倒なinfoパラメータを構築するには、これは爽やかではありません.