Introduction to Add-In Programming (Article)
Author: Ovidiu C.
Version Compatibility: Visual Basic 6, Visual Basic 5
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.