Spanish [RESUELTO] Problema con Menu creado por codigo

roerGarcia

Active Member
Licensed User
Longtime User
Resuelto con los aportes de angel y Rubsanpe.
El poder de la comunidad.


Buenos dias/tardes/noches, segun corresponda.

Comunidad, amigos todos, compañeros de codigo, jajaja, perdon, ando en plan simple.

Tengo la siguiente situacion:

Menu creado por codigo:
mb1.Initialize("mb1")
    MainForm.RootPane.AddNode(mb1, 0, 0, -1, 32dip)
   
    mnu0.Initialize("Archivo", "mb1")
    mi.Initialize("Nuevo", "mb1") : mi.Tag = "NEW" : mnu0.MenuItems.Add(mi)
    mi.Initialize("Salir", "mb1") : mi.Tag = "FIN" : mnu0.MenuItems.Add(mi)
    mb1.Menus.Add(mnu0)
   
    mnu0.Initialize("Folio", "mb1")
    mi.Initialize("Registrar Nuevo", "mb1") : mi.Tag = "RNF" : mnu0.MenuItems.Add(mi)
    mi.Initialize("Revisado", "mb1") : mi.Tag = "MRH" : mnu0.MenuItems.Add(mi)
    mi.Initialize("Cerrado Hoy", "mb1") : mi.Tag = "MCH" : mnu0.MenuItems.Add(mi)
    mi.Initialize("Cerrado el ", "mb1") : mi.Tag = "MCD" : mnu0.MenuItems.Add(mi)
    mi.Initialize("Ajustar", "mb1") : mi.Tag = "AJU" : mnu0.MenuItems.Add(mi)
    mi.Initialize("Imprimir", "mb1") : mi.Tag = "PRN" : mnu0.MenuItems.Add(mi)
    mb1.Menus.Add(mnu0)
   
    'cm.Initialize("")
    mnu0.Initialize("Reportado Via", "mb1")
    mi.Initialize("Aplicacion", "mb1") : mi.Tag = "vapl" : mnu0.MenuItems.Add(mi)
    mi.Initialize("Correo", "mb1") : mi.Tag = "vcor" : mnu0.MenuItems.Add(mi)
    mi.Initialize("Facebook", "mb1") : mi.Tag = "vfac" : mnu0.MenuItems.Add(mi)
    mi.Initialize("Presencial", "mb1") : mi.Tag = "vpre" : mnu0.MenuItems.Add(mi)
    mi.Initialize("TEC", "mb1") : mi.Tag = "vtec" : mnu0.MenuItems.Add(mi)
    mi.Initialize("TEQ", "mb1") : mi.Tag = "vteq" : mnu0.MenuItems.Add(mi)
    mi.Initialize("Twitter", "mb1") : mi.Tag = "vtwi" : mnu0.MenuItems.Add(mi)
    mi.Initialize("Whatsapp", "mb1") : mi.Tag = "vwha" : mnu0.MenuItems.Add(mi)
    'cm.MenuItems.Add(mnu0)
    mb1.Menus.Add(mnu0)
   
    mnu0.Initialize("Area indicada", "mb1")
    mi.Initialize("BUS", "mb1") : mi.Tag = "abus" : mnu0.MenuItems.Add(mi)
    mi.Initialize("COM", "mb1") : mi.Tag = "acom" : mnu0.MenuItems.Add(mi)
    mi.Initialize("EST", "mb1") : mi.Tag = "aest" : mnu0.MenuItems.Add(mi)
    mi.Initialize("MAN", "mb1") : mi.Tag = "aman" : mnu0.MenuItems.Add(mi)
    mi.Initialize("INAPAM", "mb1") : mi.Tag = "aina" : mnu0.MenuItems.Add(mi)
    mi.Initialize("RH", "mb1") : mi.Tag = "arh" : mnu0.MenuItems.Add(mi)
    mi.Initialize("TRA", "mb1") : mi.Tag = "atra" : mnu0.MenuItems.Add(mi)
    mi.Initialize("OTR", "mb1") : mi.Tag = "aotr" : mnu0.MenuItems.Add(mi)
    'cm.MenuItems.Add(mnu0)
    mb1.Menus.Add(mnu0)
   
    mnu0.Initialize("Sistema", "mb1")
    mi.Initialize("Metro", "mb1") : mi.Tag = "smet" : mnu0.MenuItems.Add(mi)
    mi.Initialize("Circuito DIF", "mb1") : mi.Tag = "sdif" : mnu0.MenuItems.Add(mi)
    mi.Initialize("ECOVIA", "mb1") : mi.Tag = "seco" : mnu0.MenuItems.Add(mi)
    mi.Initialize("MetroBus", "mb1") : mi.Tag = "sbus" : mnu0.MenuItems.Add(mi)
    mi.Initialize("TransMetro GPE", "mb1") : mi.Tag = "sgpe" : mnu0.MenuItems.Add(mi)
    'cm.MenuItems.Add(mnu0)
    'txadescrip.ContextMenu = cm
    mb1.Menus.Add(mnu0)

Obtenemos lo que se supone debemos obtener con este codigo:

1651849899741.png


Hasta aqui todo va bien. En el foro encontramos que la inicializacion del menu o submenu o menuitems pueden incluir la sub rutina que manejara el evento que el clic produzca. En caso de no incluirlo se toma el nombre del parent. En este caso el Menu mb1. Pues si, el problema es que en todos los clics el Sender resultante es el ultimo menu item agregado al menu Sistema, en este caso.

Seleccionando Archivo - Nuevo el log me arroja:
1651850120264.png

Que corresponde a este codigo:
Codigo que maneja el evento:
Private Sub mb1_Action
    Dim miClicked As MenuItem = Sender
    Log("mb0 " & miClicked.Tag)
    Log("mb0 " & miClicked.Text)
    Select miClicked.Tag
        Case "RNF"
            addAFolio

Como veran opte por tomar el TAG para llevar a cabo las acciones pertinentes, pero dado que cualquier clic me da un Sender erroneo me imposibilita para ello.

¿Cual es mi error aqui?

- Probe sin indicar el evento.
- Incluyendo el evento a nivel menu sub menu e item.
- Use otra sub con otro nombre.
- Cambie del menu original en el diseñador por este incluido 100% en codigo
- El menu original del diseñador pues no tenia problema, pero quiero agregar opciones al vuelo.

Se supone que segui las reglas, pero no logro que el TAG o el TEXT de la opcion clicada llegue a la sub que maneja el evento.

Saludos! y gracias anticipadas.
 
Last edited:

roerGarcia

Active Member
Licensed User
Longtime User
Caracoles... el proyecto anexo se creo desde cero, b4j, el mismo codigo simple de adicion de menubar y adolece de la misma falla.

1651869071811.png


Creo que tendre que reportarlo directo a Erel.
 

Attachments

  • menubarx.zip
    1.9 KB · Views: 163
Last edited:

angel_

Well-Known Member
Licensed User
Longtime User
No te serviría así

B4X:
Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("Layout1")
    MainForm.Show
    mb1.Initialize("mb1")
    MainForm.RootPane.AddNode(mb1, 0, 0, -1, 32dip)
    Dim mnu0 As Menu
    Dim mi As MenuItem
    mnu0.Initialize("Archivo", "mnu0")
   
    mi.Initialize("Nuevo", "mb1")
    mnu0.MenuItems.Add(mi)
   
    mi.Initialize("Salir", "mb2")
    mnu0.MenuItems.Add(mi)
    mb1.Menus.Add(mnu0)
End Sub

Sub mb1_Action
    Log("NEW")
End Sub

Sub mb2_Action
    Log("FIN")
End Sub
 

Rubsanpe

Active Member
Licensed User
Basado en tu código esto funciona para mi

B4X:
#Region Project Attributes
    #MainFormHeight: 600
    #MainFormWidth: 600
#End Region

Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Private xui As XUI
    Public mb1 As MenuBar
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("Layout1")
    mb1.Initialize("mb1")
    MainForm.RootPane.AddNode(mb1, 0, 0, -1, 32dip)
    Dim mnu0 As Menu
    
    mnu0.Initialize("Archivo", "mb1")
    Dim mi As MenuItem
    mi.Initialize("Nuevo", "mb1") : mi.Tag = "NEW" : mnu0.MenuItems.Add(mi)
    Dim mi As MenuItem
    mi.Initialize("Salir", "mb1") : mi.Tag = "FIN" : mnu0.MenuItems.Add(mi)
    mb1.Menus.Add(mnu0)
    MainForm.Show
End Sub

Sub mb1_Action
    Dim mim As MenuItem = Sender
    Log(mim.Tag)
End Sub

Declara la opción de menú cada vez. Es lo mismo que se hace cuando creas controles similares en un bucle.

Rubén
 

roerGarcia

Active Member
Licensed User
Longtime User
No te serviría así

B4X:
Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("Layout1")
    MainForm.Show
    mb1.Initialize("mb1")
    MainForm.RootPane.AddNode(mb1, 0, 0, -1, 32dip)
    Dim mnu0 As Menu
    Dim mi As MenuItem
    mnu0.Initialize("Archivo", "mnu0")
  
    mi.Initialize("Nuevo", "mb1")
    mnu0.MenuItems.Add(mi)
  
    mi.Initialize("Salir", "mb2")
    mnu0.MenuItems.Add(mi)
    mb1.Menus.Add(mnu0)
End Sub

Sub mb1_Action
    Log("NEW")
End Sub

Sub mb2_Action
    Log("FIN")
End Sub
Probare tu sugerencia.

(Pero, ves alguna falla en mi planteamiento original? No se puede usar una misma sub para manejar el evento mediante el Sender?)
Gracias!
 

roerGarcia

Active Member
Licensed User
Longtime User
No te serviría así

B4X:
Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("Layout1")
    MainForm.Show
    mb1.Initialize("mb1")
    MainForm.RootPane.AddNode(mb1, 0, 0, -1, 32dip)
    Dim mnu0 As Menu
    Dim mi As MenuItem
    mnu0.Initialize("Archivo", "mnu0")
  
    mi.Initialize("Nuevo", "mb1")
    mnu0.MenuItems.Add(mi)
  
    mi.Initialize("Salir", "mb2")
    mnu0.MenuItems.Add(mi)
    mb1.Menus.Add(mnu0)
End Sub

Sub mb1_Action
    Log("NEW")
End Sub

Sub mb2_Action
    Log("FIN")
End Sub
Probado. Funciona. Gracias.
Pero no ha desaparecido mi duda.

El initialize al menu item, no es necesario para re-establecer al objeto, entonces...
 

roerGarcia

Active Member
Licensed User
Longtime User
Basado en tu código esto funciona para mi

B4X:
#Region Project Attributes
    #MainFormHeight: 600
    #MainFormWidth: 600
#End Region

Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Private xui As XUI
    Public mb1 As MenuBar
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("Layout1")
    mb1.Initialize("mb1")
    MainForm.RootPane.AddNode(mb1, 0, 0, -1, 32dip)
    Dim mnu0 As Menu
   
    mnu0.Initialize("Archivo", "mb1")
    Dim mi As MenuItem
    mi.Initialize("Nuevo", "mb1") : mi.Tag = "NEW" : mnu0.MenuItems.Add(mi)
    Dim mi As MenuItem
    mi.Initialize("Salir", "mb1") : mi.Tag = "FIN" : mnu0.MenuItems.Add(mi)
    mb1.Menus.Add(mnu0)
    MainForm.Show
End Sub

Sub mb1_Action
    Dim mim As MenuItem = Sender
    Log(mim.Tag)
End Sub

Declara la opción de menú cada vez. Es lo mismo que se hace cuando creas controles similares en un bucle.

Rubén
Ok, reviso tambien esto.
Entonces, como regla... manejar controles re-utilizados va mejor con dim en cada ocasion que utilizar initialize en el loop.
Algo aprendi hoy.
Gracias a ambos.
 

Rubsanpe

Active Member
Licensed User
Lo que pasas a las funciones son referencias a los controles. Si despues modificas algun parametro lo sigues actualizando a esa referencia. Por eso en tu caso siempre hacia referencia a la ultima opción de menú. Definiendolo cada vez te aseguras de que no apuntan al mismo control.

Rubén
 
Top