Solved Placing a custom menu under the File Menu and on specific position

Hello,

Is it possible to placing a custom menu after specific submenu from the File menu, after the Save submenu for example .

enhanceMainMenu.png

The script bellow insert my custom menu at the bottom of the File menu:

def enhanceMainMenu():
    mainMenu = c4d.gui.GetMenuResource("M_EDITOR")

    menu = c4d.BaseContainer()
    menu.InsData(c4d.MENURESOURCE_SUBTITLE, "Custom Menu")
    menu.InsData(c4d.MENURESOURCE_COMMAND, "PLUGIN_CMD_{}".format(ID_MENU_1))
    menu.InsData(c4d.MENURESOURCE_COMMAND, "PLUGIN_CMD_{}".format(ID_MENU_2))
    #menu.InsData(0, '') # Append separator
    menu.InsData(c4d.MENURESOURCE_COMMAND, "PLUGIN_CMD_{}".format(ID_MENU_3))

    filemenue = mainMenu.GetData(1)
    filemenue.InsData(c4d.MENURESOURCE_SUBMENU, menu)

    mainMenu.SetData(1, filemenue)

def PluginMessage(id, data):
    if id == c4d.C4DPL_BUILDMENU:
        enhanceMainMenu()

Thanks.

Hi @m_adam,
I found the solution below that allow to inject my custom menu just after the "IDM_SAVEALL" submenu of "File" menu, but the only problem now is with the following line:
FileMenu.InsData(c4d.MENURESOURCE_SUBTITLE, "File")

Because with this solution I must to rebuild all the "IDS_EDITOR_FILE" menu. and I'm searching how to grab the default sub-title of the "IDS_EDITOR_FILE" menu depending on the user interface language. So is there method to get the default subtitle of "IDS_EDITOR_FILE".
Thanks.

import c4d, os, sys

def GetMenuContainer(name):
    mainMenu = c4d.gui.GetMenuResource("M_EDITOR")

    customMenu = c4d.BaseContainer()
    for bcMenuId, bcMenu in mainMenu:
        if bcMenu[c4d.MENURESOURCE_SUBTITLE] == "IDS_EDITOR_FILE":
            customMenu = mainMenu.GetContainerInstance(bcMenuId)
            break

    if customMenu is not None:
        customMenu.FlushAll()

def AddsMenuToC4DMenu(MenuContainer):
    MainMenu = c4d.gui.GetMenuResource("M_EDITOR")

    FileMenu = c4d.BaseContainer()
    FileMenu.InsData(c4d.MENURESOURCE_SUBTITLE, "File")

    for bcMenuId, bcMenu in MainMenu:
        if bcMenu[c4d.MENURESOURCE_SUBTITLE] == "IDS_EDITOR_FILE":
            for _bcMenuId, _bcMenu in bcMenu:
                if _bcMenu == "IDM_SAVEALL":
                    cs_menu = c4d.BaseContainer()
                    cs_menu.InsData(c4d.MENURESOURCE_SUBTITLE, "My Menu")
                    cs_menu.InsData(c4d.MENURESOURCE_COMMAND, "PLUGIN_CMD_{}".format(menu_id1))
                    cs_menu.InsData(c4d.MENURESOURCE_COMMAND, "PLUGIN_CMD_{}".format(menu_id2))
                    cs_menu.InsData(c4d.MENURESOURCE_SEPERATOR, 1) # Append separator
                    cs_menu.InsData(c4d.MENURESOURCE_COMMAND, "PLUGIN_CMD_{}".format(menu_id3))

                    FileMenu.InsData(1, cs_menu)
                    FileMenu.InsData(c4d.MENURESOURCE_SEPERATOR, 1)

                FileMenu.InsData(_bcMenuId, _bcMenu)

    MainMenu.InsDataAfter(c4d.MENURESOURCE_STRING, FileMenu, MenuContainer)

def PluginMessage(id, data):
    if id == c4d.C4DPL_BUILDMENU:
        MenuContainer = c4d.gui.SearchPluginMenuResource("IDS_EDITOR_FILE")
        AddsMenuToC4DMenu(MenuContainer)
        GetMenuContainer("IDS_EDITOR_FILE")
        c4d.gui.UpdateMenus()

Hi @mfersaoui unfortunately, this is not as easy as it sounds in Python.
Find in How to use InsDataAfter in menu a user who wants to add its own item after the "Scroll to first active object" within the Object Manager menu and in the last answers, there is a code snippet to do it.

If you need more specific help or if there is anything you don't understand, please let me know.
Cheers,
Maxime.

Hi @m_adam,
I found the solution below that allow to inject my custom menu just after the "IDM_SAVEALL" submenu of "File" menu, but the only problem now is with the following line:
FileMenu.InsData(c4d.MENURESOURCE_SUBTITLE, "File")

Because with this solution I must to rebuild all the "IDS_EDITOR_FILE" menu. and I'm searching how to grab the default sub-title of the "IDS_EDITOR_FILE" menu depending on the user interface language. So is there method to get the default subtitle of "IDS_EDITOR_FILE".
Thanks.

import c4d, os, sys

def GetMenuContainer(name):
    mainMenu = c4d.gui.GetMenuResource("M_EDITOR")

    customMenu = c4d.BaseContainer()
    for bcMenuId, bcMenu in mainMenu:
        if bcMenu[c4d.MENURESOURCE_SUBTITLE] == "IDS_EDITOR_FILE":
            customMenu = mainMenu.GetContainerInstance(bcMenuId)
            break

    if customMenu is not None:
        customMenu.FlushAll()

def AddsMenuToC4DMenu(MenuContainer):
    MainMenu = c4d.gui.GetMenuResource("M_EDITOR")

    FileMenu = c4d.BaseContainer()
    FileMenu.InsData(c4d.MENURESOURCE_SUBTITLE, "File")

    for bcMenuId, bcMenu in MainMenu:
        if bcMenu[c4d.MENURESOURCE_SUBTITLE] == "IDS_EDITOR_FILE":
            for _bcMenuId, _bcMenu in bcMenu:
                if _bcMenu == "IDM_SAVEALL":
                    cs_menu = c4d.BaseContainer()
                    cs_menu.InsData(c4d.MENURESOURCE_SUBTITLE, "My Menu")
                    cs_menu.InsData(c4d.MENURESOURCE_COMMAND, "PLUGIN_CMD_{}".format(menu_id1))
                    cs_menu.InsData(c4d.MENURESOURCE_COMMAND, "PLUGIN_CMD_{}".format(menu_id2))
                    cs_menu.InsData(c4d.MENURESOURCE_SEPERATOR, 1) # Append separator
                    cs_menu.InsData(c4d.MENURESOURCE_COMMAND, "PLUGIN_CMD_{}".format(menu_id3))

                    FileMenu.InsData(1, cs_menu)
                    FileMenu.InsData(c4d.MENURESOURCE_SEPERATOR, 1)

                FileMenu.InsData(_bcMenuId, _bcMenu)

    MainMenu.InsDataAfter(c4d.MENURESOURCE_STRING, FileMenu, MenuContainer)

def PluginMessage(id, data):
    if id == c4d.C4DPL_BUILDMENU:
        MenuContainer = c4d.gui.SearchPluginMenuResource("IDS_EDITOR_FILE")
        AddsMenuToC4DMenu(MenuContainer)
        GetMenuContainer("IDS_EDITOR_FILE")
        c4d.gui.UpdateMenus()

@mfersaoui
Hi,
I found the following solution:

FileMenu = c4d.BaseContainer()
resource = c4d.plugins.GeResource()
resource.InitAsGlobal()
FileMenu.InsData(c4d.MENURESOURCE_SUBTITLE, resource.LoadString(12587))