Hosting .NET controls in VB6

I recently ran into a need to interop a C# .NET user control with a VB6 form.

We all know that VB6 only allows you to reference a user control if it resides in an OCX.

The Interop Forms Toolkit, mentioned here, seems to be only good for VB.NET user controls.

Prior to this, I've been able to get by with dynamically adding the control via Controls.Add {COMClassname}, {ControlName}

But now, I need to be able to manipulate the control in design time.

So, based on the above experience, I created a very basic VB6 user control called DotNetControlWrapper. The tricks with this control are the following:

  • There's a public property called DotNetClassName, which is a COM class name of the .NET control.

  • It delegates resizing logic to the .NET control.

  • It exposes the .NET control via a DotNetObject property, thus allowing the user to sync the control's events if needed.

The bulk of DotNetControlWrapper.ctl looks like this:

Option Explicit

Private object As Object
Private ctlExtender As VBControlExtender
Private mstrDotNetClass As String

Public Property Get DotNetClassName() As String
DotNetClassName = mstrDotNetClass
End Property
Public Property Let DotNetClassName(ByVal clsname As String)
mstrDotNetClass = clsname
If mstrDotNetClass = "" Then Exit Property
' initialize the .NET control
If Not ctlExtender Is Nothing Then
Controls.Remove UserControl.Extender.Name + "_dotnet"
End If
Set ctlExtender = Controls.Add(mstrDotNetClass, UserControl.Extender.Name + "_dotnet")
ctlExtender.ZOrder 0
Set object = ctlExtender.object
End Property

Private Sub UserControl_Resize()
If object Is Nothing Then Exit Sub
ctlExtender.Move 0, 0, UserControl.Width, UserControl.Height
object.BringToFront ' Bring the .NET control to foreground
End Sub

Private Sub UserControl_Show()
If ctlExtender Is Nothing Then Exit Sub
ctlExtender.Visible = True
End Sub

Public Property Get DotNetObject() As Object
Set DotNetObject = object
End Property

Private Sub UserControl_Terminate()
If ctlExtender Is Nothing Then Exit Sub
Set ctlExtender = Nothing
Set object = Nothing
End Sub

Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
PropBag.WriteProperty "DotNetClassName", mstrDotNetClass
PropBag.WriteProperty "Width", UserControl.Width
PropBag.WriteProperty "Height", UserControl.Height
End Sub

Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
On Error Resume Next
DotNetClassName = PropBag.ReadProperty("DotNetClassName")
Width = PropBag.ReadProperty("Width")
Height = PropBag.ReadProperty("Height")
End Sub