Menu dell'Add-on¶
I menu personalizzati permettono al tuo add-on di integrarsi direttamente nell'interfaccia di SAP Business One, aggiungendo voci sotto il menu Moduli.
1. Struttura dei Menu in SAP B1¶
Il menu di SAP Business One è un albero gerarchico. Ogni voce è un MenuItem identificato da un ID univoco (stringa). SAP riserva degli ID per i menu di sistema — quello che ci interessa è:
| ID | Menu |
|---|---|
43520 |
Moduli — il contenitore principale dove gli add-on aggiungono le proprie voci |
Come visualizzare l'id dei menu
Attiva le informazioni di sistema da View > Informazioni di sistema (CTRL + SHIFT + I).
Poi passa con il mouse sopra al menu nella toolbar e visualizza in basso il suo ID
Per aggiungere un menu personalizzato, la logica è:
- Recuperare il
MenuItemdel menu "Moduli" tramite il suo ID - Accedere ai suoi
SubMenus - Aggiungere le proprie voci con
Add()
2. Tipi di Voce: BoMenuType¶
Ogni voce di menu ha un tipo che ne determina il comportamento:
| Tipo | Descrizione |
|---|---|
mt_POPUP |
Voce contenitore — ha un sottomenu. Non è cliccabile di per sé. |
mt_STRING |
Voce cliccabile — genera un MenuEvent quando l'utente ci clicca. |
mt_SEPERATOR |
Linea separatrice visiva tra le voci. Non è cliccabile. |
3. Il Codice Completo: AddOnMenu.cs¶
using System;
using SAPbouiCOM.Framework;
namespace MySAPAddon
{
internal class AddOnMenu
{
public void AddMenuItems()
{
SAPbouiCOM.MenuItem oMenuItem = Application.SBO_Application.Menus.Item("43520"); // Menu Moduli
SAPbouiCOM.Menus oMenus = oMenuItem.SubMenus;
// solo per debug, per non chiudere e riaprire SAP ogni volta
if (oMenus.Exists("RS_MENU1"))
oMenus.RemoveEx("RS_MENU1");
// voce principale (contenitore)
oMenus.Add("RS_MENU1", "Il Mio Add-on", SAPbouiCOM.BoMenuType.mt_POPUP, -1);
// sottomenu
oMenus = Application.SBO_Application.Menus.Item("RS_MENU1").SubMenus;
oMenus.Add("RS_MENU1_SUB1", "SubMenu 1", SAPbouiCOM.BoMenuType.mt_STRING, -1);
oMenus.Add("RS_MENU1_SUB2", "SubMenu 2", SAPbouiCOM.BoMenuType.mt_SEPERATOR, -1);
oMenus.Add("RS_MENU1_SUB3", "SubMenu 3", SAPbouiCOM.BoMenuType.mt_STRING, -1);
oMenus.Add("RS_MENU1_SUB4", "SubMenu 4", SAPbouiCOM.BoMenuType.mt_POPUP, -1);
// sottomenu del sottomenu
oMenus = Application.SBO_Application.Menus.Item("RS_MENU1_SUB4").SubMenus;
oMenus.Add("RS_MENU1_SUB4_SUB1", "Sub sub Menu 1", SAPbouiCOM.BoMenuType.mt_STRING, -1);
oMenus.Add("RS_MENU1_SUB4_SUB2", "Sub sub Menu 2", SAPbouiCOM.BoMenuType.mt_SEPERATOR, -1);
oMenus.Add("RS_MENU1_SUB4_SUB3", "Sub sub Menu 3", SAPbouiCOM.BoMenuType.mt_STRING, -1);
}
public void SBO_Application_MenuEvent(ref SAPbouiCOM.MenuEvent pVal, out bool BubbleEvent)
{
BubbleEvent = true;
try
{
if (pVal.BeforeAction == false && pVal.MenuUID == "RS_MENU1_SUB1")
{
// Qui istanzieremo e mostreremo la nostra Form
}
}
catch (Exception ex)
{
Application.SBO_Application.MessageBox(ex.ToString(), 1, "Ok", "", "");
}
}
}
}
Nel Program.cs, registri l'handler così:
AddOnMenu menu = new AddOnMenu();
menu.AddMenuItems();
app.RegisterMenuEventHandler(menu.SBO_Application_MenuEvent);
4. Spiegazione del Codice¶
Aggiungere le voci: AddMenuItems()¶
Il metodo Menus.Add() ha questa firma:
oMenus.Add(
string UniqueID, // ID univoco della voce (lo usi per identificarla negli eventi)
string Name, // Testo visualizzato nel menu
BoMenuType Type, // mt_POPUP, mt_STRING o mt_SEPERATOR
int Position // -1 = in fondo, altrimenti posizione specifica
);
La logica per creare un menu gerarchico è semplice:
- Recuperi il menu padre —
Application.SBO_Application.Menus.Item("43520")ti dà il menu "Moduli" - Aggiungi una voce
mt_POPUP— questa sarà il contenitore del tuo add-on - Navighi nei
SubMenus— per aggiungere le sotto-voci, recuperi la voce appena creata e accedi ai suoiSubMenus - Annidi a piacere — una voce
mt_POPUPpuò contenere a sua volta altrimt_POPUP, permettendo strutture a più livelli
Il trucco RemoveEx per il debug
SAP non permette di aggiungere un menu con un ID che esiste già — otterresti un'eccezione. Chiamando RemoveEx prima di Add, puoi riavviare l'add-on in debug senza dover chiudere e riaprire il client SAP ogni volta.
Gestire i click: SBO_Application_MenuEvent¶
Il MenuEvent viene scatenato due volte da SAP per ogni click:
| Fase | BeforeAction |
Quando |
|---|---|---|
| Prima | true |
Prima che SAP esegua l'azione. Puoi bloccarla con BubbleEvent = false. |
| Dopo | false |
Dopo che l'azione è stata completata. È qui che reagiamo. |
Per i menu personalizzati, ci interessa quasi sempre solo la fase dopo (BeforeAction == false). Il MenuUID ti dice quale voce è stata cliccata.
BubbleEvent controlla la propagazione dell'evento: impostandolo a true l'evento continua normalmente, con false SAP blocca l'azione. Per i menu custom lascialo sempre a true.
Il pattern Before/After
Questo pattern è una costante in tutta la UI API di SAP, non solo nei menu. Lo ritroverai negli eventi delle form, degli item, ecc. Serve per darti la possibilità di validare o bloccare un'azione prima che SAP la esegua, oppure di reagire dopo.
5. Struttura Risultante¶
Il codice sopra genera questa struttura nel menu Moduli di SAP:
📂 Moduli
└── 📂 Il Mio Add-on (mt_POPUP)
├── 📄 SubMenu 1 (mt_STRING) → genera MenuEvent
├── ── ── ── ── (mt_SEPERATOR)
├── 📄 SubMenu 3 (mt_STRING) → genera MenuEvent
└── 📂 SubMenu 4 (mt_POPUP)
├── 📄 Sub sub Menu 1 (mt_STRING) → genera MenuEvent
├── ── ── ── ── (mt_SEPERATOR)
└── 📄 Sub sub Menu 3 (mt_STRING) → genera MenuEvent