2011-12-19 17 views
5

私はinterop経由で.NET DLLフォームを表示するVB6アプリケーションを持っています。VB6オブジェクトをinterop経由で.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(); } 

これは機能しますか?

「プロセス境界」を超えてオブジェクトを送信すると問題が発生する可能性があります。これは正しいです?

+1

これはプロセス境界ではなく、同じプロセスです。はい、それは痛みですが、効果があります。 – Jeff

答えて

4

つのルートは、.NETでCOMインターフェイスを定義することであろう。

<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 

にこのインタフェースを実装し、その後IEventHandlersの静的コレクションと.NETでレジストラを有します:

<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でRegiあなたのVB6 IEventHandlerが呼び出されます。

+0

私のアプローチは簡単ではありませんか?私はイベントを処理するすべてのものを避けようとしていました。 – CJ7

+0

はい、シンプルですが、コールバックを作成するためにレイトバインディングを使用する必要があります。 – Jeff

+0

このシナリオでレイトバインディングのリスクは何ですか? – CJ7

0

コードを少しシンプルに(またはVB6側から少なくとも自然に)作ることができるComSourceInterfacesAttributeを使用することもできます。あなたからの.NET UIの多くを使用してしようとしている場合は

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 

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のクライアントは、次のようないくつかのコードを持っていると思いますあなたのVB6アプリケーション私は非常に物事を簡単にする方法としてInterop Forms Toolkitをお勧めします。 (これは、これらのサンプルのようなコードの生成に役立つほか、いくつかの一般的なシナリオの処理に役立ちます)。

関連する問題