Page 1 of 1

CONTRUIR UN MENU en ventana principal desde una tabla o dbf

Posted: Mon Aug 12, 2013 7:37 pm
by joseluisysturiz
Necesito crear menues personalizados dependiendo de los niveles de usuarios los cuales las opciones a mostrar estaran en una tabla mysql o una dbf, se que en el foro habia algo parecido o un sample, pero tengo bastante rato buscandolo y nada que lo consigo, si alguien por casualidad tiene el lnk del tema o un sample se lo agradeceria, las opciones de menu las creare basado en un modelo que contiene todas las opciones del menu, y luego voy seleccionando las que el usuario puede o no tener disponible, saludos... :shock:

Re: CONTRUIR UN MENU en ventana principal desde una tabla o dbf

Posted: Mon Aug 12, 2013 10:24 pm
by noe aburto
En lo personal, tengo una una variable publica x una cadena con 150 digitos: ej. '0001000100010000111111110001111111111...
cada caracter indica el numeto de permiso en el sistema de cada opcion dentro del menu, para contruir el menu hago algo asi:

if PasaProceso(i)
MENUITEM OPCI_OBJ(i) PROMPT OPCI_TIT(i) ACTION OPCI_ACC(i) BLOCK OPCI_BLO(i) RESOURCE OPCI_BMP(i)
else
MENUITEM OPCI_OBJ(i) PROMPT OPCI_TIT(i) ACTION OPCI_ACC(i) BLOCK OPCI_BLO(i) RESOURCE OPCI_BMP(i) DISABLED
endif

la funcion PasaProceso(i) lo unico que hace es tomas de la variable publica el caracter equivalente a (i), si es 1 pasa, si es 0, no
y la opcion del menu esta DISABLED

Re: CONTRUIR UN MENU en ventana principal desde una tabla o dbf

Posted: Mon Aug 12, 2013 11:58 pm
by horacio
Fijate si este hilo te ayuda

http://forums.fivetechsupport.com/viewt ... nu#p106243
Saludos

Re: CONTRUIR UN MENU en ventana principal desde una tabla o dbf

Posted: Tue Aug 13, 2013 12:27 am
by joseluisysturiz
horacio wrote:Fijate si este hilo te ayuda

http://forums.fivetechsupport.com/viewt ... nu#p106243
Saludos
Gracias a los que han respondido, pero Horacio, lo que me dices es para llamar el nuevo menu, lo que necesito es como seria el algortimo para construir el menu, ya que las opciones de menu en _ unos deberan mostrarse y en otros no, dependiendo las que se le haya asiganado a dicho usuario, imagino debere usar un for o do while o algo parecido, doy ejemplo...saludos... :shock:

para un usuario a lo mejor tiene asignado las siguientes opciones:

Code: Select all

   
MENU oMenu 2007
        MENUITEM "&Archivo"
          MENU
            MENUITEM "Salir del Sistema" ;
               RESOURCE "SALIR16" ;
               ACTION ( oDatos:oWndPpal:END() ) ;

          ENDMENU

        MENUITEM "&Inventario"
          MENU
            MENUITEM "Productos" ACTION ( productos() )
            MENUITEM "Marcas" ACTION ( marcas() )
            MENUITEM "Clases" ACTION ( lineas() )
          SEPARATOR
            MENUITEM "Movimientos" ACTION ( movinv() )
          SEPARATOR
            MENUITEM "Reportes" ACTION msginfo("Listados y Reportes")
          ENDMENU
ENDMENU
 
pero para otro solo estas...

Code: Select all

   MENU oMenu 2007
        MENUITEM "&Archivo"
          MENU
            MENUITEM "Salir del Sistema" ;
               RESOURCE "SALIR16" ;
               ACTION ( oDatos:oWndPpal:END() ) ;

          ENDMENU

        MENUITEM "&Inventario"
          MENU
            MENUITEM "Productos" ACTION ( productos() )
            MENUITEM "Clases" ACTION ( lineas() )
            MENUITEM "Reportes" ACTION msginfo("Listados y Reportes")
          ENDMENU
ENDMENU
 
voy asignando las opciones principales y derivadas en linea, las grabo en una tabla o dbf como si fueran los detalles de una factura, el punto es que el menu debe construirse solo dinamicamente al momento de validar la clave de acceso del usuario, dependiendo de sus opciones asignadas, algo como un tree que vi que ramifica el menu ppal y luego sus derivados y al final un checkbox para seleccionar las opciones a asignar.

Espero no haber enredado mas el papagallo, gracias, saludos... :shock:

Re: CONTRUIR UN MENU en ventana principal desde una tabla o dbf

Posted: Tue Aug 13, 2013 2:15 am
by russimicro
FUNCTION MenuPrincipal(oWnd)

LOCAL cPatTem := "C:\TEMP\"
LOCAL cNombas := 'Menu'+ALLTRIM(STR(hb_random(10000000),8,0))+M->cCiaAct+cNroUsr
LOCAL cFilTem := cNombas+'.TMD'
LOCAL cFilTeI := cNombas+'.CDX'
LOCAL oGif
LOCAL nUsuSis := VAL(cNroUsr)
LOCAL cAliAct := ALIAS()
LOCAL cNomba1 := 'SEGURIDAD'+ALLTRIM(STR(hb_random(10000000),8,0))+M->cCiaAct+cNroUsr
LOCAL cFilTe1 := cNomba1+'.TMD'
LOCAL cFilTe2 := cNomba1+'.CDX'
LOCAL cPatLoc := "C:\TEMP\"
LOCAL cNroOpc := ""

IF !lUsaTab(M->cPatSis+"\","OPCIONES.DAT","OPC",{"OPCIONES.CDX"},.T.)
IF !EMPTY(cAliAct)
SELECT &cAliAct
ENDIF
RETURN
ENDIF

SELECT OPC
DBSETORDER(1)

filtrarScope("OPC",1,STR(VAL(M->cNroUsr),2,0),STR(VAL(M->cNroUsr),2,0))

FERASE("C:\TEMP\"+cFilTeI)
COPY_FILE_DBF_DBF( "MENU.DAT", "C:\TEMP\"+cFilTem )

IF !FILE("C:\TEMP\"+cFilTem)
MYMEN("Error. No existe archivo de configuraci¢n de menus")
RETURN
ENDIF

IF SELECT("MEN") <> 0
CLOSE MEN
ENDIF

IF !lUsaTab(cPatTem, cFilTem,"MEN",{},.F.,NIL,"DBFCDX")
RETURN
ENDIF

SELECT MEN
INDEX ON CCODIGOMEN TAG ORDER1 TO &("C:\TEMP\"+cFilTeI)
DBSETORDER(1)
GO TOP

MENU oMenu 2007

DO WHILE MEN->( !EOF() )
cNroOpc := ALLTRIM(MEN->cNroOpcSeg)
IF XXVALOPUSR(cNroOpc)
MENUITEM HB_OEMTOANSI( ALLTRIM(MEN->cNombreMen) )
ELSE
MENUITEM HB_OEMTOANSI( ALLTRIM(MEN->cNombreMen) ) DISABLED
ENDIF

MENU
MENUX(1)
ENDMENU

ENDDO

ENDMENU

// CLOSE MEN
// CLOSE OPC

RETURN

//**************************************************************************************

FUNCTION MENUX( nNroNiv )

LOCAL bBloEje, nNivAct
LOCAL cNroOpc := ""

nNivAct := SUBS( MEN->cCodigoMen, 1, nNroNiv * 2 )
DO WHILE MEN->( !EOF() ) .AND. SUBS( MEN->cCodigoMen,1,nNroNiv * 2 ) == nNivAct

IF LEN(ALLTRIM(MEN->cCodigoMen)) > nNroNiv * 2
cFunEje := MEN->cFunEjeMen
cNomOpc := MEN->cNombreMen
cRegAct := ALLTRIM(MEN->cCodigoMen)
cNroOpc := ALLTRIM(MEN->cNroOpcSeg)
MEN->( DBSKIP() )
cRegSig := SUBS( MEN->cCodigoMen,1,( nNroNiv + 1 ) * 2 )

IF cRegAct == cRegSig

IF XXVALOPUSR(cNroOpc) // cRegAct
MENUITEM HB_OEMTOANSI( ALLTRIM(cNomOpc) )
ELSE
MENUITEM HB_OEMTOANSI( ALLTRIM(cNomOpc) ) DISABLED
ENDIF

SELECT MEN
SKIP -1
MENU
MenuX( nNroNiv + 1 )
ENDMENU
ELSE

bBloEje := &( "{||" + IF( EMPTY( cFunEje ), ".T.", ALLTRIM( cFunEje ) ) + "}" )

IF XXVALOPUSR(cNroOpc)
MENUITEM HB_OEMTOANSI( ALLTRIM(cNomOpc) ) ACTION ( bBloEje ) BLOCK bBloEje // FILENAME getImage( BITMAP )
ELSE
MENUITEM HB_OEMTOANSI( ALLTRIM(cNomOpc) ) DISABLED ACTION ( bBloEje ) BLOCK bBloEje // FILENAME getImage( BITMAP )
ENDIF

ENDIF
ELSE
MEN->( DBSKIP() )
ENDIF

ENDDO

RETURN NIL


//**********************************************

Re: CONTRUIR UN MENU en ventana principal desde una tabla o dbf

Posted: Tue Aug 13, 2013 2:50 am
by joseluisysturiz
Saludos russimicro, estoy revisando lo que me distes, creo es lo que ando buscando, luego te comento, estamos a la orden por aca en Venezuela, saludos... :shock:

Re: CONTRUIR UN MENU en ventana principal desde una tabla o dbf

Posted: Tue Aug 13, 2013 2:54 am
by cmsoft
Yo lo hago de ésta manera:

Code: Select all

// --------------------------------------------------------------------//
// ------------- Funcion men£ de la pantalla principal ----------------//
// --------------------------------------------------------------------//
STATIC FUNCTION HazMenu(musuario,nItems) // Musuario es el nombre de un usuario válido, ;
                                                                     // y nItems se pasa por referencia para poner en que nivel queda el menuinfo
LOCAL i, oMenu, j, oMenuItem, nivel, nivel1, ult
MEMVAR oWPpal
use menues ALIAS "menu1" SHARED NEW
SET INDEX TO menues

menu1->(DBSEEK(musuario))
MENU oMenu
j := 0
aproce :={}
nItems := 1
nivel  := 1
ult    := "N"
DO WHILE menu1->usuario = musuario
   IF menu1->submenu = "S"            && Si es submenu
      MENUITEM ALLTRIM(menu1->detalle)
      ult := "S"
      MENU
      ELSE
      ult := "N"
      IF menu1->submenu = "-"         && Si un separador
         SEPARATOR
         ELSE                         && Si un proceso
         j++
         AADD(aproce,menu1->modulo)      && Cargo la tabla de procesos
         MENUITEM oMenuItem PROMPT ALLTRIM(menu1->detalle);
                            ACTION ejecfunc(oMenuItem:nHelpid) HELPID j
      ENDIF
   ENDIF
   IF nivel = 1     && Si es un titulo
      nItems++      && Cuento los items del menu principal
   ENDIF
   nivel1 := AT("0",menu1->orden1) - 1
   menu1->(DBSKIP(1))
   nivel  := AT("0",menu1->orden1) - 1
   IF nivel < nivel1 .and. menu1->usuario = musuario      && Si retrocedo
      FOR i := nivel TO (nivel1 - 1)                      && en nivel pongo
          ENDMENU                                         && los ENDMENU
      NEXT i
      IF ult = "S" .and. nivel = 1                        && Si es titulo
         ENDMENU                                          && solo tambien
      ENDIF
      ELSE
      IF ult = "S" .and. nivel = 1                        && Si es titulo
         ENDMENU                                          && solo tambien
      ENDIF
   ENDIF
ENDDO
  ENDMENU
  ** Esta parte del menu siempre va
  MENUITEM "&Salir" 
        MENU
          MENUITEM "&Salir" ACTION (oWPpal:end)
          SEPARATOR
          MENUITEM "Calc&uladora"     ACTION WinExec( "Calc.exe" )
          MENUITEM "Configuar &Impresora" ACTION PrinterSetup()
        ENDMENU
ENDMENU
CLOSE menu1
RETURN oMenu

STATIC FUNCTION ejecfunc(mifunc)
LOCAL fun
fun := ALLTRIM(aproce[mifunc])
DO &fun
RETURN NIL
 
El proceso se base un una DBF que contiene que items del menú son visibles para cada usuario (basados en una tabla que contiene el menú completo, y que obviamente tiene su ABM de usuarios y menues)

La tabla es la siguiente:

Code: Select all

USUARIO MODULO   DETALLE SUBMENU ORDEN1
 
Donde usuario es el usuario, módulo es la función que debe ejecutar, detalle es lo que sale en el menu, submenu indica si es submenu, separador o item, y orden1 es el orden del item de menu general (en formato cuenta contable, 100000, 110000, 120000, 200000, 210000, 211000, etc)
Es una función que utilizo desde mis viejos programas CLIPPER y que me ha servido mucho.
Si te interesa también la he desarrollado para MySql con Dolphin, avisame y te la paso.
Saludos y espero te sirva

Re: CONTRUIR UN MENU en ventana principal desde una tabla o dbf

Posted: Tue Aug 13, 2013 3:05 am
by joseluisysturiz
Saludos cmsoft, es lo que busco, la igual que del otro colega de Colombia, leer y revisare sus .prg, la unica diferencia entre comillas, es que en vez de una dbf uso una tabla con mysql, ya habia creado la tabla con _ parecido a los tuyos, gracias y saludos... :shock:

Re: CONTRUIR UN MENU en ventana principal desde una tabla o dbf

Posted: Tue Aug 13, 2013 8:09 am
by Antonio Mart.
Hola,

Para mi la cuestión principal de los menues configurables sería separar la construccion del menu de su configuración.
Para ello necesitaríamos que el comando MENUITEM dispusiera de un tag (etiqueta) ID. Otra opción sería ponérselo nosotros mismos redefiniendo el comando MENUITEM.
Teniendo este ID, el resto lo haríamos así

1) Funcion. Encerrariamos la funcion del menu en una funcion BuildMenu()
2) Configuración. Invocariamos a BuildMenu() para la UI (interfaz) de configuracion del menu. En ese caso nos sirve para obtener los distintos menuitem para configurar un tree de configuración que se guardaría en una .dbf o un .txt o lo que sea.
3) Carga menú. Invocaríamos a BuildMenu() para construir el menu de la Window. El menú se crearía según lo configurado en 2.

Se podría profundizar en la forma de hacerlo, pero creo que a grandes rasgos podría ser así.

Espero que a alguien le sirva la idea.
Saludos

Re: CONTRUIR UN MENU en ventana principal desde una tabla o dbf

Posted: Tue Aug 13, 2013 2:29 pm
by jcenteno
José Luis,

Mira si te sirve:

FUNCTION BldMenu()
*----------------------------------------------------------------*
LOCAL oMainMenu, oMnuItem, lRight, cValue, cMnuAlias, i:= 1, nRec, fAction, cFileBmp, cResName
LOCAL cQry, oQry, nL, nEnd

IF ! oApp:lMySql && Si es DBF

IF !AbreDbf( @cMnuAlias, oSystem:csysmenu, 1 )
oWnd:PostMsg(WM_CLOSE)
ENDIF
nRec := (cMnuAlias)->( AdsKeyCount( ,,ADS_RESPECTSCOPES ) ) //nRec := (cMnuAlias)->( LastRec() )

MENU oApp:oMainMenu 2007 // MENU oMainMenu 2007

FOR i := 1 To nRec

IF (cMnuAlias)->FLDSEPARAT //== TRUE
SEPARATOR
ENDIF

IF (cMnuAlias)->FLDVIRTKEY == 0
MENUITEM oMnuItem PROMPT OemToAnsi(ALLTRIM((cMnuAlias)->FLDTXTOPT)) ;
MESSAGE OemToAnsi(ALLTRIM((cMnuAlias)->FLDMESSAGE))
ELSE
MENUITEM oMnuItem PROMPT OemToAnsi(ALLTRIM((cMnuAlias)->FLDTXTOPT)) ;
MESSAGE OemToAnsi(ALLTRIM((cMnuAlias)->FLDMESSAGE)) ;
ACCELERATOR (cMnuAlias)->FLDNSTATE, (cMnuAlias)->FLDVIRTKEY
ENDIF

oMnuItem:lChecked := (cMnuAlias)->FLDCHECK

oMnuItem:lActive := ( lRight:= Eval( {||&(ALLTRIM((cMnuAlias)->FLDCONDI))} ) )

IF ! EMPTY( fAction := ALLTRIM((cMnuAlias)->FLDACTION) )
oMnuItem:bAction := &( fAction )
ENDIF

IF FILE( cFileBmp := oGraph:cmnuimgpath + ALLTRIM((cMnuAlias)->FLDFILEBMP) )
oMnuItem:hBitmap:= ReadBitmap( 0, cFileBmp )
ENDIF
IF ! EMPTY( cResName := ALLTRIM((cMnuAlias)->FLDRESBMP) )
oMnuItem:hBitmap:= LoadBitmap( GetResources(), cResName )
ENDIF
IF ! EMPTY( ALLTRIM((cMnuAlias)->FLDSYS) )
AAdd( oApp:aObjSys, oMnuItem )
ENDIF

cValue := ALLTRIM((cMnuAlias)->CNEXT)
DO CASE
CASE cValue == 'M0'
MENU
CASE cValue == 'M1'
MENU
CASE cValue == 'E1'
ENDMENU
CASE cValue == 'E2'
ENDMENU ; ENDMENU
CASE cValue == 'E3'
ENDMENU ; ENDMENU ; ENDMENU
CASE cValue == 'E4'
ENDMENU ; ENDMENU ; ENDMENU ; ENDMENU
CASE cValue == 'E5'
ENDMENU ; ENDMENU ; ENDMENU ; ENDMENU ; ENDMENU
CASE cValue == 'E6'
ENDMENU ; ENDMENU ; ENDMENU ; ENDMENU ; ENDMENU ; ENDMENU
END CASE
(cMnuAlias)->(dbSkip())
NEXT i

MENUITEM 'A&yuda' HELP
MENU
MENUITEM '&Help' ACTION HelpIndex() RESOURCE 'AYUDA1'
MENUITEM '&Acerca de...' ACTION fAbout()
ENDMENU
ENDMENU

(cMnuAlias)->(dbCloseArea())

ELSE && Para MySql

cQry := "SELECT * FROM " + oSystem:csysmenu + " WHERE lActive ORDER BY fldnivel ASC"

IF !AbreDbf( @oQry, oSystem:csysmenu, 1,, oRDD:rdbms, cQry )
MsgInfo('Error de apertura')
oWnd:PostMsg(WM_CLOSE)
ENDIF

nRec := oQry:LastRec()

oApp:oMainMenu := MenuBegin( ,,, TRUE ) // MENU oApp:oMainMenu 2007

FOR i := 1 To nRec

IF ( oQry:FLDSEPARAT ) //== TRUE
*SEPARATOR
oMnuItem:= MenuAddItem()
ENDIF

IF FILE( cFileBmp := oGraph:cmnuimgpath + ALLTRIM(oQry:FLDFILEBMP) )
ENDIF
IF ! EMPTY( cResName := ALLTRIM(oQry:FLDRESBMP) )
ENDIF
IF ! EMPTY( ALLTRIM(oQry:FLDACTION) )
fAction := &( ALLTRIM(oQry:FLDACTION) )
ENDIF

&& Crea nuevo Item del Menú
WITH OBJECT ( oMnuItem := MenuAddItem( ,,,,, cFileBmp, cResName, oApp:oMainMenu ) )

:cPrompt := ALLTRIM( oQry:FLDTXTOPT )
:cMsg := ALLTRIM( oQry:FLDMESSAGE )
:bAction := fAction
:lActive := ( lRight:= Eval( {||&( ALLTRIM( oQry:FLDCONDI ) )} ) ) //lRight:= Eval( {|| &(ALLTRIM((cMnuAlias)->FLDCONDI)) } )
:lBreak := FALSE
:lChecked := oQry:FLDCHECK
:lHelp := FALSE
:oMenu := oApp:oMainMenu
:nVKState := oQry:FLDNSTATE
:nVirtKey := oQry:FLDVIRTKEY

END

IF ! EMPTY( ALLTRIM(oQry:FLDSYS) )
AAdd( oApp:aObjSys, oMnuItem )
ENDIF

cValue := ALLTRIM(oQry:CNEXT) && Próximo nivel a crear o eliminar

nEnd := oQry:NLOOP
FOR nL := 1 TO nEnd

DO CASE
CASE Left(cValue,1) = 'M'
MenuBegin( ,,, TRUE )
CASE Left(cValue,1) = 'E'
MenuEnd()
END CASE

NEXT nL

oQry:Skip()
NEXT i

MENUITEM 'A&yuda' HELP
MENU
MENUITEM '&Help' ACTION HelpIndex() RESOURCE 'AYUDA1'
MENUITEM '&Acerca de...' ACTION fAbout()
ENDMENU
ENDMENU

oQry:End()

ENDIF

RELEASE lRight, cValue, cMnuAlias, i, nRec, fAction, cFileBmp, cResName, cQry

RETURN oApp:oMainMenu

Re: CONTRUIR UN MENU en ventana principal desde una tabla o dbf

Posted: Wed Aug 14, 2013 12:59 am
by cmsoft
Jose Luis:
Por si te interesa, te dejo la función pero para una tabla MySql con Dolphin. También le agregré al menú el estilo 2007 con íconos en el menú

Code: Select all

// --------------------------------------------------------------------//
// ------------- Funcion men£ de la pantalla principal ----------------//
// --------------------------------------------------------------------//
STATIC FUNCTION HazMenu(musuario,nItems)
LOCAL i, oMenu, j, oMenuItem, nivel, nivel1, ult, oQry
MEMVAR oWnd
oQry := oServer:Query( "SELECT * FROM menues WHERE usuario="+ClipValue2SQL(musuario))
MENU oMenu 2007
j := 0
aproce :={}
nItems := 1
nivel  := 1
ult    := "N"
DO WHILE !oQry:Eof()
   IF oQry:submenu = "S"            && Si es submenu
      MENUITEM ALLTRIM(oQry:detalle) RESOURCE ALLTRIM(oQry:icono)
      ult := "S"
      MENU
      ELSE
      ult := "N"
      IF oQry:submenu = "-"         && Si un separador
         SEPARATOR
         ELSE                         && Si un proceso
         j++
         AADD(aProce,oQry:modulo)      && Cargo la tabla de procesos
         MENUITEM oMenuItem PROMPT ALLTRIM(oQry:detalle);
                            ACTION ejecfunc(oMenuItem:nHelpid) HELPID j;
                            RESOURCE ALLTRIM(oQry:icono)
      ENDIF
   ENDIF
   IF nivel = 1     && Si es un titulo
      nItems++      && Cuento los items del menu principal
   ENDIF
   nivel1 := AT("0",oQry:orden1) - 1
   oQry:Skip()
   nivel  := AT("0",oQry:orden1) - 1
   IF nivel < nivel1 .and. oQry:usuario = musuario      && Si retrocedo
      FOR i := nivel TO (nivel1 - 1)                      && en nivel pongo
          ENDMENU                                         && los ENDMENU
      NEXT i
      IF ult = "S" .and. nivel = 1                        && Si es titulo
         ENDMENU                                          && solo tambien
      ENDIF
      ELSE
      IF ult = "S" .and. nivel = 1                        && Si es titulo
         ENDMENU                                          && solo tambien
      ENDIF
   ENDIF
ENDDO
  ENDMENU
  ** Esta parte del menu siempre va
  MENUITEM "&Salir" 
        MENU
          MENUITEM "&Salir" ACTION (oWnd:end) RESOURCE "SALIR1"
          SEPARATOR
          MENUITEM "&Acerca" ACTION MsgInfo("Sistema XXXXXXXXXX" +CHR(10)+;
                 "CM Soft - 2013"+CHR(10)+;
                 "www.cmsoft.com.ar"+CHR(10)+;
                 "Desarrollo de sistemas"+CHR(10)+;
                 "Todos los derechos reservados","Acerca de XXXXXXXXXXXXX")
          MENUITEM "Calc&uladora"     ACTION WinExec( "Calc.exe" ) RESOURCE "CALCU1"
          MENUITEM "Configuar &Impresora" ACTION PrinterSetup()
        ENDMENU
ENDMENU
oQry:End()
RETURN oMenu
Saludos!

Re: CONTRUIR UN MENU en ventana principal desde una tabla o dbf

Posted: Wed Aug 14, 2013 3:10 am
by joseluisysturiz
Muchas gracias CMSOFT, estoy descargando y analizando lo enviado para adaptarlo a mi sistema, luego comento, saludos... :shock: