COM 相互運用機能を使用して .NET コントロールを ActiveX として公開するときに、イベントを手動で接続するという同じ問題が発生していたため、もう少し先に進みました。
Reflector (Redgate Reflector など) を使用して UserControl クラスを少し掘り下げると、ComConnectionPointContainer および ComConnectionPoint メンバーを持つ「AdviseHelper」と呼ばれる別のネストされた静的クラスを含む「ActiveXImpl」ネストされたクラス メンバーが表示されます。また、必要に応じてポイントを接続するためのヘルパー機能もあります。
問題があります。コントロール (イベント ソース) からコネクション ポイント コンテナー (コントロールのイベントのイベント シンクを含む) にイベントが COM 相互運用によってフックされると、IQuickActivate.QuickActivate 関数が呼び出され、AdviseHelper クラスが呼び出されます。 ' 関数。
クライアント上のイベント シンクへの IUnknown インターフェイス ポインター (つまり、コントロールではなく、それを含むもの) がこの QuickActivate 関数 (パラメーター 'pUnkEventSink') に渡されます。リフレクターでは、この関数は次のようになります。実際のイベント接続を行います:
internal void QuickActivate(UnsafeNativeMethods.tagQACONTAINER pQaContainer, UnsafeNativeMethods.tagQACONTROL pQaControl)
{
int num;
this.LookupAmbient(-701).Value = ColorTranslator.FromOle((int) pQaContainer.colorBack);
this.LookupAmbient(-704).Value = ColorTranslator.FromOle((int) pQaContainer.colorFore);
if (pQaContainer.pFont != null)
{
Control.AmbientProperty ambient = this.LookupAmbient(-703);
IntSecurity.UnmanagedCode.Assert();
try
{
Font font2 = Font.FromHfont(((UnsafeNativeMethods.IFont) pQaContainer.pFont).GetHFont());
ambient.Value = font2;
}
catch (Exception exception)
{
if (ClientUtils.IsSecurityOrCriticalException(exception))
{
throw;
}
ambient.Value = null;
}
finally
{
CodeAccessPermission.RevertAssert();
}
}
pQaControl.cbSize = UnsafeNativeMethods.SizeOf(typeof(UnsafeNativeMethods.tagQACONTROL));
this.SetClientSite(pQaContainer.pClientSite);
if (pQaContainer.pAdviseSink != null)
{
this.SetAdvise(1, 0, (IAdviseSink) pQaContainer.pAdviseSink);
}
IntSecurity.UnmanagedCode.Assert();
try
{
((UnsafeNativeMethods.IOleObject) this.control).GetMiscStatus(1, out num);
}
finally
{
CodeAccessPermission.RevertAssert();
}
pQaControl.dwMiscStatus = num;
if ((pQaContainer.pUnkEventSink != null) && (this.control is UserControl))
{
Type defaultEventsInterface = GetDefaultEventsInterface(this.control.GetType());
if (defaultEventsInterface != null)
{
IntSecurity.UnmanagedCode.Assert();
try
{
**AdviseHelper.AdviseConnectionPoint(this.control, pQaContainer.pUnkEventSink, defaultEventsInterface, out pQaControl.dwEventCookie);**
}
catch (Exception exception2)
{
if (ClientUtils.IsSecurityOrCriticalException(exception2))
{
throw;
}
}
finally
{
CodeAccessPermission.RevertAssert();
}
}
}
if ((pQaContainer.pPropertyNotifySink != null) && UnsafeNativeMethods.IsComObject(pQaContainer.pPropertyNotifySink))
{
UnsafeNativeMethods.ReleaseComObject(pQaContainer.pPropertyNotifySink);
}
if ((pQaContainer.pUnkEventSink != null) && UnsafeNativeMethods.IsComObject(pQaContainer.pUnkEventSink))
{
UnsafeNativeMethods.ReleaseComObject(pQaContainer.pUnkEventSink);
}
}
「pUnkEventSink」変数は tagQACONTROL 構造を介してこの関数に渡されますが、ご覧のとおり、IAdviseSink、コントロール コンテナー、フォント スタイルなどとは異なり、この変数は「ActiveXImpl」クラスのどのメンバーにも設定されません。したがって、この関数が最初にフレームワークによって呼び出された後は、それにアクセスできません。
この IUnknown pUnkEventSink 変数を取得して、AdviseHelper.AdviseConnectionPoint() 関数を呼び出す必要があります。この関数は、手動イベント フックアップを行います。そして、これが私が抱えていた問題です - 残念ながら、あなたはそれを手に入れることができないようです.
他の誰かがこれをさらに発展させたので、私に知らせてください!