Select to view content in your preferred language

Modify (add) to MAIN Toolbar with Addinx files

2486
9
06-24-2011 09:17 AM
MichaelRobb
Honored Contributor
Hi everyone,

Has anyone figured out a way to add a Menu to the MAIN (Root) menu toolbar using Addins?
So a menu in between File and EDIT or after HELP.

I know you can modify the Main Toolbar via ESRIRegAsm com object w/ deployed MSI installable.. but what about ADDINS?


I can Create a new Menu ... but then unable to do anything from there...(button wise) in an Extention Addin Setting:
            Dim TopMenuBar As ESRI.ArcGIS.Framework.ICommandBar
            TopMenuBar = GetToolbarByName(My.ArcMap.Application, "esriArcMapUI.MxMenuBar")


            TopMenuBar.CreateMenu("Menu TEST", 1)


The Main Toolbar {56599DD3-E464-11D1-9496-080009EEBECB}
esriArcMapUI.MxFileMenu


Thanks, in advance.
0 Kudos
9 Replies
MichaelRobb
Honored Contributor
Anyone ?
No one attempted to modify the Main Bar? add a menu and add a button in the menu with addins?
0 Kudos
MichaelRobb
Honored Contributor
Bump... Still trying to find a solution to this.
0 Kudos
JeffreyHamblin
Occasional Contributor
Hi Mike,

I haven't worked with the menuing system yet, but I noticed this note at the bottom of the ICommandBar doc page:

"If you want to create a new menu in a development environment other than VBA, you should implement IMenuDef instead of using ICommandBar.CreateMenu."

Maybe that will help...
0 Kudos
MichaelRobb
Honored Contributor
The whole issue with IMenuDef is the fact Im trying to do this through Addins as stated, which is not structured in that manner. (Am I missing something perhaps?)
Back in the 'old' days... years of doing msi installer packages and registering a compiled dll, I used IMenuDef to alter any arcmap...

The problem is we now have everyone on shared addins, rather than installing and registering dlls using, (esriregasm), as its a headache free updating setup (one update = everyone gets updated on next arcmap setup, via addins or addition of new tools, etc without any babysitting of everyones machines to ensure they uninstall/install etc. correctly.  Then go through the entire process again for any found issues.  Addins has streamlined the updating tremendously, using shared addins on a visible network drive/folder for all offices.

The first post code works, it adds the menu, but thats where the road ends... unable to add any further Addin Tools.
Ill look at it again, but I dont think modifying the Main menu bar is plausible at this time...

I have the menu bar receiving the added item via an Addin Extension
0 Kudos
JeffreyHamblin
Occasional Contributor
Hi Mike,

I find this a little puzzling too.

If I use the Add-Ins Wizard in Visual Studio, and add a Menu type Command Bar, there is an option to set it as a Root Menu: "Specifies whether or not this menu is a root menu. Root menus appear on the main menu bar. The File and Edit menus are examples of root menus."
Menu Config XML Schema

However, it doesn't show on the main menu bar at startup. I had to open the Customize dialog, select the Commands tab, select "[Menus]", then drag my test menu to the main menu bar.

It seems like there should be a Premiere (showInitially) attribute like toolbars have.
0 Kudos
MichaelRobb
Honored Contributor
Hi Jeff,

It is interesting, possibly requiring a fix in newer releases or a WIP?
Funny how writing 15,000 lines of code for some complex task is less frustrating than something you would think is so simple to accomplish, lol.
Perhaps someone else will chime in soon, or you find something I overlooked...
I really dont want to go back to registering dlls methods outside of addins just because of this.
Thank you for your efforts with this!
0 Kudos
JeffreyHamblin
Occasional Contributor
Hi Mike,

I found a way to push an Add-In menu onto the main menu bar in an Extension Add-In. Below is some raw C# code that seems to work in limited testing. It is based on code from the resource center: Applying user interface customizations at startup

The steps are:
1. Use the Add-Ins Wizard in Visual Studio, and add a Menu type Command Bar, set it as a Root Menu, and assign one or more buttons as items.

2. Use the Add-Ins Wizard in Visual Studio and add an Extension set to autoload.

3. Replace the guts of the extension class with the following:

public class TestAddToMainMenu : ESRI.ArcGIS.Desktop.AddIns.Extension
{

    public TestAddToMainMenu()
    {
    }

    protected override void OnStartup()
    {
        WireEvents();
    }

    protected override void OnShutdown()
    {
    }

    private void WireEvents()
    {

        ArcMap.Events.OpenDocument +=
                new ESRI.ArcGIS.ArcMapUI.IDocumentEvents_OpenDocumentEventHandler(Events_OpenDocument);

        ArcMap.Events.NewDocument +=
                new ESRI.ArcGIS.ArcMapUI.IDocumentEvents_NewDocumentEventHandler(Events_NewDocument);

        IApplicationStatusEvents_Event appStatusEvents = 
                ArcMap.Application.Document.Parent as IApplicationStatusEvents_Event;
        appStatusEvents.Initialized += new IApplicationStatusEvents_InitializedEventHandler(Events_Initialized);
    }

    void Events_Initialized()
    {
        // Need this to load menu when no document loaded at startup
        LoadCustomMainMenu();
    }

    void Events_OpenDocument()
    {
        LoadCustomMainMenu();
    }

    void Events_NewDocument()
    {
        LoadCustomMainMenu();
    }

    private void LoadCustomMainMenu()
    {
        ICommandBar mainMenuBar = GetMainMenuBar();

        // make sure we got the main menu bar
        if (mainMenuBar == null)
            return;

        // check if our custom menu is already there
        string menuID = "REPLACE WITH MENU ADDIN ID"; // ID of Add-In Root Menu
        ICommandItem cmdItem = mainMenuBar.Find(menuID, false);

        // skip out if custom menu already there
        if (cmdItem != null)
            return;

        System.Diagnostics.Debug.WriteLine("**** MENU ADDED ****");
        // Add Menu, if needed
        UID uid = new UIDClass();
        uid.Value = menuID;
        Object indexObj = Type.Missing; // adds menu at far right
        ICommandBar myMenu = mainMenuBar.Add(uid, ref indexObj) as ICommandBar;
        ((ICommandItem)mainMenuBar).Refresh();

    }

    private ICommandBar GetMainMenuBar()
    {
        try
        {
            //Grab the root menu bar
            UID uid = new UIDClass();
            uid.Value = "{1E739F59-E45F-11D1-9496-080009EEBECB}";  // Main menubar
            ICommandBars cmdBars = ArcMap.Application.Document.CommandBars;
            ICommandItem commandItem = cmdBars.Find(uid, false, false);
            return cmdBars.Find(uid, false, false) as ICommandBar;
        }
        catch
        {
            return null;
        }
    }


}


4. In the LoadCustomMainMenu method, replace the string value for menuID with the exact id value from the Menu section of the Config.esriaddinx file.


As I mentioned, this is proof-of-concept code that likely needs refining to make it more robust. But I hope it helps get you started.
0 Kudos
MichaelRobb
Honored Contributor
Wow!  This works!  Thanks a ton!  Your example, and adjustments all make complete sense.
Handy to have that Acme example as well... thanks for that pointer!

Im no C# guy, so Ill post my vb.net version for anyone else to go over, including yourself

In the config.esriaddinx
as usual, create the menu, containing the items > button and Commands containing the button ID

Autoload = true >> on the extension
isRootMenu = true >> on the Menu


And here is the vb.net version that works.
* note I used IndexObject value of 1 to place right beside the FILE choice on the main bar.

Imports System.Windows.Forms

Imports ESRI.ArcGIS.Framework
Imports ESRI.ArcGIS.esriSystem


Public Class Extension1

    Inherits ESRI.ArcGIS.Desktop.AddIns.Extension

    Private c_mainMenuID As String = "{1E739F59-E45F-11D1-9496-080009EEBECB}" ' Main menubar 

    Public Sub New()

    End Sub

    Protected Overrides Sub OnStartup()

        WireDocumentEvents()

    End Sub

    Protected Overrides Sub OnShutdown()

    End Sub

    Private Sub WireDocumentEvents()

        AddHandler My.ArcMap.Events.NewDocument, AddressOf ArcMapNewDocument
        AddHandler My.ArcMap.Events.OpenDocument, AddressOf ArcMapOpenDocument

    End Sub

    Private Sub ArcMapNewDocument()

        Try
            LoadCustomMainMenu()

        Catch ex As Exception
            MessageBox.Show(ex.Message & vbNewLine & "Details: " & ex.StackTrace, "", MessageBoxButtons.OK, MessageBoxIcon.Asterisk)

        End Try

    End Sub
    Private Sub ArcMapOpenDocument()

        Try
            LoadCustomMainMenu()

        Catch ex As Exception
            MessageBox.Show(ex.Message & vbNewLine & "Details: " & ex.StackTrace, "", MessageBoxButtons.OK, MessageBoxIcon.Asterisk)

        End Try

    End Sub


    Private Sub LoadCustomMainMenu()
        Dim mainMenuBar As ESRI.ArcGIS.Framework.ICommandBar = GetMainMenuBar()

        ' make sure we got the main menu bar
        If mainMenuBar Is Nothing Then
            Return
        End If

        ' check if our custom menu is already there
        Dim menuID As String = "FocusToolsToolbar_Addin_v10_ERCBMenu"
        ' ID of Add-In Root Menu
        Dim cmdItem As ESRI.ArcGIS.Framework.ICommandItem = mainMenuBar.Find(menuID, False)

        ' skip out if custom menu already there
        If cmdItem IsNot Nothing Then
            Return
        End If

        System.Diagnostics.Debug.WriteLine("**** MENU ADDED ****")
        ' Add Menu, if needed
        Dim uid As ESRI.ArcGIS.esriSystem.UID = New ESRI.ArcGIS.esriSystem.UIDClass()
        uid.Value = menuID
        Dim indexObj As [Object] = 1 ' Right beside FILE 
        ' adds menu one spot in
        Dim myMenu As ICommandBar = TryCast(mainMenuBar.Add(uid, indexObj), ICommandBar)
        DirectCast(mainMenuBar, ESRI.ArcGIS.Framework.ICommandItem).Refresh()

    End Sub


    Private Function GetMainMenuBar() As ICommandBar
        Try
            'Grab the root menu bar 
            Dim uid As ESRI.ArcGIS.esriSystem.UID = New ESRI.ArcGIS.esriSystem.UIDClass()
            uid.Value = c_mainMenuID
            Dim mx As ESRI.ArcGIS.ArcMapUI.MxDocument = DirectCast(My.ArcMap.Application.Document, ESRI.ArcGIS.ArcMapUI.MxDocument)
            Dim cmdBars As ESRI.ArcGIS.Framework.ICommandBars = mx.CommandBars
            Dim x As ESRI.ArcGIS.Framework.ICommandItem = cmdBars.Find(uid, False, False)
            Return TryCast(cmdBars.Find(uid, False, False), ICommandBar)
        Catch
            Return Nothing
        End Try
    End Function

End Class
0 Kudos
kyleknoche
Emerging Contributor
Hi.  Nice thread.   I'm wondering if you guys have any ideas on how to get something in the Customize menu drop down. 

I'm trying to but a addin Button in there by finding esriArcMapUI.MxCustomizeMenu and then trying to add an item.  This only works if i choose customize and drag the item onto another toolbar.  Then the OnUpdate starts firing.  I can't get the OnUpdate to fire without that being done.  I have the onDemand attribute set to false.


MxAppMngr.Singleton.AddCommandItemToMainMenuCustomizeMenu(ThisAddIn.IDs.AUSettingsButton);
            ICommandBar custMenu = MxAppMngr.Singleton.FindMainCustomizeMenu();
            (custMenu as ICommandItem).Refresh();

This appears to work, but the button is not on the customize menu when you navigate to it.

I can, however, add the button as a CommandItem to the MainMenu using almost identical code.

Anyone have any ideas what I'm missing here?
0 Kudos