Programming VBE Add-ins -MZ-Tools P4
Programming VBE Add-ins -MZ-Tools P4
HOWTO: Create a toolwindow for the VBA editor of Office from an add-in with Visual Studio .NET.
Author: Carlos J. Quintero (Microsoft MVP) Applies to: Microsoft Office 64-bit
Date: September 2012 Microsoft Office 32-bit
Introduction
This article explains how to create a toolwindow (dockable window like the Project Explorer) from an add-in for the VBA editor of Office using Visual Studio
.NET and the .NET Framework.
The sample code creates two buttons on the Standard toolbar that show a different toolwindow each one.
More information
Toolwindows are dockable, modeless windows that are created calling the VBE.Windows.CreateToolWindow method. This method returns a VBE.Window
instance, which can be made visible setting its Window.Visible property to True. When closed, toolwindows are not destroyed. Rather, they are made
invisible.
Toolwindows host ActiveX UserDocuments inside, but UserDocuments don't exist in .NET. Fortunately, Usercontrols can be used instead, with one caveat:
the toolwindow doesn't resize a UserControl automatically as it does with a UserDocument when creating add-ins with Visual Basic 6.0 (the sample code
provides a workaround).
(Input) The add-in instance (that was received in the OnConnection method).
(Input) The ProgId of the ActiveX UserDocument (or UserControl) that will be hosted. This class must be Public and visible to COM (so it needs the
ComVisible attribute and set to True), and must be registered on the machine.
(Input) The caption of the toolwindow.
(Input) A GUID to uniquely identify the toolWindow. The VBA editor uses this GUID to store information specific to each toolwindow, such as its size or
position.
(Output )The instance of the usercontrol that the method has created from the ProgId that you passed as second parameter.
Create an add-in for the VBA editor of Microsoft Office as explained in the article HOWTO: Create an add-in for the VBA editor (32-bit or 64-bit) of
Office with Visual Studio .NET.
Add two usercontrols named UserControlToolWindow1.vb and UserControlToolWindow2.vb.
Add a usercontrol named UserControlHost.vb to the project. This is the common usercontrol that will be hosted by all toolwindows when calling the
VBE.Windows.CreateToolWindow method. In turn, this usercontrol will host the specific usercontrol of each toolwindow (UserControlToolWindow1 and
UserControlToolWindow2). This approach of using an intermediate usercontrol to host the actual usercontrols has the following advantages:
This UserControlHost control is the only one that needs to be Public and COM-registered. Otherwise each usercontrol of each toolwindow should
be COM-registered.
It provides a centralized workaround for the resizing problem.
It provides a centralized workaround for a problem that exists in toolwindows of the VBA editor and VB5 (but not in VB6): keys such as Tab,
Return, etc. don't work.
Change the code of the Connect.vb file by the code below. The code creates two buttons on the Standard toolbar that shows different toolwindows.
When a button is clicked, if the toolwindow is not created yet, it is created. Since when closing toolwindows they are not destroyed, just hidden, if the
toolwindow was already created it is made visible.
Imports MyCompany.Interop
Imports MyCompany.Interop.Extensibility
Imports System.Windows.Forms
Imports System.Runtime.InteropServices
Imports Microsoft.Office.Core
Imports System.Drawing
Try
Case ext_ConnectMode.ext_cm_Startup
' OnStartupComplete will be called
Case ext_ConnectMode.ext_cm_AfterStartup
InitializeAddIn()
End Select
Catch ex As Exception
MessageBox.Show(ex.ToString())
End Try
End Sub
_CommandBarButton1.Delete()
_CommandBarButton1 = Nothing
End If
_CommandBarButton2.Delete()
_CommandBarButton2 = Nothing
End If
End Sub
InitializeAddIn()
End Sub
End Sub
End Sub
Try
standardCommandBar = _VBE.CommandBars.Item("Standard")
commandBarControl = standardCommandBar.Controls.Add(MsoControlType.msoControlButton)
_CommandBarButton1 = DirectCast(commandBarControl, CommandBarButton)
_CommandBarButton1.Caption = "Toolwindow 1"
_CommandBarButton1.FaceId = 59
_CommandBarButton1.Style = MsoButtonStyle.msoButtonIconAndCaption
_CommandBarButton1.BeginGroup = True
commandBarControl = standardCommandBar.Controls.Add(MsoControlType.msoControlButton)
_CommandBarButton2 = DirectCast(commandBarControl, CommandBarButton)
_CommandBarButton2.Caption = "Toolwindow 2"
_CommandBarButton2.FaceId = 59
_CommandBarButton2.Style = MsoButtonStyle.msoButtonIconAndCaption
_CommandBarButton2.BeginGroup = True
Catch ex As Exception
MessageBox.Show(ex.ToString())
End Try
End Sub
' IMPORTANT: ensure that you use the same ProgId value used in the ProgId attribute of the UserControlHost class
progId = "MyVBAAddin.UserControlHost"
toolWindow.Visible = True
userControlHost.AddUserControl(toolWindowUserControl)
Return toolWindow
End Function
Try
userControlToolWindow1.Initialize(_VBE)
Else
_toolWindow1.Visible = True
End If
Catch ex As Exception
MessageBox.Show(ex.ToString)
End Try
End Sub
Try
userControlToolWindow2.Initialize(_VBE)
Else
_toolWindow2.Visible = True
End If
Catch ex As Exception
MessageBox.Show(ex.ToString)
End Try
End Sub
End Class
Imports System.Runtime.InteropServices
Imports System.Windows.Forms
Imports System.Drawing
MyBase.WndProc(m)
End Sub
Me.ReleaseHandle()
MyBase.Finalize()
End Sub
End Class
<StructLayout(LayoutKind.Sequential)> _
Private Structure RECT
Friend Left As Integer
Friend Top As Integer
Friend Right As Integer
Friend Bottom As Integer
End Structure
Private Declare Function GetParent Lib "user32" (ByVal hWnd As IntPtr) As IntPtr
Private Declare Function GetClientRect Lib "user32" Alias "GetClientRect" (ByVal hWnd As IntPtr, ByRef lpRect As RECT) As Integer
_parentHandle = GetParent(Me.Handle)
control.Dock = DockStyle.Fill
Me.Controls.Add(control)
AdjustSize()
End Sub
AdjustSize()
End Sub
End If
End Sub
Case Keys.Tab
End If
Case Keys.Return
End If
End Select
End If
Return result
End Function
End Class
In the UserControlToolWindow1 usercontrol, add a Button named Button1 and some textboxes.
Replace the code of the UserControlToolWindow1 by the code below. The code sets the backcolor to red to identify this toolwindow.
Notice that the scope of the class has been changed to Friend, it doesn't need to be Public.
The usercontrol can store the VBE instance for whatever use.
When testing the toolwindow, check that the Tab / Shift+Tab keystrokes change the focus and that the Return key clicks the button, as expected.
Imports MyCompany.Interop.VBAExtensibility
Imports System.Windows.Forms
Me.BackColor = Drawing.Color.Red
_VBE = vbe
End Sub
End Sub
End Class
In the UserControlToolWindow2 usercontrol, add a Button named Button1 and some textboxes.
Replace the code of the UserControlToolWindow2 by the code below. The code sets the backcolor to blue to identify this toolwindow.
Notice that the scope of the class has been changed to Friend, it doesn't need to be Public.
The usercontrol can store the VBE instance for whatever use.
When testing the toolwindow, check that the Tab / Shift+Tab keystrokes change the focus and that the Return key clicks the button, as expected.
Imports MyCompany.Interop.VBAExtensibility
Imports System.Windows.Forms
Me.BackColor = Drawing.Color.Blue
_VBE = vbe
End Sub
End Sub
End Class
IMPORTANT: After building the project for the first time without errors, you need to register the dll as COM component (the Connect and
UserControlHost public types) using the regasm.exe tool with the /codebase argument as explained in the article HOWTO: Create an add-in for the
VBA editor (32-bit or 64-bit) of Office with Visual Studio .NET.
Related articles
HOWTO: Create an add-in for the VBA editor (32-bit or 64-bit) of Office with Visual Studio .NET
HOWTO: Adding buttons, commandbars and toolbars to the VBA editor of Office from an add-in with Visual Studio .NET