Click here to Skip to main content
15,885,683 members
Articles / Productivity Apps and Services / Microsoft Office

VBE CreateToolWindow

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
5 Jan 2012CPOL3 min read 27.4K   12   7
Create a custom dockable window in the VBA editor.

Introduction

To create a dockable window in the Microsoft Excel VBA Editor, you must make sure that you create a VBE (VBA) add-in and not an Excel add-in. This article quickly shows how to create a new custom window in the VBA editor making use of the CreateToolWindow method.

Background

Many of the articles on the web regarding COM add-ins for Office discuss add-ins for Excel, Word, or Outlook. But not too many talk about creating and add-in for the Visual Basic Editor of Excel. The VBE can be customised as well creating toolbars, menus, and dockable windows. The API can be found here: http://msdn.microsoft.com/en-us/library/aa443985%28v=vs.60%29.aspx.

The CreateToolWindow method can only be used if a true VBE COM add-in is built, and not with an Excel add-in. The CreateToolWindow method creates a new Tool window containing the indicated UserDocument object.

Using the code

Instead of building an add-in for Excel and calling the Run method to force the VBE to initialize from the OnConnection event, you can also build a VBE COM add-in for the VBA Editor. The only difference is the location of the Registry keys with respect to an Excel add-in. The same Registry entries need to be made, but placed in the following location: HKEY_CURRENT_USER/Software/Microsoft/VBA/VBE/6.0/Addins.

The VB6 project

Create a new ActiveX DLL project in VB6 and name it VBEDemo and add the following references to the project:

  • Microsoft Add-In Designer
  • Microsoft Visual Basic for Applications Extensibility 5.3
  • Microsoft Excel 14.0 Object Library
  • Microsoft Office 14.0 Object Library

Add a class called VBEConnect to the project and implement the IDTExtensibility2 interface in this class. Add a User Document to the project and name it CoolDoc, this User Document will be hosted in the new Tool window in the VBE. Declare two private variables at the top of the class, m_cooldoc as CoolDoc and m_window as VBIDE.Window. The m_window object will hold a reference to the Tool window that we are about to create. The VBEConnect class should now look something like this:

VBScript
Option Explicit

Implements AddInDesignerObjects.IDTExtensibility2

Private m_cooldoc As CoolDoc
private m_window as VBIDE.Window

Private Sub IDTExtensibility2_OnAddInsUpdate(custom() As Variant)
'do nothing
End Sub

Private Sub IDTExtensibility2_OnBeginShutdown(custom() As Variant)
'do nothing
End Sub

Private Sub IDTExtensibility2_OnConnection(ByVal Application As Object, _
        ByVal ConnectMode As AddInDesignerObjects.ext_ConnectMode, _
        ByVal AddInInst As Object, custom() As Variant)

On Error GoTo errorHandler

Dim app As VBIDE.VBE
Set app = Application

Set m_window = app.Windows.CreateToolWindow(AddInInst, "VBEDemo.CoolDoc", _
                   "My CoolDoc", "anystring",  m_cooldoc)
m_window.Visible = True

errorHandler:
Select Case Err.Number
Case 0
Case Else
    Debug.Print Err.Number & "  " & Err.Description
End Select
End Sub

Private Sub IDTExtensibility2_OnDisconnection(ByVal RemoveMode As _
            AddInDesignerObjects.ext_DisconnectMode, custom() As Variant)
'do nothing
End Sub

Private Sub IDTExtensibility2_OnStartupComplete(custom() As Variant)
'do nothing
End Sub

The magic happens in the OnConnection event. Here a VBIDE.VBE application object is declared that is used to call the CreateToolWindow method. The method takes the current add-in and User Document as arguments and this is where things go wrong if an Excel COM add-in is created. The AddInInst object must be a VBE add-in and not an Excel add-in!

In a previous project (an Excel add-in), I forced the VBE to start using the Run method and tried to execute CreateToolWindow, but that did not work. Just to show the difference, here is the code that does not work:

VBScript
Private Sub IDTExtensibility2_OnConnection(ByVal Application As Object, _
        ByVal ConnectMode As AddInDesignerObjects.ext_ConnectMode, _
        ByVal AddInInst As Object, custom() As Variant)

Dim gxlApp as Excel.Application
Set gxlApp = Application

Dim gxCAI as Excel.Addin
Set gxCAI = AddInInst

On Error Resume Next
''' Force the VBE to initialize.
gxlApp.Run "xhYe1lsGtd3soe2t4ns"
On Error GoTo errorHandler

Set m_window = app.Windows.CreateToolWindow(AddInInst, "VBEDemo.CoolDoc", 
                   "My CoolDoc", "anystring",  m_cooldoc)
m_window.Visible = True

errorHandler:
Select Case Err.Number
Case 0
Case Else
    Debug.Print Err.Number & " " & Err.Description
End Select
End Sub

Running the code

Before the add-in will work, it is necessary to compile the DLL and add it to the Registry using the regsvr32.exe command. The proper keys need to be created in the Windows Registry in the following location: HKEY_CURRENT_USER/Software/Microsoft/VBA/VBE/6.0/Addins.

The new key must be named after the project name and the class that is implementing the IDTExtensibility2 interface: VBEDemo.VBEConnect. The key needs to contain two DWORDs and two string values:

  • DWORD: CommandLineSafe | 0
  • DWORD: LoadBehavior | 3
  • String value: FriendlyName | VBEDemoToolWindow
  • String value: Description | A Tool Window VBE Addin Demo

When the Excel VBA editor is started, the add-in will load and the Tool window will appear. Of course, this does not do anything since no functionality has been added, but I had a grin from ear to ear having spent some hours searching the web to find out how to do it (without success if I may add) and reverting to trial and error. I hope this little super simple article may save other people a couple of hours.

History

  • First version: 2012-01-05 (yes, some people still use VB6).

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Systems Engineer RHEA
Netherlands Netherlands
I am an aerospace engineer with a passion for software engineering. I use my software engineering skills primarily to create solutions for other engineering domains such as the aerospace engineering domain. My focus lies mainly on software solutions to support collaborative Model Based System Engineering (MBSE). I have been involved for the last 20 years in designing space missions, satellites, other complex systems and software to support the design of these systems for organizations such as the European Space Agency (ESA), the German Aerospace Agency (DLR) as well as commercial companies such as Airbus DS and Thales.

Currently I am employed by RHEA and I spend most of my time, together with my team, to develop the Concurrent Design Platform (https://www.rheagroup.com/services-solutions/system-engineering/concurrent-design/download-cdp4-comet/) as well as life cycle management tools for the Space Industry. I am also an active owner of the Concurrent Design group on linked-in https://www.linkedin.com/groups/3420542 where you can find interesting posts and articles on Concurrent Design.

Comments and Discussions

 
QuestionImplements AddInDesignerObjects.IDTExtensibility2 Pin
Palewhale.12-Oct-16 14:57
professionalPalewhale.12-Oct-16 14:57 
AnswerRe: Implements AddInDesignerObjects.IDTExtensibility2 Pin
Sam Gerené13-Oct-16 5:12
Sam Gerené13-Oct-16 5:12 
GeneralRe: Implements AddInDesignerObjects.IDTExtensibility2 Pin
Palewhale.13-Oct-16 14:24
professionalPalewhale.13-Oct-16 14:24 
Thanks for replying. I sure can. See below the four (4) components in this project and the project file.
Project file-----------------------------------------------------:
Type=OleDll
Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#..\..\..\Windows\SysWOW64\stdole2.tlb#OLE Automation
Reference=*\G{2DF8D04C-5BFA-101B-BDE5-00AA0044DE52}#2.8#0#..\..\..\Program Files (x86)\Microsoft Office\Root\VFS\ProgramFilesCommonX86\Microsoft Shared\OFFICE16\MSO.DLL#Microsoft Office 16.0 Object Library
Reference=*\G{AC0714F2-3D04-11D1-AE7D-00A0C90F26F4}#1.0#0#..\..\..\Program Files (x86)\Common Files\DESIGNER\MSADDNDR.OLB#Microsoft Add-In Designer
Reference=*\G{00062FFF-0000-0000-C000-000000000046}#9.6#0#..\..\..\Program Files (x86)\Microsoft Office\Root\Office16\MSOUTL.OLB#Microsoft Outlook 16.0 Object Library
Reference=*\G{EF404E00-EDA6-101A-8DAF-00DD010F7EBB}#5.3#0#..\..\..\Program Files (x86)\Microsoft Visual Studio\VB98\VB6EXT.OLB#Microsoft Visual Basic 6.0 Extensibility
Class=Connect; Connect.cls
Module=modProjectGlobals; modProjectGlobals.bas
Class=COutlookEvents; COutlookEvents.cls
Class=COutlookControls; COutlookControls.cls
Startup="(None)"
HelpFile=""
Title="OutlookAddin"
Command32=""
Name="OutlookAddin"
HelpContextID="0"
CompatibleMode="1"
MajorVer=1
MinorVer=0
RevisionVer=0
AutoIncrementVer=1
ServerSupportFiles=1
VersionCompanyName="Microsoft"
CompilationType=-1
OptimizationType=0
FavorPentiumPro(tm)=0
CodeViewDebugInfo=0
NoAliasing=0
BoundsCheck=0
OverflowCheck=0
FlPointCheck=0
FDIVCheck=0
UnroundedFP=0
StartMode=1
Unattended=0
Retained=0
ThreadPerObject=0
MaxNumberOfThreads=1
ThreadingModel=1
RemoveUnusedControlInfo=0
DebugStartupOption=0

Connect.cls-----------------------------------------------------:
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
Persistable = 0 'NotPersistable
DataBindingBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
MTSTransactionMode = 0 'NotAnMTSObject
END
Attribute VB_Name = "Connect"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = True
Attribute VB_Ext_KEY = "SavedWithClassBuilder6" ,"Yes"
Attribute VB_Ext_KEY = "Top_Level" ,"Yes"
Option Explicit
Option Compare Text

'Implements AddInDesignerObjects.IDTExtensibility2
Implements IDTExtensibility2


'''''''''''''''''''''''''''''''''''''''''''''''''
' Declare procedures for all the methods defined
' in the IDTExtensibility2 interface.
'''''''''''''''''''''''''''''''''''''''''''''''''
Private Sub IDTExtensibility2_OnAddInsUpdate(custom() As Variant)
' not used
End Sub

Private Sub IDTExtensibility2_OnBeginShutdown(custom() As Variant)
' not used
End Sub

Private Sub IDTExtensibility2_OnStartupComplete(custom() As Variant)
' not used
End Sub

Private Sub IDTExtensibility2_OnConnection(ByVal Application As Object, _
ByVal ConnectMode As AddInDesignerObjects.ext_ConnectMode, _
ByVal AddInInst As Object, custom() As Variant)
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' IDTExtensibility2_OnConnection
' This is called when the add-in is connected to the host application (e.g., Excel).
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

'''''''''''''''''''''''''''''''''''''''''''''''''
' Set ThisCAI to the instance of this COM Add-In.
'''''''''''''''''''''''''''''''''''''''''''''''''
Set ThisCAI = AddInInst
Set ConnectInst = Me

'''''''''''''''''''''''''''''''''''''''''''''''''
' See if we're connecting to Excel. If so, set up
' the appropriate variables.
'''''''''''''''''''''''''''''''''''''''''''''''''
If TypeOf Application Is Excel.Application Then
Set ExcelApp = Application
Set ExcelEvents = New CExcelEvents
Set ExcelEvents.ExcelApp = Application
Set ExcelControls = New CExcelControls
Set ExcelControls.ExcelApp = Application
ExcelControls.CreateControls
End If

'''''''''''''''''''''''''''''''''''''''''''''''''
' See if we're connecting to PowerPoint. If so, set up
' the appropriate variables.
'''''''''''''''''''''''''''''''''''''''''''''''''
If TypeOf Application Is PowerPoint.Application Then
Set PowerPointApp = Application
Set PowerPointEvents = New CPowerPointEvents
Set PowerPointEvents.PowerPointApp = Application
Set PowerPointControls = New CPowerPointControls
Set PowerPointControls.PowerPointApp = Application
PowerPointControls.CreateControls
End If

End Sub

Private Sub IDTExtensibility2_OnDisconnection(ByVal RemoveMode As AddInDesignerObjects.ext_DisconnectMode, _
custom() As Variant)
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' IDTExtensibility2_OnDisconnection
' This executes when the COM Add-In is unloaded by the host application.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

''''''''''''''''''''''''''''''''
' Clean up Excel
''''''''''''''''''''''''''''''''
If Not ExcelApp Is Nothing Then
'''''''''''''''''''''''''''''''''
' Set ALL Excel objects to Nothing.
' Otherwise they can cause the
' Excel process to continue to
' run in the background even
' after it appears to be closed.
'''''''''''''''''''''''''''''''''
Set ExcelEvents.ExcelApp = Nothing
Set ExcelEvents = Nothing
ExcelControls.DeleteControls
Set ExcelControls = Nothing
Set ExcelApp = Nothing
End If

''''''''''''''''''''''''''''''''
' Clean up PowerPoint
''''''''''''''''''''''''''''''''
If Not PowerPointApp Is Nothing Then
'''''''''''''''''''''''''''''''''
' Set ALL PowerPoint objects to Nothing.
' Otherwise they can cause the
' Excel process to continue to
' run in the background even
' after it appears to be closed.
'''''''''''''''''''''''''''''''''
Set PowerPointEvents.PowerPointApp = Nothing
Set PowerPointEvents = Nothing
PowerPointControls.DeleteControls
Set PowerPointControls = Nothing
Set PowerPointApp = Nothing
End If

Set ThisCAI = Nothing

End Sub

modProjectGlobals.bas-------------------------------------------------:
Attribute VB_Name = "modProjectGlobals"
Option Explicit
Option Compare Text
Option Private Module
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' ExampleConnect
' By Chip Pearson, www.cpearson.com, chip@cpearson.com
' This module contains project-wide globals and constants
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

''''''''''''''''''''''''''''''''''''''''''''''''''''
' CONSTANTS
''''''''''''''''''''''''''''''''''''''''''''''''''''
Public Const C_OUTLOOK_TOOLS_MENU_ID As Long = 30007

'''''''''''''''''''''''''''''''''''''''''''''''''''
' VARIABLES
'''''''''''''''''''''''''''''''''''''''''''''''''''

''''''''''''''''''''''''''''''''''''''''''''''''
' This is an instance of the COM Add-In inself.
''''''''''''''''''''''''''''''''''''''''''''''''
Public ThisCAI As Office.COMAddIn
''''''''''''''''''''''''''''''''''''''''''''''''
' These are references to the host applications.
''''''''''''''''''''''''''''''''''''''''''''''''
Public OutlookApp As Outlook.Application
''''''''''''''''''''''''''''''''''''''''''''''''
' These are the application event handlers.
''''''''''''''''''''''''''''''''''''''''''''''''
Public OutlookEvents As COutlookEvents
''''''''''''''''''''''''''''''''''''''''''''''''
' This references the Connect object.
''''''''''''''''''''''''''''''''''''''''''''''''
Public ConnectInst As Connect

''''''''''''''''''''''''''''''''''''''''''''''''
' Instance of Menus
''''''''''''''''''''''''''''''''''''''''''''''''
Public OutlookControls As CExcelControls

COutlookEvents.cls--------------------------------------------------:
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
Persistable = 0 'NotPersistable
DataBindingBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
MTSTransactionMode = 0 'NotAnMTSObject
END
Attribute VB_Name = "COutlookEvents"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Attribute VB_Ext_KEY = "SavedWithClassBuilder6" ,"Yes"
Attribute VB_Ext_KEY = "Top_Level" ,"Yes"
Option Explicit
Option Compare Text

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' COutlookEvents
' By Chip Pearson, www.cpearson.com, chip@cpearson.com
' This module handles events from the Outlook application.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Private WithEvents pOutlookApp As Outlook.Application
Attribute pOutlookApp.VB_VarHelpID = -1

Friend Property Get OutlookApp() As Outlook.Application
Set OutlookApp = pOutlookApp
End Property

Friend Property Set OutlookApp(OLApp As Outlook.Application)
Set pOutlookApp = OLApp
End Property

Private Sub Class_Terminate()
Set pOutlookApp = Nothing
End Sub

Private Sub pOutlookApp_ItemLoad(ByVal Item As Object)
MsgBox TypeName(Item) & " Item Load", vbInformation, "pOutlookApp_ItemLoad"
End Sub

Private Sub pOutlookApp_ItemSend(ByVal Item As Object, Cancel As Boolean)
MsgBox TypeName(Item) & " Item Send", vbInformation, "pOutlookApp_ItemSend"
End Sub

Private Sub pOutlookApp_NewMail()
MsgBox "pOutlookApp_NewMail"
End Sub

Private Sub pOutlookApp_NewMailEx(ByVal EntryIDCollection As String)
MsgBox "pOutlookApp_NewMailEx"
End Sub

COutlookControls.cls----------------------------------------------------:
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
Persistable = 0 'NotPersistable
DataBindingBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
MTSTransactionMode = 0 'NotAnMTSObject
END
Attribute VB_Name = "COutlookControls"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Attribute VB_Ext_KEY = "SavedWithClassBuilder6" ,"Yes"
Attribute VB_Ext_KEY = "Top_Level" ,"Yes"
Option Explicit
Option Compare Text
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' COutlookMenus
' This class contains the definitions, creation code, and event procedures for the
' menu items for Outlook.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

'''''''''''''''''''''''''''''''''''''''''''''
' Private reference to the Outlook Application.
'''''''''''''''''''''''''''''''''''''''''''''
Private pOutlookApp As Outlook.Application

'''''''''''''''''''''''''''''''''''''''''''''''''
' Reference to the Tools menu in Outlook.
'''''''''''''''''''''''''''''''''''''''''''''''''
Private OutlookToolsMenu As Office.CommandBarPopup

'''''''''''''''''''''''''''''''''''''''''''''
' One test menu item.
'''''''''''''''''''''''''''''''''''''''''''''
Private WithEvents MenuItem1 As Office.CommandBarButton
Attribute MenuItem1.VB_VarHelpID = -1

''''''''''''''''''''''''''''''''''''''''
' All controls created in this module
' should have be stored in this Collection.
' We keep references in a Collection to
' make it easy to delete them when the
' add-in is disconnected. Since we're
' not using the Tag property (to allow
' for separate event handlers for
' each control), we need an easy way
' to get a reference to each control
' when we delete them.
''''''''''''''''''''''''''''''''''''''''
Private ControlsCollection As Collection

'''''''''''''''''''''''''''''''''''''''''
' Property to Get/Set the reference
' to the Outlook application.
'''''''''''''''''''''''''''''''''''''''''
Friend Property Get OutlookApp() As Outlook.Application
Set OutlookApp = pOutlookApp
End Property

Friend Property Set OutlookApp(OLApp As Outlook.Application)
Set pOutlookApp = OLApp
End Property

Friend Sub CreateControls()
'''''''''''''''''''''''''''''''''''''''''''''''''''
' CreateControls
' This is where you would create all of your menu
' items and commandbar controls. Store each one
' in the ControlCollection object so we can
' easily delete them when the add-in disconnects.
' Note that we are NOT using either the Tag
' property or the OnAction property.
'''''''''''''''''''''''''''''''''''''''''''''''''''

Set OutlookToolsMenu = pOutlookApp.CommandBars.FindControl(Id:=C_OUTLOOK_TOOLS_MENU_ID)
Set MenuItem1 = OutlookToolsMenu.Controls.Add(Type:=msoControlButton, temporary:=True)
With MenuItem1
.Caption = "Click Me #1"
End With
ControlsCollection.Add Item:=MenuItem1

'''''''''''''''''''''''''
' Repeat the code above
' for each control you
' need to add.
'''''''''''''''''''''''''

End Sub

Friend Sub DeleteControls()
'''''''''''''''''''''''''''''''''''''''''''''''''''''
' DeleteControls
' This loops through the ControlsCollection object
' and deletes all of our controls.
'''''''''''''''''''''''''''''''''''''''''''''''''''''
Dim Ndx As Long
Dim Ctrl As Office.CommandBarControl
For Ndx = ControlsCollection.Count To 1 Step -1
Set Ctrl = ControlsCollection(Ndx)
Ctrl.Delete
ControlsCollection.Remove Ndx
Next Ndx

End Sub

Private Sub Class_Initialize()
'''''''''''''''''''''''''''''''''''''''''''''''''''''
' Class_Initialize
' Create a new Collection object.
'''''''''''''''''''''''''''''''''''''''''''''''''''''
Set ControlsCollection = New Collection
End Sub

Private Sub Class_Terminate()
'''''''''''''''''''''''''''''''''''''''''''''''''''''
' Class_Terminate
' Destroy the Collection
'''''''''''''''''''''''''''''''''''''''''''''''''''''
Set ControlsCollection = Nothing
End Sub

Private Sub MenuItem1_Click(ByVal Ctrl As Office.CommandBarButton, _
CancelDefault As Boolean)
'''''''''''''''''''''''''''''''''''''''''''''''''''''
' MenuItem1_Click
' Event procedure for menu item.
'''''''''''''''''''''''''''''''''''''''''''''''''''''
MsgBox Ctrl.Caption
End Sub

-----------End of code------------------------------------------------------

Sam, not all of it may make sense. I took the samples which were for Excel and changed "Excel" words/references/etc to "Outlook" - well it was a little more complex than that simple explanation.
But neither my changed code nor the original example (Excel oriented) would get any further - run or compile - than complaining about the "Implements..." statement.

If you can shed any light in why, I would appreciate that.

Jef.
GeneralRe: Implements AddInDesignerObjects.IDTExtensibility2 Pin
Sam Gerené13-Oct-16 21:36
Sam Gerené13-Oct-16 21:36 
Questionhow can I create a VBE (VBA) add-in in VS2010 Pin
Tracy Jia8-Jul-14 22:23
Tracy Jia8-Jul-14 22:23 
AnswerRe: how can I create a VBE (VBA) add-in in VS2010 Pin
Sam Gerené8-Jul-14 22:32
Sam Gerené8-Jul-14 22:32 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.