Rescue me from getting insane.

  • Sorry for the clickbait topic, I couldn’t resist.

    Okay, looks like I’m not able to understand the usage of NPPM_ALLOCATECMDID with getFuncsArray and NPPM_ADDTOOLBARICON.

    My understanding, so far, is, that you need to allocate a cmdid for every
    menuitem (not for submenu but also for items in submenus) of the plugins menu.
    Menuitems from the root menu of a plugin are special as those can get
    a shortcut key assigned which items from a submenus can’t.

    In order to be able to assign a shortcut key these functions need to be
    returned within getFuncsArray callback.

    In order to be able to use toolbar buttons, it is needed to provide the
    needed information within NPPN_TBMODIFICATION notification.

    Okay, so my workflow is the following

    • when plugin gets loaded send NPPM_ALLOCATECMDID to request
      the number of cmdids needed
    • when getFuncsArray is called provide the functions by using the
      received cmdid startid and add 1 for each function
    • when receiving NPPN_TBMODIFICATION notification provide the cmdid,
      which has been used for a function from getFuncsArray for the
      respective toolbar button together with a proper image.

    Now this seem to work, partially, functions are listed in the root menu and can be executed.
    The toolbar buttons get created BUT clicking on it doesn’t do anything.

    In the contrast, if I don’t provide the functions within getFuncsArray,
    but create them using win32 menu functions and still using the returned cmd ids,
    then the menu items can be clicked and executed as well as the toolbar buttons
    because a WM_COMMAND together with the cmdid is sent back via messageProc,
    which I can map to the real function.
    Downside, I cannot map shortcuts to those functions.

    An additional weirdness, when registering functions via getFuncsArray,
    their respective toolbar buttons don’t get the tooltip name where as
    creating it via the win32 menu functions, those names are available.

    Has anyone an idea where my misunderstanding is?


  • @Ekopalypse

    As far as I understand your question you want to create (for example) the following menu structure:

    (Npp main menu) Plugins -> Name-of-your-plugin -> Your-plugin-action-1
    (Npp main menu) Plugins -> Name-of-your-plugin -> Your-plugin-action-2

    To do that you do not need to use NPPM_ALLOCATECMDID. You only need to fill the following fields of a struct FuncItem contained in the funcsArray:

    • _itemName - the text of the menu entry of one of your plugin’s actions, Your-plugin-action-1 or Your-plugin-action-2 in the example above.
    • _pFunc - a pointer to the function to be called when the according menu entry has been clicked.
    • _pShKey (optional) - a pointer to a struct ShortcutKey to pre-define a keyboard shortcut for the according plugin action.

    The field _init2Check can be used to initialize the checked state of the according menu entry. To set the checked state during runtime of Notepad++ use the NPPM_SETMENUITEMCHECK message.

    The field _cmdID is filled by Notepad++ after it has called the getFuncsArray callback function. You don’t have to allocate a menu command id by yourself. When processing the NPPN_TB_MODIFICATION notification, send an NPPM_ADDTOOLBARICON message to the Notepad++ window with wParam set to the menu command id obtained from the funcsArray item of the according plugin action menu entry and lParam set to the pointer to a proper initialized struct toolbarIcons.

    As far as I know the NPPM_ALLOCATECMDID message comes into play when you want to create menu entries in one of the other menus of Notepad++ except the Plugins menu, e.g. creating entries in the Macro menu.

  • @dinkumoil

    thank you - Thank you - THANK YOU :-D
    I was looking for ages to find some documentation how to do this correctly.
    And, yes, if I do it like you perfectly described it, I can use both, menu items
    and toolbar buttons, even with tooltip names, brilliant.
    Another two issues I can mark solved. Thank you so much.

    Concerning the NPPM_ALLOCATECMDID I guess I need to use it when having a menu structure like this

    If I click on MyMenuItem I receive a WM_COMMAND with the cmdid in wparam and therefore can
    act upon. I could create MyMenuItem with a wID different to cmdid but then I’m unsure whether this
    could collide with other menuitems created by other plugins. What do you think?

  • @Ekopalypse said in Rescue me from getting insane.:

    but then I’m unsure whether this could collide with other menuitems created by other plugins.

    I have no clue about using wID or what is its desired use case. But your assumption seems plausible, a plugin dev should not use wID since he can not know whether a certain ID is used in another menu entry. The only known unique property of menu entries is the command id and as such should be used to distinguish them.

  • @dinkumoil said in Rescue me from getting insane.:

    I have no clue about using wID or what is its desired use case

    To quote msdn

    Type: UINT
    An application-defined value that identifies the menu item. Set fMask to MIIM_ID to use wID.

    I tested once with a self generate id and I had an issue that a function was not executing always,
    meaning it run during a npp runtime but next time I started npp it didn’t run.
    But I can’t say for sure that this was the culprit as I were constantly changing code
    to see how things affect each other. :-) So I will keep an eye on it.

    Thank you so much for your help.

  • you should declare NPPM_ALLOCATECMDID of NPP->Plugins->MyPlugin->SubMenu->MaybeAnotherSubMenu->MyMenuItem
    in NPPM_ADDTOOLBARICON condition

            PluginBase.SetCommand(0, "Close HTML/XML tag automatically", checkInsertHtmlCloseTag, new ShortcutKey(false, true, false, Keys.Q), doCloseTag);
        static void checkInsertHtmlCloseTag()
            doCloseTag = !doCloseTag;
            int i = Win32.CheckMenuItem(Win32.GetMenu(PluginBase.nppData._nppHandle), PluginBase._funcItems.Items[0]._cmdID,
                Win32.MF_BYCOMMAND | (doCloseTag ? Win32.MF_CHECKED : Win32.MF_UNCHECKED));

  • @gurikbal-singh said in Rescue me from getting insane.:


    Not quite sure I understand as neither NPPM_ALLOCATECMDID nor NPPM_ADDTOOLBARICON is used in your example.

    I’ve checked the c# plugin code and, beside of defining NPPM_ALLOCATECMDID function it does not use it internally.
    Guess this makes sense as it is a plugin framework rather then a UI plugin.

  • @Ekopalypse said in Rescue me from getting insane.:

    Sorry for the clickbait topic, I couldn’t resist.

    Not sure what there was to “resist”. Clickbait only makes future searchers of the forum have a more difficult time of it. :-(

  • @Alan-Kilborn
    But if the clickbait was chosen that good,
    then one might remember it and find it easier :-)

Log in to reply