ACHOICE()
 Ejecuta un menú emergente
------------------------------------------------------------------------------
 Sintaxis

     ACHOICE(<nSup>, <nIzq>, <nInf>, <nDer>,
        <acElementosMenú>,
        [<alElementosSeleccionables> | <lElementosSeleccionables>],
        [<cFunciónUsuario>],
        [<nElementoInicial>],
        [<nFilaVentana>]) --> nPosición

 Argumentos

     <nSup>, <nIzq> y <nInf>, <nDer> son las coordenadas
     superior izquierda e inferior derecha de la ventana. Los valores de
     fila pueden estar comprendidos entre cero y MAXROW() y los valores de
     columna entre cero y MAXCOL().

     <acElementosMenú> es la matriz de cadenas de caracteres que se va a
     mostrar como elementos de menú. Los elementos de menú individuales se
     identifican por sus posiciones numéricas en esta matriz.

     <alElementosSeleccionables> es una matriz paralela de valores
     lógicos (un elemento para cada elemento de <acElementosMenú>), que
     especifica los elementos de menú seleccionables. Los elementos de esta
     matriz pueden ser valores lógicos o cadenas de caracteres. ACHOICE() no
     permite cadenas nulas y detiene la visualización si encuentra una. Si
     algún elemento es una cadena de caracteres, se evalúa como
     macroexpresión y debe dar un resultado de tipo lógico. En cualquier
     caso, un valor falso (.F.) significa que el elemento de menú
     correspondiente no va a estar disponible y un valor verdadero (.T.)
     significa que lo estará. Si se especifica los
     <lElementosSeleccionables> en vez de una matriz, falso (.F.) hace que
     los elementos de menú no estén disponibles y verdadero (.T.) hace que
     lo estén. Por defecto, todos los elementos de menú están disponibles
     para su selección.

     <cFunciónUsuario> es el nombre de una función que se ejecuta cuando
     se pulsa una tecla irreconocible. El nombre de función debe
     especificarse como una expresión de caracteres sin paréntesis ni
     argumentos. Recuerde que el comportamiento de ACHOICE() se ve afectado
     por la presencia de este argumento. Si desea más información, consulte
     el comentario siguiente.

     <nElementoInicial> es la posición en la matriz <acElementosMenú>
     del elemento que aparece resaltado al mostrarse el menú por primera
     vez. Si se especifica un elemento de menú no disponible o no se
     especifican argumentos, el elemento de menú inicial será el primer
     elemento seleccionable de la matriz.

     <nFilaVentana> es el número de fila de la ventana en la que aparece
     el elemento de menú inicial. La numeración de las filas comienza desde
     cero. Por defecto, el elemento de menú inicial aparece lo más cerca
     posible de la parte superior de la ventana, sin dejar filas vacías al
     final. Si existen suficientes elementos de menú a continuación del
     elemento inicial para llenar la ventana, el elemento inicial aparece en
     la primera fila (fila cero) del menú. Este argumento se utiliza para
     controlar el aspecto del menú inicial cuando hay más elementos de menú
     de los que caben en la ventana.

     Como ocurre con las demás funciones, los argumentos opcionales pueden
     omitirse utilizando una coma en vez del argumento real.

 Devuelve

     ACHOICE() devuelve la posición numérica en la matriz <acElementosMenú>
     del elemento de menú seleccionado. Si se aborta el proceso de
     selección, ACHOICE() devuelve cero.

 Descripción

     ACHOICE() es una función de interfaz de usuario que permite crear
     varios tipos de menús emergentes. Cada menú utiliza una matriz de
     cadenas de caracteres como elementos de menú y una matriz paralela de
     valores lógicos para determinar si los elementos deben ser
     seleccionables o no. Cuando se invoca ACHOICE(), la lista de elementos
     de menú aparece dentro de las coordenadas de ventana especificadas. Si
     el usuario pulsa Intro, se selecciona el elemento actual y ACHOICE()
     devuelve la posición del elemento de menú en <acElementosMenú>. Si el
     usuario pulsa Esc, ACHOICE() se aborta y devuelve cero.

     Los elementos de menú pueden desplazarse si el número de elementos de
     <acElementosMenú> excede el número de filas de la ventana de menú y el
     usuario intenta desplazar la zona resaltada más allá del principio o
     del final de la ventana. Recuerde que la zona resaltada no salta de
     línea cuando se llega al principio o al final de la lista de elementos.
     No obstante, la zona resaltada puede saltar de línea si se pulsa la
     primera letra de un elemento del grupo cuya primera letra coincida con
     la tecla pulsada.

     ■ Desplazamiento por el menú: ACHOICE() posee dos modos,
        dependiendo de si se especifica el argumento <cFunciónUsuario>. Si
        no se especifica, se activan las siguientes teclas de
        desplazamiento:

        Teclas de ACHOICE() (sin función de usuario)
        ---------------------------------------------------------------------
        Tecla                 Acción
        ---------------------------------------------------------------------
        Arriba                Va al elemento anterior
        Abajo                 Va al elemento siguiente
        Inicio                Va al primer elemento del menú
        Fin                   Va al último elemento del menú
        Ctrl-Inicio           Va al primer elemento de la ventana
        Ctrl-Fin              Va al último elemento de la ventana
        RePág                 Va a la página anterior
        AvPág                 Va a la página siguiente
        Ctrl-RePág            Va al primer elemento del menú
        Ctrl-AvPág            Va al último elemento del menú
        Intro                 Selecciona el elemento actual
        Esc                   Anula la selección
        Izquierda             Anula la selección
        Derecha               Anula la selección
        Primera Letra         Va al elemento siguiente que comience
                              con esa letra
        ---------------------------------------------------------------------

     ■ Color: Los elementos de menú aparecen en el color estándar, la
        zona resaltada en el color resaltado y los elementos no disponibles
        en el color no seleccionado. Por ejemplo, la siguiente sentencia de
        color:

        SETCOLOR("W+/N, BG+/B, , , W/N")

        muestra un menú blanco brillante sobre negro, la zona resaltada en
        cian brillante sobre azul y los elementos de menú no disponibles en
        blanco atenuado sobre negro.

     ■ Función de Usuario: Al igual que las restantes funciones de
        interfaz de usuario, ACHOICE() permite utilizar una función definida
        por el usuario. Esta función se especifica cuando se desean anidar
        invocaciones a ACHOICE() para crear menús jerárquicos o redefinir
        teclas.

        Si se especifica una función de usuario, ACHOICE() sólo procesa
        automáticamente un grupo de teclas reducido que se lista en la tabla
        siguiente. Todas las demás teclas generan una excepción de teclado
        que pasa el control a la función de usuario para su tratamiento. El
        control pasa también a la función de usuario cuando ACHOICE() queda
        inactiva (es decir, cuando no quedan teclas para procesar).

        Teclas de ACHOICE() (Función de Usuario Especificada)
        ---------------------------------------------------------------------
        Tecla                 Acción
        ---------------------------------------------------------------------
        Arriba                Va al elemento anterior
        Abajo                 Va al elemento siguiente
        Ctrl-Inicio           Va al primer elemento de la ventana
        Ctrl-Fin              Va al último elemento de la ventana
        RePág                 Va a la página anterior
        AvPág                 Va a la página siguiente
        Ctrl-RePág            Va al primer elemento del menú
        Ctrl-AvPág            Va al último elemento del menú
        ---------------------------------------------------------------------

        Cuando ACHOICE() ejecuta la función de usuario, le pasa
        automáticamente estos tres parámetros:

        - Modo actual de ACHOICE()

        - Elemento actual de la matriz de elementos

        - Posición de fila relativa en la ventana de menú

        El modo indica el estado actual de ACHOICE(), que depende de la
        tecla pulsada y de la acción que realiza ACHOICE() antes de ejecutar
        la función de usuario. El parámetro de modo puede tener los valores
        que se indican a continuación:

        Modos de ACHOICE() 
        ---------------------------------------------------------------------
        Modo       Achoice.ch     Descripción
        ---------------------------------------------------------------------
        0          AC_IDLE        Inactivo
        1          AC_HITTOP      Intento de desplazar el cursor por
                                  encima del principio de la lista
        2          AC_HITBOTTOM   Intento de desplazar el cursor por
                                  debajo del final de la lista
        3          AC_EXCEPT      Excepciones del teclado
        4          AC_NOITEM      No quedan elementos seleccionables
        ---------------------------------------------------------------------

        Una vez que la función de usuario completa las acciones
        correspondientes al modo de ACHOICE() o de LASTKEY(), debe devolver
        un valor para solicitar a ACHOICE() que realice una de las
        operaciones siguientes:

        Valores de Retorno de la Función de Usuario de ACHOICE()
        ---------------------------------------------------------------------
        Valor      Achoice.ch    Acción
        ---------------------------------------------------------------------
        0          AC_ABORT      Anular la selección
        1          AC_SELECT     Confirmar la selección
        2          AC_CONT       Continuar ACHOICE()
        3          AC_GOTO       Ir al próximo elemento cuyo primer
                                 carácter coincida con la tecla pulsada
        ---------------------------------------------------------------------

 Ejemplos

      El ejemplo siguiente utiliza dos matrices literales que
        especifican los elementos de menú y los criterios de selección.
        Cuando el menú aparece en pantalla y el usuario ha realizado la
        selección, se muestra el nombre del elemento de menú seleccionado:

        acElementosMenu := {"Uno", "Dos", "-------", "Tres"}
        alElementosSeleccionables := {.T., .T., .F., .T.}
        nPosicion := ACHOICE(10, 10, 12, 15, acElementosMenu,;
                                 alElementosSeleccionables)
        ? acElementosMenu [nPosicion]

      El ejemplo siguiente declara una matriz de elementos de menú y
        utiliza una función de usuario que muestra un mensaje con cada
        opción resaltada:

        #include "achoice.ch"
        #include "inkey.ch"

        PROCEDURE Main()

           LOCAL acElementosMenu [4], cFuncionUsuario, nValDev
           LOCAL nTecla, nPos

           acElementosMenu[1] := "Añadir"
           acElementosMenu[2] := "Editar"
           acElementosMenu[3] := "Borrar"
           acElementosMenu[4] := "Actualizar"

           CLS

           nPos := ACHOICE( 10, 10, 13, 15, acElementosMenu,;
                          .T., "cFuncionUsuario" )
           DO CASE
           CASE nPos == 1
           // Poner aquí la rutina que añade
           CASE nPos == 2
              // Poner aquí la rutina que edita
           CASE nPos == 3
              // Poner aquí la rutina que borra
           CASE nPos ==4
              // Poner aquí la rutina que actualiza
           ENDCASE

        RETURN


        FUNCTION cFuncionUsuario (nModo, nElementoAct, nPosFila)

           LOCAL nValDev := AC_CONT     // Por defecto,continuar
           LOCAL nTecla := LASTKEY()

           DO CASE
        // Después de procesar todas las teclas
        // pendientes, se visualiza el mensaje
           CASE nModo == AC_IDLE
           DO CASE
              CASE nElementoAct == 1
                  @ 22, 5 SAY " Añadiendo   "
              CASE nElementoAct == 2
                  @ 22, 5 SAY " Editando   "
              CASE nElementoAct == 3
                  @ 22, 5 SAY " Borrando   "
              CASE nElementoAct == 4
                  @ 22, 5 SAY " Actualizando   "
           ENDCASE

              nValDev := AC_CONT                // Continuar ACHOICE()

           CASE nModo == AC_HITTOP              // Intento de ir antes
                                                // del principio
              TONE( 100, 3 )
           CASE nModo == AC_HITBOTTOM           // Intento de ir
                                                // por debajo del final
              TONE( 100, 3 )

           CASE nModo == AC_EXCEPT              // Excepción de teclado
              DO CASE
              CASE nTecla == K_RETURN           // Si se pulsa la
                                                // tecla INTRO,
                                                // confirmar selección
                  nValDev := AC_SELECT
              CASE nTecla == K_ESC              // Si se pulsa la tecla
                                                // ESC, anular selección
                  nValDev := AC_ABORT
              OTHERWISE
                      nValDev := AC_GOTO        // En caso
                                                // contrario, ir al
                                                // elemento
              ENDCASE
           ENDCASE

        RETURN nValDev

      El ejemplo siguiente declara las matrices, especifica una
        condición de selección para uno de los elementos de menú y utiliza
        una función de usuario:

        EXTERNAL UPDATED
        //
        FUNCTION MiMenu
           LOCAL acElementosMenu[4], alElementosSeleccionables[4],;
                  cFuncionUsuario := "Hacerlo"
           //
           acElementosMenu[1] := "Añadir Registro"
           acElementosMenu[2] := "Editar Registro"
           acElementosMenu[3] := "Borrar Registro"
           acElementosMenu[4] := "Actualizar Registro"
           //
           alElementosSeleccionables[1] := .T.
           alElementosSeleccionables[2] := .T.
           alElementosSeleccionables[3] := .T.
           alElementosSeleccionables[4] := "!UPDATED()"
           // Condición de Selección

           RETURN ACHOICE(10, 10, 12, 15, acElementosMenu,;
              alElementosSeleccionables, cFuncionUsuario)

      El ejemplo siguiente utiliza dos matrices que especifican los
        elementos de menú y los bloques de acción correspondientes. Cuando
        el menú aparece en pantalla y el usuario realiza una selección, se
        utiliza el valor de retorno de ACHOICE() para determinar qué bloque
        de acciones de aElementosAccion debe evaluarse:

        PROCEDURE Main()
           LOCAL nSeleccion
           LOCAL aElementosMenu := { "Añadir Registro ", ;
                                     "Editar Registro ", ;
                                     "Borrar Registro", ;
                                     "Actualizar Registro"  }

           LOCAL aElementosAccion := { {|| AnadFunc() }, ;
                                       {|| EditFunc() }, ;
                                       {|| BorrFunc() }, ;
                                       {|| ActuFunc() } }

           nSeleccion := ACHOICE( 10, 10, 13, 22, aElementosMenu )

           IF nSeleccion == 0
              QUIT        // Se ha pulsado ESC
           ENDIF

           EVAL( aElementosAccion [nSeleccion] )

        RETURN

 Ficheros   La biblioteca asociada es EXTEND.LIB,
            los ficheros de cabecera asociados son Achoice.ch e Inkey.ch.

 To download this example - click here.

See Also: MENU TO SET COLOR*