["00024413-0000-0000-C000-000000000046"]
{
DispId(0x61d)]
void NewWorkbook(object Wb);
DispId(0x616)]
void SheetSelectionChange(object Sh, object Target);
DispId(0x617)]
void SheetBeforeDoubleClick(object Sh, object Target, ref bool Cancel);
DispId(1560)]
void SheetBeforeRightClick(object Sh, object Target, ref bool Cancel);
DispId(0x619)]
void SheetActivate(object Sh);
DispId(0x61a)]
void SheetDeactivate(object Sh);
DispId(0x61b)]
void SheetCalculate(object Sh);
DispId(0x61c)]
void SheetChange(object Sh, object Target);
DispId(0x61f)]
void WorkbookOpen(object Wb);
DispId(0x620)]
void WorkbookActivate(object Wb);
DispId(0x621)]
void WorkbookDeactivate(object Wb);
DispId(1570)]
void WorkbookBeforeClose(object Wb, ref bool Cancel);
DispId(0x623)]
void WorkbookBeforeSave(object Wb, bool SaveAsUI, ref bool Cancel);
DispId(0x624)]
void WorkbookBeforePrint(object Wb, ref bool Cancel);
DispId(0x625)]
void WorkbookNewSheet(object Wb, object Sh);
DispId(0x626)]
void WorkbookAddinInstall(object Wb);
DispId(0x627)]
void WorkbookAddinUninstall(object Wb);
DispId(0x612)]
void WindowResize(object Wb, object Wn);
DispId(0x614)]
void WindowActivate(object Wb, object Wn);
DispId(0x615)]
void WindowDeactivate(object Wb, object Wn);
DispId(0x73e)]
void SheetFollowHyperlink(object Sh, object Target);
DispId(0x86d)]
void SheetPivotTableUpdate(object Sh, object Target);
DispId(2160)]
void WorkbookPivotTableCloseConnection(object Wb, object Target);
DispId(0x871)]
void WorkbookPivotTableOpenConnection(object Wb, object Target); }
Таким образом наш класс - приемник событий должен реализовывать этот интерфейс и регистрировать себя используя IConnectionPointContainer и IConnectionPoint. Библиотека базовых классов .NET уже определяет managed-версии интерфейсов: для IConnectionPointContainer это UCOMIConnectionPointContainer, а для IConnectionPoint - UCOMIConnectionPoint, которые определены в пространстве имен - System.Runtime.InteropServices.
Регистрация класса-приемника событий будет выглядеть так:
// Объявляем ссылки на IConnectionPointContainer UCOMIConnectionPointContainer icpc;
// и на IConnectionPoint
UCOMIConnectionPoint icp;
// Получаем ссылку на Excel
FExcel = Marshal.GetActiveObject("Excel.Application");
// Получаем ссылку на интерфейс IConnectionPointContainer
icpc = FExcel as UCOMIConnectionPointContainer;
// Получаем «точку подключения»
Guid guid = new Guid("00024413-0000-0000-C000-000000000046");
icpc.FindConnectionPoint(ref guid, out icp);
// Регистрируем класс - приемник событий, который реализует
// интерфейс с GUID ["00024413-0000-0000-C000-000000000046"]
// При этом наш класс получает уникальный идентификатор
// cookie, который нужно сохранить, чтобы иметь
// возможность отключиться от источника событий
icp.Advise(ExcelEventSink, out cookie);
Для отключения от событий достаточно вызвать метод Unadvise(), и передать ему в качестве параметра идентификатор cookie, который мы получили при регистрации нашего класса-приемника событий методом Advise:
icp.Unadvise(cookie);
6. Заключение.
Мы рассмотрели в статье на примере с MS Excel взаимодействие COM и NET, используя позднее связывание. Используя аналогичный подход, можно организовать управление любым COM сервером. (Чаще всего автоматизируют приложения пакета MS Office и MS Internet Explorer).
В приложенном к данной статье файле находится класс, с помощью которого можно организовать обработку событий Excel в любом приложении .NET.
7. Литература
Эндрю Троелсен. С# и платформа .NET. Библиотека программиста. - СПб. Питер, 2004.
Н. Елманова, С. Трепалин, А. Тенцер. Delphi 6 и технология СОМ. - СПб. Питер, 2002.
Техническая документация MSDN.