Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make COM Interop Events visible from Interface

I wrote my code like the example below:

public delegate void ClickDelegate(int x, int y);
public delegate void PulseDelegate();

[Guid("39D5B254-64DB-4130-9601-996D0B20D3E5"),
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)]
[ComVisible(true)]
public interface IButton
{
  void Work();
}

// Step 1: Defines an event sink interface (ButtonEvents) to be     
// implemented by the COM sink.
[GuidAttribute("1A585C4D-3371-48dc-AF8A-AFFECC1B0967") ]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)]
public interface ButtonEvents
{
    void Click(int x, int y);
    void Pulse();
}

// Step 2: Connects the event sink interface to a class 
// by passing the namespace and event sink interface.
// ("EventSource.ButtonEvents, EventSrc").
[ComSourceInterfaces(typeof(ButtonEvents))]
public class Button : IButton
{
    public event ClickDelegate Click;
    public event PulseDelegate Pulse;

    public Button() { }

    public void CauseClickEvent(int x, int y) { Click(x, y); }
    public void CausePulse() { Pulse(); }

    public void Work() { /* Do some stuff */ }
}

This works fine with VB. When I define it like:

Dim WithEvents obj As Button

But I want to define it with the Interface like:

Dim WithEvents obj As IButton

This is not working 'cause the events are not visible from the IButton interface.

Is there a way to do this?

like image 769
Richy1989 Avatar asked Jul 21 '26 22:07

Richy1989


1 Answers

A variable that connects to an object's events must be declared to be of the type (CoClass) of the object (Button in your example). An interface (IButton in your example) doesn't know anything about the events, and it cannot be used to request them.

This is the way I like to think about it:

An interface is something two objects agree on using so the "client" can send commands to the "server" ("server, do XYZ!"). An Event is just a different interface that the two objects also agree on using, but for the opposite: that is, for the "server" object to send commands to the "client".

Whether a given Event interface is supported is a property of the object, not a property of whatever interface(s) the object might support. The server object says: "Give me a ButtonEvents interface pointer, and I'll use it to tell you when the button has been clicked". It's not the IButton interface that makes that offer.

That's also why you have to apply the [ComSourceInterfaces] attribute to the class Button, not to the interface IButton. The Button CoClass is the one that makes the offer.

The thing that makes events look special or weird is that we need to use a somewhat complicated and confusing dance ("Connection Points") to pass the event's interface pointer around. WithEvents is the way to ask VB6 to "do the dance" for you.

like image 85
Euro Micelli Avatar answered Jul 23 '26 12:07

Euro Micelli



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!