How to Add a Custom Menu Item in Microsoft Dynamics GP 2013
There is a considerable amount of information online about how to add a custom form to the Additional menu in a form’s menu bar in Dynamics GP:
IvItemMainenanceForm.AddMenuHandler(new EventHandler(OpenInventoryManager), "Inventory Manager");
But there are far fewer references instructing how to add a custom menu item to the cards items list in Dynamics GP:
In order to add a form from a .NET add-in to these menus, you will need to use the Menus for Visual Studio Tools add-in. This tool provides classes and methods for associating forms to menu items. Let’s look at the methods (and the code below) needed to add an item to a menu.
//menu for VS Tools section
// Application Name
const string APPNAME = "VSTMenusCSharp";
// Dictionary ID Constants
const short DYNAMICS = 0;
// Shortcut Key Modifier Constants
const int COMMAND_SHORTCUT_CTRL = 65536;
const int COMMAND_SHORTCUT_CTRLSHIFT = 327680;
const int COMMAND_SHORTCUT_CTRLALT = 196608;
const int COMMAND_SHORTCUT_ALT = 131072;
const int COMMAND_SHORTCUT_ALTSHIFT = 393216;
const int COMMAND_SHORTCUT_CTRLALTSHIFT = 458752;
// Shortcut Key Function Key Constants, can be used instead of ASCII value
const short COMMAND_SHORTCUT_KEY_F1 = 112;
const short COMMAND_SHORTCUT_KEY_F2 = 113;
const short COMMAND_SHORTCUT_KEY_F3 = 114;
const short COMMAND_SHORTCUT_KEY_F4 = 115;
const short COMMAND_SHORTCUT_KEY_F5 = 116;
const short COMMAND_SHORTCUT_KEY_F6 = 117;
const short COMMAND_SHORTCUT_KEY_F7 = 118;
const short COMMAND_SHORTCUT_KEY_F8 = 119;
const short COMMAND_SHORTCUT_KEY_F9 = 120;
const short COMMAND_SHORTCUT_KEY_F10 = 121;
const short COMMAND_SHORTCUT_KEY_F11 = 122;
const short COMMAND_SHORTCUT_KEY_F12 = 123;
short MenuListTag1; short MenuTag1;
short MenuTag2;
short MenuTag3;
short MenuTag4;
public void Initialize()
{
// Register Event to add menu entries
MenusForVisualStudioTools. Functions.EventRegister.InvokeAfterOriginal += new EventRegisterFunction.InvokeEventHandler(VSTMCommandFormRegister);
// Register Event to handle callbacks from menu entries
MenusForVisualStudioTools. Functions.EventHandler.InvokeAfterOriginal += new EventHandlerFunction.InvokeEventHandler(VSTMCommandFormCallback);
}
void VSTMCommandFormRegister(object sender, EventRegisterFunction.InvokeEventArgs e)
{
short ParentTag = 0;
short BelowTag = 0;
short ResID = 0;
try
{
// Get Parent Tag for command list to add menu to
ParentTag = MenusForVisualStudioTools.Functions.GetTagByName.Invoke(
DYNAMICS, "Command_Inventory", "CL_Inventory_Utilities"); // Dictionary ID, Form Name, Command Name
if (ParentTag <= 0)
{
throw new Exception("Parent GetTagByName, error code: " + Convert.ToString(ParentTag));
}
// Get Below Tag for command/command list to add menu below
BelowTag = MenusForVisualStudioTools.Functions.GetTagByName.Invoke(
DYNAMICS, "Command_Inventory", "CL_Inventory_Utilities"); // Dictionary ID, Form Name, Command Name
if (BelowTag <= 0)
{
throw new Exception("Below GetTagByName, error code: " + Convert.ToString(BelowTag));
}
// Get Security Form Resource ID for menus to inherit security access from
ResID = MenusForVisualStudioTools.Functions.GetFormResId.Invoke(
DYNAMICS, "IV_Reconcile"); // Get Form Resource ID for Security
if (ResID <= 0)
{
throw new Exception("GetFormResId, error code: " + Convert.ToString(ResID));
}
MenuTag1 = MenusForVisualStudioTools.Functions.RegisterWithSecurity.Invoke(
ParentTag, // Parent Command Tag
"Inventory Manager", // Menu Caption
"Click to open Inventory Manager", // Menu Tooltip
0, 0, // Menu Shortcut Key, Shortcut Modifier
true, false, false, // Checked, Disabled, Hidden
BelowTag, // Add Below Command Tag
false, false, // Add Separator, Add Command List
DYNAMICS, ResID); // Security Dictionary and Form Resource ID
if (MenuTag1 <= 0)
{
throw new Exception("Command 1 RegisterWithSecurity, error code: " + Convert.ToString(MenuTag1));
}
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message, APPNAME);
}
}
void VSTMCommandFormCallback(object sender, EventHandlerFunction.InvokeEventArgs e)
{
short Tag = 0;
// Get Callback Tag Number for menu entry
// Tag = MenusForVisualStudioTools.Functions.Callback.Invoke();
Tag = e.inParam1;
// Compare Tag Sequence Number with Menu Sequence obtained during registration
if (Tag == MenuTag1)
{
//Forms.ContractNumberSelect contractSelect = new Forms.ContractNumberSelect();
//contractSelect.ShowDialog();
inventoryManager.ShowDialog();
}
}
This seems complicated and confusing, and certainly can be, but there are really just a few things required to accomplish the goal of adding a form to the menu.
More or less, copying the code above (download the code snippet here) to your GPAddIn.cs file will get you most of the way there, but there are a few changes that need to be made to personalize it. The first item is the ParentTag.
The ParentTag object is the ID of the menu that you wish to place the new item into. If you want to add your custom form link to the Customer Cards menu, then you need to find the Form Name and Command Name. This can only be found in the table provided in the associated document that comes with the download for the Menus add-in. I have duplicated it below.
Top Level Menu | Submenu | Form | Command |
Tools* | Command_System | CL_Tools | |
Toole >> Setup | Command_System | CL_Setup | |
System | Command_System | CL_System_Setup | |
Company | Command_System | CL_Comapny_Setup | |
Posting | Command_System | CL_Posting_Setup | |
Financial | Command_Financials | CL_Financial_Setup | |
Sales | Command_Sales | CL_Sales_Setup | |
Purchasing | Command_Purchasing | CL_Purchasing_Setup | |
Inventory | Command_Inventory | CL_Inventory_Setup | |
Payroll | Command_Payroll | CL_Payroll_Setup | |
Tools >> Utilities | Command_System | CL_Utilities | |
System | Command_System | CL_System_Utilities | |
Company | Command_System | CL_Company_Utilities | |
Financials | Command_Financials | CL_Financial_Utilities | |
Sales | Command_Sales | CL_Sales_Utilities | |
Purchasing | Command_Purchasing | CL_Purchasing_Utilities | |
Inventory | Command_Inventory | CL_Inventory_Utilities | |
Payroll | Command_Payroll | CL_Payroll_Utilities | |
Tools >> Routines | Command_System | CL_Routines | |
Company | Command_System | CL_Company_Routines | |
Financial | Command_Financial | CL_Financial_Routines | |
Sales | Command_Sales | CL_Sales_Routines | |
Purchasing | Command_Purchasing | CL_Purchasing_Routines | |
Inventory | Command_Inventory | CL_Inventory_Routines | |
Payroll | Command_Payroll | CL_Payroll_Routines | |
Transactions | Command_System | CL_Transactions | |
Financial | Command_Financial | CL_Financial_Transactions | |
Sales | Command_Sales | CL_Sales_Transactions | |
Purchasing | Command_Purchasing | CL_Purchasing_Transactions | |
Inventory | Command_Inventory | CL_Inventory_Transactions | |
Payroll | Command_Payroll | CL_Payroll_Transactions | |
Inquiry | Command_System | CL_Inquiry | |
System | Command_System | CL_System_Inquiry | |
Financial | Command_Financial | CL_Financial_Inquiry | |
Sales | Command_Sales | CL_Sales_Inquiry | |
Purchasing | Command_Purchasing | CL_Purchasing_Inquiry | |
Inventory | Command_Inventory | CL_Inventory_Inquiry | |
Payroll | Command_Payroll | CL_Payroll_Inquiry | |
Reports | Command_System | CL_Reports | |
System | Command_System | CL_System_Reports | |
Company | Command_Payroll | CL_Company_Reports | |
Financial | Command_Purchasing | CL_Purchasing_Reports | |
Sales | Command_Sales | CL_Sales_Reports | |
Purchasing | Command_Purchasing | CL_Purchasing_Reports | |
Inventory | Command_Inventory | CL_Inventory_Reports | |
Payroll | Command_Payroll | CL_Payroll_Reports | |
Cards | Command_System | CL_Cards | |
System | Command_System | CL_System_Cards | |
Financial | Command_Financial | CL_Financial_Cards | |
Sales | Command_Sales | CL_Financial_Cards | |
Purchasing | Command_Purchasing | CL_Purchasing_Cards | |
Inventory | Command_Inventory | CL_Inventory_Cards | |
Payroll | Command_Payroll | CL_Payroll_Cards | |
Help* | Command_System | CL_Help |
*We recommend not adding items directly to this top-level menu
So, again, if we wanted to add a menu item in Customer Cards, for example, we would need to use Sales Cards, because Customers is listed in the Sales top level menu. So the Form Name is Command_Sales and the Command Name is CL_Sales_Cards. This would be the only items modified in the ParentTag. So the ParentTag would look like this:
ParentTag = MenusForVisualStudioTools.Functions.GetTagByName.Invoke(DYNAMICS, "Command_Sales", "CL_Sales_Cards");
Similarly, the BelowTag must be modified.
BelowTag = MenusForVisualStudioTools.Functions.GetTagByName.Invoke(DYNAMICS, "Command_Sales", "CL_Sales_Cards");
An additional modification to the VSTMCommandFormRegister method is to alter the ResId Resource ID to tell the menu what level of security to associate with the new custom menu item. The ResId is the name of a form in GP with the same level of permissions to associate with the new form.
ResID = MenusForVisualStudioTools.Functions.GetFormResId.Invoke(DYNAMICS, "IV_Reconcile");
You must define the new Menu item which can be done in the MenuTag1 (You can define more than one).
MenuTag1 = MenusForVisualStudioTools.Functions.RegisterWithSecurity.Invoke(
ParentTag, // Parent Command Tag
"Assign Customer", // Menu Caption
"Click to Assign Customers to Salespeople", // Menu Tooltip
0, 0, // Menu Shortcut Key, Shortcut Modifier
true, false, false, // Checked, Disabled, Hidden
BelowTag, // Add Below Command Tag
false, false, // Add Separator, Add Command List
DYNAMICS, ResID); // Security Dictionary and Form Resource ID
The important items here are the Menu Caption and the Menu Tooltip. I have modified them in the above example to reflect a custom form that allows the user to assign specific customers to a salesperson.
The last required action is taken within the VSTMCommandFormCallback method. Here is where you define the form to open (or any other actions to be taken) when the new custom menu item is clicked. If, for example, our Assign Customers form class was named AssignCustomers.cs, then we could instantiate the new form here (unless it is defined the GPAddIn.cs class) and call it.
void VSTMCommandFormCallback(object sender, EventHandlerFunction.InvokeEventArgs e)
{
short Tag = 0;
// Get Callback Tag Number for menu entry
// Tag = MenusForVisualStudioTools.Functions.Callback.Invoke();
Tag = e.inParam1;
// Compare Tag Sequence Number with Menu Sequence obtained during registration
if (Tag == MenuTag1)
{
//Forms.ContractNumberSelect contractSelect = new Forms.ContractNumberSelect();
//contractSelect.ShowDialog();
AssignCustomers assignCustomers = new AssignCustomers();
assignCustomers.ShowDialog();
}
Happy customizing!
Feel free to reach out should you have questions or need assistance customizing Microsoft Dynamics GP.
Written by:
Aaron Rumford,
Consultant FMT Consultants