5

I have a VB6 app that shows a .NET DLL form via interop.

I would like an event in the .NET DLL to cause a form in the VB6 app to be shown.

My idea is to have the VB6 app pass a reference to a form to the .NET DLL. Eg:

[VB6]
Dim objNetDllObject As New NetDllObject
objNetDllObject.PassVb6Form(MyForm)
objNetDllObject.ShowForm

[C#]
object Vb6Form; 
private void PassVb6Form(object form) { Vb6Form = form; }
private void button1_Click(object sender, EventArgs e) { Vb6Form.Show(); }

Will this work?

I've read elsewhere that sending objects across a 'process boundary' can cause problems. Is this correct?

1
  • 1
    This isn't a process boundary...it's the same process. Yes, it's a pain, but it can work. Commented Dec 19, 2011 at 15:01

2 Answers 2

4

One route would be to define a COM Interface in .NET:

<System.Runtime.InteropServices.GuidAttribute("0896D946-8A8B-4E7D-9D0D-BB29A52B5D08"), _
InterfaceType(ComInterfaceType.InterfaceIsIDispatch)> _
Public Interface IEventHandler
    Sub OnEvent(ByRef sender As Object, ByRef e As Object)
End Interface

Implement this interface in VB6

Implements MyInterop.IEventHandler

Private Sub IEventHandler_OnEvent(ByRef sender As Variant, ByRef e As Variant)
    Dim id
    id = e.Entity.Id
    ' As long as e is COM Visible (not necessarily COM registered, this will work)
End Sub

and then have a Registrar in .NET with a static collection of IEventHandlers:

<ComClass(ComRegistrar.ClassId, ComRegistrar.InterfaceId, ComRegistrar.EventsId>
Public Class ComRegistrar

   Private Shared ReadOnly _eventHandlers As New Dictionary(Of String, List(Of IEventHandler))


   ' This is called by .NET code to fire events to VB6
   Public Shared Sub FireEvent(ByVal eventName As String, ByVal sender As Object, ByVal e As Object)
        For Each eventHandler In _eventHandlers(eventName)
                eventHandler.OnEvent(sender, e)
        Next
   End Sub

   Public Sub RegisterHandler(ByVal eventName As String, ByVal handler As IEventHandler)
        Dim handlers as List(Of IEventHandler)
        If Not _eventHandlers.TryGetValue(eventName, handlers)
             handlers = New List(Of IEventHandler)
             _eventHandlers(eventName) = handlers
        End If
        handlers.Add(handler)
   End Sub

End Class

Your .NET code would call FireEvent and if VB6 had previously called RegisterHandler, your VB6 IEventHandler would get called.

Sign up to request clarification or add additional context in comments.

8 Comments

Isn't my approach simpler? I was trying to avoid all that event handling stuff.
Yes, simpler, but you'll need to use late binding to make your callback.
What are the risks with late binding in this scenario?
Same as the usual :) ...method doesn't exist. You don't invoke it right. Signature changes...etc.
How would the signature change?
|
0

You could also use the ComSourceInterfacesAttribute which could make your code a little bit simpler (or at least more natural from the VB6 side). You'd have some code like the following:

C# library:

namespace WindowsFormsControlLibrary1
{
    using System;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;

    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    public interface IMyFormEvents
    {
        [DispId(1)]
        void MyEvent();
    }

    public delegate void MyEventEventHandler();

    [ComSourceInterfaces(typeof(IMyFormEvents))]
    public partial class MyForm : Form
    {
        public event MyEventEventHandler MyEvent;

        public MyForm()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (this.MyEvent != null)
            {
                this.MyEvent();
            }
        }
    }
}

And the VB6 client:

Option Explicit

Private WithEvents f As WindowsFormsControlLibrary1.MyForm

Private Sub Command1_Click()
    Set f = New WindowsFormsControlLibrary1.MyForm
    Call f.Show
End Sub

Private Sub f_MyEvent()
    MsgBox "Event was raised from .NET"
    'Open another VB6 form or do whatever is needed
End Sub

If you are going to be using a lot of .NET UI from your VB6 application I would highly recommend the Interop Forms Toolkit as a way to make things simpler. (It helps generate code like these samples, as well as handling some other common scenarios).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.