У меня получилось немного дальше, так как у меня возникла та же проблема с ручным подключением событий при представлении элемента управления .NET в качестве ActiveX с помощью взаимодействия COM.
Если вы немного покопаетесь в классе UserControl с помощью Reflector (например, Redgate Reflector), вы увидите вложенный класс ActiveXImpl, который содержит другой вложенный статический класс с именем 'AdviseHelper', который имеет члены ComConnectionPointContainer и ComConnectionPoint. Он также имеет вспомогательные функции для соединения точек по вашему усмотрению.
Есть проблема. Когда COM-взаимодействие от вашего элемента управления (источника события) подключается к контейнеру точки подключения (который содержит приемник событий для событий вашего элемента управления), вызывается функция IQuickActivate.QuickActivate, которая затем вызывает класс AdviseHelper 'AdviseConnectionPoint 'функция.
Указатель интерфейса 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 (), которая будет выполнять ручное подключение события. И это проблема, с которой я столкнулся - к сожалению, вы просто не можете ее решить.
У кого-нибудь еще были какие-либо изменения в этом, дайте мне знать!