2011-12-19 9 views
5

Ho un'app VB6 che mostra un modulo DLL .NET tramite interoperabilità.Passare l'oggetto VB6 a un oggetto .NET tramite interop?

Vorrei un evento nella DLL .NET per visualizzare un modulo nell'app VB6.

La mia idea è di fare in modo che l'app VB6 passi un riferimento a un modulo alla DLL .NET. Es .:

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

Questo lavoro funzionerà?

Ho letto altrove che l'invio di oggetti attraverso un "limite del processo" può causare problemi. È corretto?

+1

Questo non è un limite di processo ... è lo stesso processo. Sì, è un dolore, ma può funzionare. – Jeff

risposta

4

Una via potrebbe essere quella di definire un'interfaccia COM 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 

implementare questa interfaccia 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 

e poi avere un cancelliere in .NET con una collezione statica di 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 

Il tuo codice .NET chiamerebbe FireEvent e se VB6 aveva precedentemente chiamato Regi sterHandler, il tuo VB6 IEventHandler verrebbe chiamato.

+0

Il mio approccio non è più semplice? Stavo cercando di evitare tutto ciò che gestiva gli eventi. – CJ7

+0

Sì, più semplice, ma è necessario utilizzare l'associazione tardiva per effettuare la richiamata. – Jeff

+0

Quali sono i rischi con l'associazione tardiva in questo scenario? – CJ7

0

Si potrebbe anche utilizzare lo ComSourceInterfacesAttribute che potrebbe rendere il codice un po 'più semplice (o almeno più naturale dal lato VB6). Avresti qualche codice come il seguente: biblioteca

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

E il client 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 

Se avete intenzione di utilizzare un sacco di .NET UI da la tua applicazione VB6 mi raccomando vivamente il Interop Forms Toolkit come un modo per rendere le cose più semplici. (Aiuta a generare codice come questi esempi, oltre a gestire altri scenari comuni).