Chris Calvert
Chris Calvert

Reputation: 129

IProgressCallBack between VB6 EXE and VB.NET DLL

I am currently upgrading our software from VB6 to VB.NET and doing so one DLL at a time. The EXE will be last since it has a lot of third party UI controls.

One issue that I found is that the VB6 version of the DLL housed an IProgressCallBack class that was acting like an interface class (which does not officially exist in VB6) and allowed the EXE to get progress reports from the DLL and display it on the screen for the user.

When this DLL is migrated the IProgressCallBack class can be set as an Interface class, but then it cannot be 'Set' to the instance of the form using it. But if I create it as just a normal class, it still will not let me 'Set' it to the instance of the form using it since they are two different object types.

I need to know how do I either make the IProgressCallBack class work between VB6 and VB.NET or what is an alternate solution to keep the VB6 UI informed of the progress of the .NET DLL?

Here is an example of the VB6 version of both and how they work:

VB6 DLL: IProgressCallBack

Option Explicit
Public Function NotifyProgress(ByVal Progress As Single, ByRef isCancel As Boolean) As Boolean
End Function

VB6 DLL: MainFunctions Class

Public ProgressNotify As IProgressCallBack
Public Sub DoWork()
    Dim l As Long
    For l = 1 to 100
        Sleep 10 'sleep for 1/100 of a second
        ProgressNotify.NotifyProgress 1, False
    Next
End Sub

VB6 EXE

Implements IProgressCallBack
Dim m_oMainFunc As MainFunctions

Private Sub cmdStart_Click()
    Set m_oMainFunc = New MainFunctions
    Set m_oMainFunc.ProgressNotify = Me
    m_oMainFunc.DoWork
    Set m_oMainFunc = Nothing
End Sub

Public Function IProgressCallBack_NotifyProgress(ByVal Progress As Single, isCancel As Boolean) As Boolean
    lblStatus.Caption = CStr(Round(Progress)) & "%"
    pbStatus.Value = Round(Progress)
    Me.Refresh
End Function

Thanks, Chris

Upvotes: 1

Views: 604

Answers (1)

Chris Calvert
Chris Calvert

Reputation: 129

I have not exactly found the answer to the question I posted above, but I have found a nice workaround. Essentially I pass in the form as an object to the class pretending to be an interface and directly call the interface method that resides on the form to update the screen. Here is the code sample of how I do this:

VB.NET DLL: IProgressCallBack Class

Dim m_oForm As Object

Public Sub New(ByRef oForm As Object)
    m_oForm = oForm
End Sub

Public Function NotifyProgress(ByVal Progress As Single, ByRef isCancel As Boolean) As Boolean
m_oForm.IProgressCallBack_NotifyProgress(Progress, isCancel)
End Function

VB.NET DLL: MainFunctions Class

Public ProgressNotify As IProgressCallBack

Public Sub New()
    'Need Public Sub New() with no parameters for all Com Classes
    MyBase.New()
End Sub

Public Sub Initialize(ByRef oForm As Object)
    ProgressNotify = New IProgressCallBack(oForm)
End Sub

Public Sub DoWork()
    For l As Long = 1 to 100
        Threading.Thread.Sleep(10) 'sleep for 1/100 of a second
        ProgressNotify.NotifyProgress(l,False)
    Next
End Sub

VB6 EXE

Dim m_oMainFunc As TestDLL_Net.MainFunctions
Private cmdStart_Click()
    Set m_oMainFunc = New TestDLL_Net.MainFunctions
    m_oMainFunc.Initialize Me
    m_oMainFunc.DoWork
    Set m_oMainFunc = Nothing
End Sub

Public Function IProgressCallBack_NotifyProgress(ByVal Progress As Single, isCancel As Boolean) As Boolean
    DoEvents
    lblStatus.Caption = CStr(Round(Progress)) & "%"
    Me.Refresh
    pbStatus.Value = Round(Progress)
End Function

This provides the same result as the VB6 DLL to VB6 EXE example posted above, and the changes in the EXE are minimal to make it work.

Thanks, Chris

Upvotes: 1

Related Questions