Introduction to Add-In Programming (Article)

Category:
Miscellaneous
Type:
Snippets
Difficulty:
Intermediate

Author: Ovidiu C.

Version Compatibility: Visual Basic 6, Visual Basic 5

More information:
This article provides an introduction to creating an Add-in in VB6 by walking through creation of a sample add-in

Instructions: 

Let's see in this article how to create an add-in used in VB IDE which gets all the controls of current VB project. In this small example all the controls of all forms of the project will be displayed into the list-box, but this method can be used to change some of the properties of the controls or any other operation to the controls.

The algorithm is reccursive and work with all container-controls, even on multiple levels (for instance a frame in another frame).

I want to keep this program as simply as possible so, there is only the basic functionality. In the beginning, we add a new ActiveX DLL and name the project "AllControls" with a class called "Connect.cls", a form ("frmMain.frm") and a class-module ("mAllControls.bas").

Then add a reference (Project | References...) to "Microsoft Visual Basic 6.0 Extensibility" and "Microsoft Office 8.0 Library" (or newer).

The class "Connect" (or any name you used in your own add-in) has to implement a specific class called "IDTExtensibility". Doing so, the class has to implement 4 methods of this interface, used by the IDE automatically. These methods are: OnConnection(), OnDisconnection(), OnAddInsUpdate() and OnStartupComplete(). The last 2 methods are optionally, but you have ti add at least an empty commented line, otherwise these methods are deleted by the compiler (this will cause an error). As you may guess the first method is used any time when the add-in is loaded, and the last one when the IDE is closed or the add-in is unloaded.

To add a custom menu item or a new toolbar you can use the objects exposed by "MS Office Library". All we are doing when the add-in is loaded and the method IDTExtensibility_OnConnection() is executed is to create a new menu item under "Add-ins" item with an event, then save the instance of the IDE passed as parameter to this method into a global variable and show the main form of the add-in. The instance of VB IDE is used in the form. In the method IDTExtensibility_OnDisconnection() all the objects are destroyed and the form is unloaded (if isn't already unloaded).

See the code of the class below.

Implements IDTExtensibility

Private m_mnuAddIns As CommandBar
Private m_mnuOpen As CommandBarControl
Private WithEvents m_evtCmdOpen As CommandBarEvents

Private Sub IDTExtensibility_OnAddInsUpdate(custom() _
   As Variant)
'
End Sub

Private Sub IDTExtensibility_OnConnection _
  (ByVal VBInst As Object, ByVal ConnectMode As VBIDE.vbext_ConnectMode, _
  ByVal AddInInst As VBIDE.AddIn, _
   custom() As Variant)
On Error Resume Next

Set m_mnuAddIns = VBInst.CommandBars("Add-Ins")
If Not m_mnuAddIns Is Nothing Then
    Set m_mnuOpen = m_mnuAddIns.Controls.Add(msoControlButton)
    m_mnuOpen.Caption = "Open AllControls form..."
    Set m_evtCmdOpen = VBInst.Events.CommandBarEvents(m_mnuOpen)
End If

Set gVBInst = VBInst
frmMain.Show
End Sub

Private Sub IDTExtensibility_OnDisconnection _
  (ByVal RemoveMode As _
   VBIDE.vbext_DisconnectMode, custom() As Variant)
On Error Resume Next
Set gVBInst = Nothing
Set m_evtMenuOpen = Nothing
m_mnuOpen.Delete
Set m_mnuOpen = Nothing
Set m_mnuAddIns = Nothing
Unload frmMain
End Sub

Private Sub IDTExtensibility_OnStartupComplete _
   (custom() As Variant)
'
End Sub

Private Sub m_evtCmdOpen_Click _
  (ByVal CommandBarControl As Object, _
   handled As Boolean, _
   CancelDefault As Boolean)
On Error Resume Next
frmMain.Show
End Sub

The module "mAllControls.bas" has only one line to declare a global object to the instance of VB IDE:

Public gVBInst As VBIDE.VBE

Finally, let's see the form of the add-in, with a reccursive function get all controls.

Private Sub cmdAllControls_Click()
Dim comp As VBComponent
Dim ctrl As VBControl
Dim vbf As VBForm
lstControls.Clear
For Each comp In gVBInst.ActiveVBProject.VBComponents
    If (comp.Type = vbext_ct_MSForm Or _
        comp.Type = vbext_ct_UserControl _
          Or comp.Type = vbext_ct_VBForm Or _
         comp.Type = vbext_ct_VBMDIForm) Then
        lstControls.AddItem comp.Name & " components"
        Set vbf = comp.Designer
        For Each ctrl In vbf.ContainedVBControls
lstControls.AddItem "    " & ctrl.Properties("Name").Value & " _
               [" & ctrl.ClassName & "]"
            control_rec ctrl, 1
        Next
        Set vbf = Nothing
    End If
Next
End Sub

Sub control_rec _
    (ByVal f As VBControl, _
     ByVal level As Long)
Dim ctrl As VBControl
For Each ctrl In _
    f.ContainedVBControls
    lstControls.AddItem Space$(level * 4) & _
      "    " & ctrl.Properties("Name").Value & _
      " [" & ctrl.ClassName & "]"
    If ctrl.ContainedVBControls.Count >  0 Then control_rec ctrl, level + 1
Next
End Sub

This is all. As you can see, is not need to use the "Addin" type of project or isn't need to use a designer. Also, be aware that all the add-ins have to be register in VBAddin.ini, from %WINDIR% folder (generally, C:\Windows or C:\WinNT). In this project, you have to add by hand the following line:

AllControls.Connect = 0

After this you can load the project directlly into your VB IDE by selecting the class of the project from "Add-ins | Add-in Manager..." and then check the option "Load / Unload" and/or "Load on Startup".

This functionality and many more other are available in VB CodeUtility Add-in (see under "Programs"). Using add-ins you really can enhance the programming process because many tasks can be automated - for instance: inserting comments or error handlers, export the code as HTML, changing or deleting controls or forms with their properties or events, registering/unregistering third-party components, creating logs for the project and others.