[Tutorial] Make your own menu bar

Started by Lars-Erik, April 24, 2008, 06:16:14 AM

Previous topic - Next topic

0 Members and 2 Guests are viewing this topic.

Lars-Erik

As my template will be used by people who never worked with Visio I thought it might be smart to make a custom menu and set up the most important functions there. This way everything they need most will be easy to find.

Let's start by running the VBA editor. The quickest way to do this is hitting the Alt+F11 keys. Next use the Project explorer (may be hidden as default, if so press ctrl+R to make is visible). Macro's in the ThisDocument part of the project can watch for certain events. We want the menu to be loaded when the document is loaded. We also want ( or not, it's your choice ) it to be unloaded on closing the document of closing Visio.
So here goes:

Loading the menu:

Private Sub Document_DocumentCreated(ByVal doc As IVDocument)
MakeMenu
End Sub

Private Sub Document_DocumentOpened(ByVal doc As IVDocument)
MakeMenu
End Sub


These two subs will make sure the sub "MakeMenu" is called when the document is opened, or created. Simple enough so far. Next we are gone make a sub that can remove the menu when to document is closed.

Deleting the menu bar:

Sub DeleteMenu()
On Error Resume Next
Application.CommandBars("-").Controls(3).Delete
Application.CommandBars("Menu Bar").Controls("Your Menu Bar").Delete
On Error GoTo 0
End Sub


This sub will remove the "Your Menu Bar" menu from the Visio "Menu Bar". You can alter the names of the bars to make the sub delete different bars. I'll leave it as it is because we are going to make a menu bar with the name "Your Menu Bar" and nest it inside the main Visio bar.
The following sub will be triggered when the document is closed, note that when closing Visio itself this sub will never be triggered as the closing of Visio overwrites every document triggered event. It took me a while to figure out how to remove the menu bar when closing Visio but we will get to that a little later on. For now, deleting the menu on document close:

Private Sub Document_BeforeDocumentClose(ByVal doc As IVDocument)
DeleteMenu
End Sub


Personally I don't use this trigger because I found that opening two document that both use the menu will end up messing up your menu. When you close one of the two document, the remaining document will be left without menu. Therefore I leave the menu as it is until Visio is closed.
So, for the final bit. How do we create the menu. (I didn't write this code myself, most of it is googled, I'm sorry I didn't write down the programmer, but all credits go to him)

Configure the menubar:

Sub MakeMenu()
'Defining the menubars
Dim cMenu1 As CommandBarControl
Dim cbMainMenuBar As CommandBar
Dim iHelpMenu As Integer
Dim cbcCustomMenu As CommandBarControl

'Delete any existing bars. On Error Resume in case it does not exist.
On Error Resume Next
DeleteMenu
On Error GoTo 0

'Set a CommandBar variable to Worksheet menu bar
'Change the Menu Bar to change the placement of the bar
Set cbMainMenuBar = _
Application.CommandBars("Menu Bar")

'Return the Index number of the Help menu. We can then use this to place a custom menu before the help menu, if you want a different location change the Help to a preferred menu item
iHelpMenu = _
cbMainMenuBar.Controls("Help").Index

'Add a Control to the "Worksheet Menu Bar" before the above set menu item
'Set a CommandBarControl variable to it
'The Temporary=True statement makes Visio delete the bar on quitting (as mentioned above)
Set cbcCustomMenu = _
cbMainMenuBar.Controls.Add(Type:=msoControlPopup, _
Before:=iHelpMenu, Temporary:=True)

'Give the control a caption this has to be the same name as the one mentioned in the DeleteMenu sub
cbcCustomMenu.Caption = "Your Menu Bar"

'Adding bars to the menu, give it a caption and tell it which macro to run (OnAction).
With cbcCustomMenu.Controls.Add(Type:=msoControlButton)
.Caption = "Item 1"
.OnAction = "Macro"
End With
'Add another one
With cbcCustomMenu.Controls.Add(Type:=msoControlButton)
.Caption = "Item 2"
.OnAction = "Macro"
End With
'Repeat as needed...
'Add another menu that will lead off to another menu
'Set a CommandBarControl variable to it
Set cbcCustomMenu = cbMainMenuBar.Controls("Your Menu Bar")
Set cbcCustomMenu = cbcCustomMenu.Controls.Add(Type:=msoControlPopup)
'Give the control a caption
cbcCustomMenu.Caption = "Sub Menu"

'Add a contol to the sub menu, just created above
With cbcCustomMenu.Controls.Add(Type:=msoControlButton)
.Caption = "Sub item 1"
.OnAction = "Macro"
End With
With cbcCustomMenu.Controls.Add(Type:=msoControlButton)
.Caption = "Sub item 2"
.OnAction = "Macro"
End With
'Adding another menu item below sub menu's
Set cbcCustomMenu = cbMainMenuBar.Controls("Your Menu Bar")
With cbcCustomMenu.Controls.Add(Type:=msoControlButton)
.Caption = "Final item"
.OnAction = "Macro"
End With
End Sub


So there you have it, we've created a fully functioning menu.

It will look something like this:



There might be different ways to do this, but this at least one way of doing it. If you know of a better way to do this, let me know. About the removing the bar part I spoke of earlier. The Temporary=True statement makes Visio delete the bar on quitting (as mentioned above)

Good luck,

- Lars-Erik

Visio Guy

#1
Instead of using the events DocumentCreated and DocumentOpened, you can use RunModeEntered, which runs on document opened or document created.

This has the benefit of allowing you to click the little "Design Mode" triangle on and off to re-start your code.

You can test without having to close and re-open your document! You can read more in this article:

Run VBA Code When Documents Open
For articles, tips and free content, see the Visio Guy Website at http://www.visguy.com
Get my Visio Book! Using Microsoft Visio 2010

Lars-Erik

Quote from: Mike MulvennaLars,
      I copied the code for the menu add in VISIO. WHen i try to run it i vae to comment out the ".onaction" lines as they get the error

      onaction method failed.

      Any ideas?

      Thanks
      Mike Mulvenna

I've copied this from the comment section of my site, it's a comment on the same topic on my site.
Because Mike asks a good question I'm posting it here aswell, here's my answer:


I have had problems with this myself, the most likely reason though:
The macro you are trying to 'attach' to the menu item doesn't exist.
Here's how it should look:
      .OnAction = "VisioProjectName.Module.Macro"
Where the VisioProjectName is the bold text in your VBA editors Project explorer. Module is the module where your macro is located within this project. (to create one right-click your project->insert->module). And the macro is the macro's name without the () so here's one I use in one of my projects:
      Hosokawa_Micron.NewMacros.Open_Hidden_Background_Sheet

Yes my module is called NewMacros, I know it's silly :)

Hope this helps,

- Lars-Erik

mmulvenna

Lars-Erik

Adding the module name to the onaction corrected the issue. ::) Thanks so much for the quick reponse.

Mike

khott13

Hello,

I am having troubling assigning macros to command bar items that are from different Visio projects. I have been able to assign macros from any module within the project where I am running MakeMenu. I keep receiving a message saying that the method of .onaction failed when using the following code when Drawing36 is the active document (which is where the MakeMenu macro lives):

'Add a contol to the sub menu, just created above
With cbcCustomMenu.Controls.Add(Type:=msoControlButton)
      .Caption = "Sub item 1"
      .OnAction = "Drawing37.ThisDocument.Macro"
End With

While this works when Drawing 36 is the active document:

'Add a contol to the sub menu, just created above
With cbcCustomMenu.Controls.Add(Type:=msoControlButton)
      .Caption = "Sub item 2"
      .OnAction = "Drawing36.ThisDocument.Macro"
End With


Any suggestions? I greatly appreciate the help!

Thanks,
Kyle


Quote from: mmulvenna on May 29, 2008, 02:13:39 PM
Lars-Erik

Adding the module name to the onaction corrected the issue. ::) Thanks so much for the quick reponse.

Mike

Lars-Erik

I'll check this... see if there is a clean solution for this.

As for now, a workaround might work, instead of linking the function in the other document to the menu.
Link a macro in the current document, that then calls the other documents function.
That way the menu will always be able to find a function and probably stop giving an error.

Hope this helps.

Lars

devpods

Hey,

I tried to do the "VisioProjectName.Module.Macro" in the .OnAction line but I still get the same error.
Is it wrong that all of the above code is in my ThisDocument?