0% found this document useful (0 votes)
3 views6 pages

Programming VBE Add-ins -MZ-Tools P4

This document provides a detailed guide on creating a tool window for the VBA editor in Microsoft Office using Visual Studio .NET. It explains the necessary steps to implement a dockable window, including sample code for creating user controls and handling events. The article also addresses specific issues related to resizing and key handling in the tool window environment.

Uploaded by

Cerebral007
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
0% found this document useful (0 votes)
3 views6 pages

Programming VBE Add-ins -MZ-Tools P4

This document provides a detailed guide on creating a tool window for the VBA editor in Microsoft Office using Visual Studio .NET. It explains the necessary steps to implement a dockable window, including sample code for creating user controls and handling events. The article also addresses specific issues related to resizing and key handling in the tool window environment.

Uploaded by

Cerebral007
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
Download as pdf or txt
You are on page 1/ 6

HOWTO: Create a toolwindow for the VBA editor of Office from an ad... https://web.archive.org/web/20211024050815/https://www.mztools.com/...

The Wayback Machine - https://web.archive.org/web/20211024050815/https://www.mztools.com/articles/2012/MZ2012017.aspx

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).

The VBE.Windows.CreateToolWindow method has these parameters:

(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.

To create the sample use the following steps:

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.

Language: VB.NET Copy Code (IE only)

Imports MyCompany.Interop
Imports MyCompany.Interop.Extensibility
Imports System.Windows.Forms
Imports System.Runtime.InteropServices
Imports Microsoft.Office.Core
Imports System.Drawing

<ComVisible(True), Guid(PUT_NEW_GUID_HERE), ProgId("MyVBAAddin.Connect")> _


Public Class Connect
Implements IDTExtensibility2

Private _VBE As VBAExtensibility.VBE


Private _AddIn As VBAExtensibility.AddIn
Private WithEvents _CommandBarButton1 As CommandBarButton
Private WithEvents _CommandBarButton2 As CommandBarButton

Private _toolWindow1 As VBAExtensibility.Window


Private _toolWindow2 As VBAExtensibility.Window

Private Sub OnConnection(Application As Object, ConnectMode As ext_ConnectMode, AddInInst As Object, _


ByRef custom As System.Array) Implements IDTExtensibility2.OnConnection

Try

_VBE = DirectCast(Application, VBAExtensibility.VBE)


_AddIn = DirectCast(AddInInst, VBAExtensibility.AddIn)

Select Case ConnectMode

Case ext_ConnectMode.ext_cm_Startup
' OnStartupComplete will be called

Case ext_ConnectMode.ext_cm_AfterStartup

1 sur 6 11/10/2023, 21:07


HOWTO: Create a toolwindow for the VBA editor of Office from an ad... https://web.archive.org/web/20211024050815/https://www.mztools.com/...

InitializeAddIn()

End Select

Catch ex As Exception

MessageBox.Show(ex.ToString())

End Try

End Sub

Private Sub OnDisconnection(RemoveMode As ext_DisconnectMode, _


ByRef custom As System.Array) Implements IDTExtensibility2.OnDisconnection

If Not _CommandBarButton1 Is Nothing Then

_CommandBarButton1.Delete()
_CommandBarButton1 = Nothing

End If

If Not _CommandBarButton2 Is Nothing Then

_CommandBarButton2.Delete()
_CommandBarButton2 = Nothing

End If

End Sub

Private Sub OnStartupComplete(ByRef custom As System.Array) _


Implements IDTExtensibility2.OnStartupComplete

InitializeAddIn()

End Sub

Private Sub OnAddInsUpdate(ByRef custom As System.Array) _


Implements IDTExtensibility2.OnAddInsUpdate

End Sub

Private Sub OnBeginShutdown(ByRef custom As System.Array) Implements IDTExtensibility2.OnBeginShutdown

End Sub

Private Sub InitializeAddIn()

Dim standardCommandBar As CommandBar


Dim commandBarControl As CommandBarControl

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

Private Function CreateToolWindow(ByVal toolWindowCaption As String, ByVal toolWindowGuid As String, _


ByVal toolWindowUserControl As UserControl) As VBAExtensibility.Window

Dim userControlObject As Object = Nothing


Dim userControlHost As UserControlHost
Dim toolWindow As VBAExtensibility.Window
Dim progId As String

' IMPORTANT: ensure that you use the same ProgId value used in the ProgId attribute of the UserControlHost class
progId = "MyVBAAddin.UserControlHost"

toolWindow = _VBE.Windows.CreateToolWindow(_AddIn, progId, toolWindowCaption, toolWindowGuid, userControlObject)


userControlHost = DirectCast(userControlObject, UserControlHost)

toolWindow.Visible = True

2 sur 6 11/10/2023, 21:07


HOWTO: Create a toolwindow for the VBA editor of Office from an ad... https://web.archive.org/web/20211024050815/https://www.mztools.com/...

userControlHost.AddUserControl(toolWindowUserControl)

Return toolWindow

End Function

Private Sub _CommandBarButton1_Click(Ctrl As Microsoft.Office.Core.CommandBarButton, _


ByRef CancelDefault As Boolean) Handles _CommandBarButton1.Click

Dim userControlObject As Object = Nothing


Dim userControlToolWindow1 As UserControlToolWindow1

Try

If _toolWindow1 Is Nothing Then

userControlToolWindow1 = New UserControlToolWindow1()

' TODO: Change the GUID


_toolWindow1 = CreateToolWindow("My toolwindow 1", "{PUT_NEW_GUID_HERE}", userControlToolWindow1)

userControlToolWindow1.Initialize(_VBE)

Else

_toolWindow1.Visible = True

End If

Catch ex As Exception

MessageBox.Show(ex.ToString)

End Try

End Sub

Private Sub _CommandBarButton2_Click(Ctrl As Microsoft.Office.Core.CommandBarButton, _


ByRef CancelDefault As Boolean) Handles _CommandBarButton2.Click

Dim userControlObject As Object = Nothing


Dim userControlToolWindow2 As UserControlToolWindow2

Try

If _toolWindow2 Is Nothing Then

userControlToolWindow2 = New UserControlToolWindow2()

' TODO: Change the GUID


_toolWindow2 = CreateToolWindow("My toolwindow 2", "{PUT_NEW_GUID_HERE}", userControlToolWindow2)

userControlToolWindow2.Initialize(_VBE)

Else

_toolWindow2.Visible = True

End If

Catch ex As Exception

MessageBox.Show(ex.ToString)

End Try

End Sub

End Class

Replace the code of UserControlHost by the code below.


Notice that the scope of the usercontrol must be Public, and that it must have a ProgId and be visible to COM.
This usercontrol will host the actual usercontrol of the toolwindow (which will have the DockStyle.Fill).
It needs to do subclassing with the parent window to detect when the size is changed.
It needs to override the ProcessKeyPreview method to detect the Tab, Shift+Tab and Return keys, to make them behave as expected.

Language: VB.NET Copy Code (IE only)

Imports System.Runtime.InteropServices
Imports System.Windows.Forms
Imports System.Drawing

<ComVisible(True), Guid(PUT_NEW_GUID_HERE), ProgId("MyVBAAddin.UserControlHost")> _


Public Class UserControlHost

Private Class SubClassingWindow


Inherits System.Windows.Forms.NativeWindow

Public Event CallBackProc(ByRef m As Message)

3 sur 6 11/10/2023, 21:07


HOWTO: Create a toolwindow for the VBA editor of Office from an ad... https://web.archive.org/web/20211024050815/https://www.mztools.com/...

Public Sub New(ByVal handle As IntPtr)


MyBase.AssignHandle(handle)
End Sub

Protected Overrides Sub WndProc(ByRef m As Message)

Const WM_SIZE As Integer = &H5;

If m.Msg = WM_SIZE Then


RaiseEvent CallBackProc(m)
End If

MyBase.WndProc(m)

End Sub

Protected Overrides Sub Finalize()

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

Private _parentHandle As IntPtr


Private WithEvents _subClassingWindow As SubClassingWindow

Friend Sub AddUserControl(ByVal control As UserControl)

_parentHandle = GetParent(Me.Handle)

_subClassingWindow = New SubClassingWindow(_parentHandle)

control.Dock = DockStyle.Fill

Me.Controls.Add(control)

AdjustSize()

End Sub

Private Sub _subClassingWindow_CallBackProc(ByRef m As System.Windows.Forms.Message) Handles _subClassingWindow.CallBackProc

AdjustSize()

End Sub

Private Sub AdjustSize()

Dim tRect As RECT

If GetClientRect(_parentHandle, tRect) <> 0 Then

Me.Size = New Size(tRect.Right - tRect.Left, tRect.Bottom - tRect.Top)

End If

End Sub

Protected Overrides Function ProcessKeyPreview(ByRef m As System.Windows.Forms.Message) As Boolean

Const WM_KEYDOWN As Integer = &H100;

Dim result As Boolean = False


Dim pressedKey As Keys
Dim hostedUserControl As UserControl
Dim activeButton As Button

hostedUserControl = DirectCast(Me.Controls.Item(0), UserControl)

If m.Msg = WM_KEYDOWN Then

pressedKey = CType(m.WParam, Keys)

Select Case pressedKey

Case Keys.Tab

If Control.ModifierKeys = Keys.None Then ' Tab

4 sur 6 11/10/2023, 21:07


HOWTO: Create a toolwindow for the VBA editor of Office from an ad... https://web.archive.org/web/20211024050815/https://www.mztools.com/...

Me.SelectNextControl(hostedUserControl.ActiveControl, True, True, True, True)


result = True

ElseIf Control.ModifierKeys = Keys.Shift Then ' Shift + Tab

Me.SelectNextControl(hostedUserControl.ActiveControl, False, True, True, True)


result = True

End If

Case Keys.Return

If TypeOf hostedUserControl.ActiveControl Is Button Then

activeButton = DirectCast(hostedUserControl.ActiveControl, Button)


activeButton.PerformClick()

End If

End Select

End If

If result = False Then


result = MyBase.ProcessKeyPreview(m)
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.

Language: VB.NET Copy Code (IE only)

Imports MyCompany.Interop.VBAExtensibility
Imports System.Windows.Forms

Friend Class UserControlToolWindow1

Private _VBE As VBE

Friend Sub Initialize(ByVal vbe As VBE)

Me.BackColor = Drawing.Color.Red

_VBE = vbe

End Sub

Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click

MessageBox.Show("Toolwindow shown in VBA editor version " & _VBE.Version)

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.

Language: VB.NET Copy Code (IE only)

Imports MyCompany.Interop.VBAExtensibility
Imports System.Windows.Forms

Friend Class UserControlToolWindow2

Private _VBE As VBE

Friend Sub Initialize(ByVal vbe As VBE)

Me.BackColor = Drawing.Color.Blue

_VBE = vbe

End Sub

5 sur 6 11/10/2023, 21:07


HOWTO: Create a toolwindow for the VBA editor of Office from an ad... https://web.archive.org/web/20211024050815/https://www.mztools.com/...

Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click

MessageBox.Show("Toolwindow shown in VBA editor version " & _VBE.Version)

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

Copyright © 2021 MZTools Software. All Rights Reserved. Legal Notice

6 sur 6 11/10/2023, 21:07

You might also like