Пытаюсь создать простенький COM-объект на C#. Вот такой код:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace COMTest
{
public delegate void COMTestEvent(String TestStr);
[Guid("AF1DE52F-5A91-4215-8E73-BAE236EE4475"),
ComVisible(true),
InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface ICOMTest
{
String TestProperty {get;set;}
void TestMethod();
};
[Guid("0526D61B-2732-4036-92CE-E10E62C9D50A"),
ComVisible(true),
InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface ICOMTestEvent
{
[DispId(1)]
void COMTestEventFunc(String TestStr);
}
[ClassInterface(ClassInterfaceType.None),
ComSourceInterfaces(typeof(ICOMTestEvent))]
public partial class UserControl1 : UserControl, ICOMTest
{
public event COMTestEvent COMTestEventFunc;
private String _TestProperty;
public String TestProperty {get{return _TestProperty;} set{_TestProperty=value;}}
void ICOMTest.TestMethod()
{
MessageBox.Show("TestMethod Called!!!");
if(COMTestEventFunc!=null) COMTestEventFunc(_TestProperty);
}
public UserControl1()
{
InitializeComponent();
}
}
}
Галка "Register for COM interop" в свойствах проекта выставлена.
Регистрирую вот такой командой:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe COMTest.dll /tlb:COMTest.tlb /codebase
Проверяю из VBA вот так:
Dim WithEvents COMTestObj As COMTest.UserControl1
Sub t1()
Dim pCOMTest As ICOMTest
Set pCOMTest = New COMTest.UserControl1
pCOMTest.TestProperty = "qwerty"
pCOMTest.TestMethod
Set pCOMTest = Nothing
End Sub
Private Sub COMTestObj_COMTestEvent(ByVal TestStr As String)
MsgBox TestStr
End Sub
Свойство выставляется, метод вызывается. Событие работать не хочет. Смотрел в отладчике — COMTestEventFunc всегда null.
Что я сделал не так?
Здравствуйте, RegSubscr, Вы писали:
RS>Народ, ну неужели никто не делал COM-объекты на C#. Что у всех все нормально? Ни у кого не было подобных проблем с событиями?
А VBA код у вас какой-то странный. События ловятся для переменной COMTestObj, а присваивание происходит pCOMTest. Оно точно делает попытку подписки на EventSource (на стороне COM) ?
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, TK, Вы писали:
TK>А VBA код у вас какой-то странный. События ловятся для переменной COMTestObj, а присваивание происходит pCOMTest.
pCOMTest это указатель на интерфейс, в котором определен метод, который поднимает событие. А как бы Вы написали?
TK>Оно точно делает попытку подписки на EventSource (на стороне COM) ?
Видимо нет А как это проверить?
Здравствуйте, RegSubscr, Вы писали:
TK>>А VBA код у вас какой-то странный. События ловятся для переменной COMTestObj, а присваивание происходит pCOMTest. RS>pCOMTest это указатель на интерфейс, в котором определен метод, который поднимает событие. А как бы Вы написали?
В бейсике не силен. Попробуйте написать Dim WithEvents COMTestObj As New COMTest.UserControl1 и использовать дальше COMTestObj за место локальной переменной. или просто присвоить ей значение.
Проблема скорее всего в том, что события ловятся в одном месте, а экземпляр создается в другом.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, TK, Вы писали:
TK>Попробуйте написать Dim WithEvents COMTestObj As New COMTest.UserControl1
Так не получается. Ругается компилятор.
TK>и использовать дальше COMTestObj за место локальной переменной. или просто присвоить ей значение. TK>Проблема скорее всего в том, что события ловятся в одном месте, а экземпляр создается в другом.
Видимо Вы правы и проблема была в этом. Написал вот так:
Public WithEvents COMTestObj As COMTest.UserControl1
Sub t1()
Set COMTestObj = New COMTest.UserControl1
COMTestObj.TestProperty = "qwery"
COMTestObj.TestMethod
Set pCOMTest = Nothing
End Sub
Private Sub COMTestObj_COMTestEventFunc(ByVal TestStr As String)
MsgBox "Event Raised!!!" + Chr(13) + Chr(10) + "Rarameter:" + TestStr
End Sub
Все заработало. Событие вызвалось. Примите мою искреннюю благодарность за помощь
TK>В бейсике не силен.
А в Delphi? Просто COM-объект который я делаю планируется использовать там...
Не подскажите, как в Delphi должно выглядеть подключение к событию? А то я никогда на Delphi не писал. Собственно, это уже
не моя проблема, а коллеги (он Дельфист). Я просто подумал, что вдруг у Вас был уже подобный опыт и с Вашей помощью
мы сможем обойти какие-то типичные грабли.
TK>>В бейсике не силен. RS>А в Delphi? Просто COM-объект который я делаю планируется использовать там...
Все. Уже разобрался. Правда не в Delphi, а в C++ Builder, но они вроде в этом плане не отличаются.
Там все просто оказалось:
В меню Project->Import Type Library выбрал из списка свой COM-объект.
Скомпилировал пакет.
Положил получившийся компонент на форму.
Все. События подцепляются без всяких хитростей также как и для любого другого контрола.