Передать объект VB6 в объект .NET через взаимодействие? - PullRequest
5 голосов
/ 19 декабря 2011

У меня есть приложение VB6, которое показывает форму DLL .NET через взаимодействие.

Я бы хотел, чтобы событие в .NET DLL вызывало отображение формы в приложении VB6.

Моя идея состоит в том, чтобы приложение VB6 передавало ссылку на форму в .NET DLL. Например:

[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(); }

Будет ли это работать?

Я читал в другом месте, что отправка объектов через «границу процесса» может вызвать проблемы. Это правильно?

Ответы [ 2 ]

4 голосов
/ 19 декабря 2011

Одним из способов будет определение интерфейса COM в .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

Реализация этого интерфейса в 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

, а затем наличие регистратора в .NET со статическимколлекция 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

Ваш код .NET будет вызывать FireEvent, и если VB6 ранее вызывал RegisterHandler, ваш VB6 IEventHandler будет вызываться.

0 голосов
/ 13 января 2012

Вы также можете использовать ComSourceInterfacesAttribute , который может сделать ваш код немного проще (или, по крайней мере, более естественным со стороны VB6). У вас будет такой код:

C # библиотека:

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();
            }
        }
    }
}

И клиент VB6:

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

Если вы собираетесь использовать большое количество .NET UI из своего приложения VB6, я настоятельно рекомендую Interop Forms Toolkit , чтобы упростить задачу. (Это помогает генерировать код, подобный этим образцам, а также обрабатывает некоторые другие распространенные сценарии).

...