无法在单击按钮时将 Com Interop 事件从 Winforms(form) 引发到 VB
Unable to raise Com Interop event on button click from a Winforms(form) to VB
我用 C# 编写了一个 COM Interop 可见 class 库。如果我打开 vb6 对象浏览器并查看暴露的成员,我会看到每个暴露的成员都有一个事件。
在我的互操作中,我有一个带有一个按钮的表单,因此一旦用户单击该按钮,就需要调用该事件,但即使我在单击按钮时调用了 com 可见事件,它也没有发生。但是或者,如果我从 vb6 调用一个 public C# 函数并且在函数内部调用了 com 可见事件,那么该事件将在 vb6.0
中触发
下面是我的 C# 代码
public partial class Form1 : Form, EventsInf
{
public delegate void GetData_delegate(string serviceid);
public event GetData_delegate GetData;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Button click entered");
GetData?.Invoke("test");
}
public void raiseevent()
{
MessageBox.Show("Event raised from function");
GetData?.Invoke("test");
}
public void show()
{
Form1 f1 = new Form1();
f1.ShowDialog();
}
我的界面:
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)]
[ComVisible(true)]
public interface Interface
{
void GetData(string serviceid);
}
我的活动信息:
[ComVisible(true)]
public interface EventsInf
{
void raiseevent();
}
VB6.0代码:
Private WithEvents test As ClassLibrary5.Form1
Private obj As ClassLibrary5.Class1
Private Sub Form_Load()
Set obj = New ClassLibrary5.Class1
Set test = New ClassLibrary5.Form1
test.raiseevent
Me.Visible = False
obj.Show
End Sub
Private Sub test_GetData(ByVal serviceid As String)
End Sub
请参考屏幕截图,其中我已将 C# dll 转换为 tlb 并将其添加为对我的 vb6 项目的引用。现在在执行 vb 6 项目时,winform 的 (form window) 被启动。但是,在按下 'click me' 按钮后,断点没有被击中。
您确实应该遵循公开事件的标准约定。如果您想引发一个提供文本数据的事件并在用户单击 Button
时引发该事件,那么它应该如下所示:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public event EventHandler<DataAvailableEventArgs> DataAvailable;
protected virtual void OnDataAvailable(DataAvailableEventArgs e)
{
DataAvailable?.Invoke(this, e);
}
}
public class DataAvailableEventArgs : EventArgs
{
public string Data { get; }
public DataAvailableEventArgs(string data)
{
Data = data;
}
}
然后您通过调用 OnDataAvailable
方法并传递一个 DataAvailableEventArgs
对象来引发事件,例如
OnDataAvailable(new DataAvailableEventArgs("test"));
您可以从 Button
或 RaiseDataAvailable
方法的 Click
事件处理程序或任何地方执行此操作。事件处理程序将与其他任何事件处理程序一样,即 sender
参数将是引发事件的对象,而 e
参数将包含数据,例如
Dim data As String = e.Data
如果您真的想定义自己的委托(也许 COM 需要;不确定)那么您可以这样做:
public delegate void DataAvailableEventHandler(object sender, DataAvailableEventArgs e);
还有这个:
public event DataAvailableEventHandler DataAvailable;
在 C# 中,您有两个不同的名称 GetData
。这似乎是一个错误。
表格class中有event ... GetData
。
并且界面中有正则函数GetData
Interface
.
并且该表单无论如何都没有实现该接口。 (为什么甚至需要它?)
所以我认为就 VB6 而言,您的 test_GetData
并不存在。在 IDE 中,您应该在左侧下拉菜单 IIRC 中看到 test
,在右侧下拉菜单中看到 GetData
以及任何其他事件。但它实际上只是在左侧显示“一般”。
您是否必须手动输入 Private Sub test_GetData ...
?
根本原因:
我在 class 中写了 'f1.ShowDialog();' ,其中 f1 是表单对象。
修复:
通过在 public 函数中使用 'this.Show();' 重写表单代码解决了这个问题。
C# 代码:
private void button1_Click(object sender, EventArgs e)
{
GetData?.Invoke("test");
}
public void raiseevent()
{
this.Show();
MessageBox.Show("Event raised from function");
}
VB6.0
Private WithEvents test As ClassLibrary5.Form1
Private Sub Form_Load()
Set test = New ClassLibrary5.Form1
test.raiseevent
Me.Visible = False
End Sub
Private Sub test_GetData(ByVal serviceid As String)
End Sub
我用 C# 编写了一个 COM Interop 可见 class 库。如果我打开 vb6 对象浏览器并查看暴露的成员,我会看到每个暴露的成员都有一个事件。
在我的互操作中,我有一个带有一个按钮的表单,因此一旦用户单击该按钮,就需要调用该事件,但即使我在单击按钮时调用了 com 可见事件,它也没有发生。但是或者,如果我从 vb6 调用一个 public C# 函数并且在函数内部调用了 com 可见事件,那么该事件将在 vb6.0
中触发下面是我的 C# 代码
public partial class Form1 : Form, EventsInf
{
public delegate void GetData_delegate(string serviceid);
public event GetData_delegate GetData;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Button click entered");
GetData?.Invoke("test");
}
public void raiseevent()
{
MessageBox.Show("Event raised from function");
GetData?.Invoke("test");
}
public void show()
{
Form1 f1 = new Form1();
f1.ShowDialog();
}
我的界面:
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)]
[ComVisible(true)]
public interface Interface
{
void GetData(string serviceid);
}
我的活动信息:
[ComVisible(true)]
public interface EventsInf
{
void raiseevent();
}
VB6.0代码:
Private WithEvents test As ClassLibrary5.Form1
Private obj As ClassLibrary5.Class1
Private Sub Form_Load()
Set obj = New ClassLibrary5.Class1
Set test = New ClassLibrary5.Form1
test.raiseevent
Me.Visible = False
obj.Show
End Sub
Private Sub test_GetData(ByVal serviceid As String)
End Sub
请参考屏幕截图,其中我已将 C# dll 转换为 tlb 并将其添加为对我的 vb6 项目的引用。现在在执行 vb 6 项目时,winform 的 (form window) 被启动。但是,在按下 'click me' 按钮后,断点没有被击中。
您确实应该遵循公开事件的标准约定。如果您想引发一个提供文本数据的事件并在用户单击 Button
时引发该事件,那么它应该如下所示:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public event EventHandler<DataAvailableEventArgs> DataAvailable;
protected virtual void OnDataAvailable(DataAvailableEventArgs e)
{
DataAvailable?.Invoke(this, e);
}
}
public class DataAvailableEventArgs : EventArgs
{
public string Data { get; }
public DataAvailableEventArgs(string data)
{
Data = data;
}
}
然后您通过调用 OnDataAvailable
方法并传递一个 DataAvailableEventArgs
对象来引发事件,例如
OnDataAvailable(new DataAvailableEventArgs("test"));
您可以从 Button
或 RaiseDataAvailable
方法的 Click
事件处理程序或任何地方执行此操作。事件处理程序将与其他任何事件处理程序一样,即 sender
参数将是引发事件的对象,而 e
参数将包含数据,例如
Dim data As String = e.Data
如果您真的想定义自己的委托(也许 COM 需要;不确定)那么您可以这样做:
public delegate void DataAvailableEventHandler(object sender, DataAvailableEventArgs e);
还有这个:
public event DataAvailableEventHandler DataAvailable;
在 C# 中,您有两个不同的名称 GetData
。这似乎是一个错误。
表格class中有
event ... GetData
。并且界面中有正则函数
GetData
Interface
.
并且该表单无论如何都没有实现该接口。 (为什么甚至需要它?)
所以我认为就 VB6 而言,您的 test_GetData
并不存在。在 IDE 中,您应该在左侧下拉菜单 IIRC 中看到 test
,在右侧下拉菜单中看到 GetData
以及任何其他事件。但它实际上只是在左侧显示“一般”。
您是否必须手动输入 Private Sub test_GetData ...
?
根本原因: 我在 class 中写了 'f1.ShowDialog();' ,其中 f1 是表单对象。
修复: 通过在 public 函数中使用 'this.Show();' 重写表单代码解决了这个问题。
C# 代码:
private void button1_Click(object sender, EventArgs e)
{
GetData?.Invoke("test");
}
public void raiseevent()
{
this.Show();
MessageBox.Show("Event raised from function");
}
VB6.0
Private WithEvents test As ClassLibrary5.Form1
Private Sub Form_Load()
Set test = New ClassLibrary5.Form1
test.raiseevent
Me.Visible = False
End Sub
Private Sub test_GetData(ByVal serviceid As String)
End Sub