''

Menues de Crecimiento Vertical y Horizontal

Por Francisco San Pablo

 

Una de las conclusiones a las que llegan los programadores al cabo de los años es que las únicas aplicaciones rentables son las que son estándares y lo suficientemente genéricas como para servir para un gran número de empresas o clientes. Con mucha frecuencia llegan al programador propuestas de programas específicos para empresas o negocios que siguen los criterios del capricho del gerente o de un negocio lo suficientemente extraño como para ser único en un país. En esos casos el programador sabe que una vez hecha esa aplicación ya no podrá sacarle ningún partido. Ante esa situación, el programador suele poner unos precios elevados que compensen los esfuerzos realizados.

Pero, a pesar de lo anterior y por muy bien pagada que esté la aplicación los años demuestran que no son rentables para el programador por eso muchos programadores tienden a hacer programas estándares que van completando con las peticiones de los clientes siempre que se adapten a las filosofía general del programa. De esta forma el programa crece, madura, se rueda por varios clientes y empresas y llega a ser un programa ‘maduro y libre de fallos’. Pero, la vida no es siempre tan hermosa, al programador que sigue ese criterio, muchas veces le vienen clientes que ven el programa y lo encuentran satisfactorio en un 95% para sus necesidades y solicitan que se le incorporen una serie de modificaciones que haga que se adapte a su negocio. Pero, esas necesidades muchas veces chocan directamente con los principios que han marcado la aplicación de sencillez, generalidad, claridad, etc...

¿Qué hacer en esos casos?¿Desechar al cliente y por tanto una buena fuente de ingresos?¿Modificar un programa que muchas veces ha costado años de hacer y está ya libre de fallos?

La solución que propongo es hacer un módulo en el que quepan todas las opciones que el cliente ha pedido.

Pero, por favor, continúa leyendo, antes de criticar mi propuesta pues todavía no he acabado de exponerla.

La aplicación seguiría siendo estándar y por tanto no nos encontraríamos con los muchos problemas que crean las actualizaciones de software cuando tienes que hacer actualizaciones a clientes distintos con partes distintas, etc.... La aplicación sigue siendo la misma, nada ha cambiado, por tanto tenemos sólo una aplicación que es la que entregamos a los clientes nuevos y viejos pero... a nuestra aplicación le hemos puesto un fichero *.INI en el que hay una sección que pone [MODULOS] y el nombre del módulo y de un fichero ejecutable.

El menú de nuestra aplicación leerá siempre ese fichero *.INI y si encuentra algo creará una nueva opción en el menú llamada módulos en el que se incorporará el módulo específico que quiere el cliente. De esta forma salvaguardamos la integridad de nuestra aplicación y al cliente lo dejamos contento.

¿Cómo se hace esto? Tu aplicación estándar debería seguir el siguiente criterios:

Rutinas de la aplicación

·  1.- Lanzamiento del menú estándar de la aplicación.

·  2.- Lanzamiento del programa que incorpora los módulos si existen.

El esquema sería el siguiente:

 
DO Mimemu.mpr
DO 
... resto del programa

Fichero .INI

Hay que crear un fichero con la extensión .INI que debería estar al lado de donde se encuentra el ejecutable. En nuestro caso lo hemos llamado: Tmp.INI

En ese fichero deberíamos escribir:

 
[MODULOS]
MOD1=Producción GM;gm.exe

Que nos haría que el literal que aparezca en el menú sea en este caso el texto. “Producción GM” y que al pulsarlo el usuario llamaría a una aplicación que se llama gm.exe

Lo más grande de este asunto es que esa aplicación podría estar escrita en cualquier lenguaje.

Si quieres hacer una prueba, basta con que escribas:

MOD2=Marcador de teléfono; DIALER.EXE

Que nos llamaría al DIALER de windows.

También podrías llamar a una aplicación pura en Fox (.app) aunque tendrías que hacer algún pequeño cambio en el programa que te adjunto.

Como ves las posibilidades son muchas:

El programa que habría que incorporar en tu aplicación sería el siguiente:

 
LOCAL  lcBuffer, lcEntry, lcSeccion, ;        lnCont, lcEntryX, lnCountPad,;   
        lPadModulos, llLineaSeparador,; 
        LnBarModulos
 
*-- Instrucciones DECLARE DLL para 
*-- leer/escribir en archivos INI privados
DECLARE INTEGER GetPrivateProfileString ;
        IN Win32API  AS GetPrivStr ;
        String cSection, String cKey,;
        String cDefault, String @cBuffer, ;
        Integer nBufferSize, String cINIFile
 
#DEFINE INIFILE  "tmp.INI"
            
lcSeccion = "MODULOS"
lcEntry   = "MOD"
lcBuffer  = SPACE(150) + CHR(0)
 
lnCont         = 1
lPadModulos    = .f.
 
llLineaSeparador = .f.
lnBarModulos   = 1
 
DO WHILE .T.
        lcEntryX = lcEntry + ;
        ALLTRIM(STR(lnCont))
        lcBuffer  = SPACE(150) + CHR(0)
        
        *- Comprueba que en el INI tenemos 
        *- puesta una línea similar a la 
        *- siguiente:
        *[MODULOS]
        * MOD1=Producción GM;gm.exe;;.t.
        IF GetPrivStr(lcSeccion, lcEntryX,;
               "", @lcBuffer,;
               LEN(lcBuffer), CURDIR();
               + INIFILE) <= 0
           EXIT
        ELSE
           *- Si no existe el pad módulos, lo crea
           IF NOT lPadModulos
               DEFINE PAD _PADMODULOS OF;
                       _MSYSMENU PROMPT ;
                       "\archivo.exe
                       
        LOCAL lcPrompt, lcFileExe, lcParam, ;
               lcExeFox, lnContBuffer, lcExp1, ;
               lcExpOnBar
                                      
        STORE "" TO lcPrompt, lcFileExe, lcExp1
        lnContBuffer = 1
        lcExeFox = '.F.'
               
        FOR lnContBuffer = 1 TO 2
               lnPosComa = AT(";", lcBuffer)
               IF lnPosComa = 0
                       EXIT
               ELSE
                       lcExp1 = ALLTRIM(SUBSTR(lcBuffer,;
                               1, lnPosComa-1))
                       DO CASE
                               CASE lnContBuffer = 1
                                      lcPrompt = lcExp1
                               CASE lnContBuffer = 2
                                      lcFileExe = lcExp1
                       ENDCASE
                       
                               
                       *- Resto de la expresi¢n, menos 
                       *- pcExpValor extraida
                       lcBuffer = ALLTRIM(SUBSTR(lcBuffer,;
                               lnPosComa+1, len(lcBuffer)))
               ENDIF
        ENDFOR
        
        IF llLineaSeparador
               DEFINE BAR lnBarModulos ;
                       OF _MODULOS PROMPT "\-" AFTER _MLAST
                       lnBarModulos = lnBarModulos + 1
        ENDIF
        DEFINE BAR lnBarModulos OF;
               _MODULOS PROMPT lcPrompt AFTER _MLAST
               lcExpOnBar = [ON SELECTION BAR ;
               lnBarModulos OF _MODULOS]
        lcExpOnBar = lcExpOnBar + [ RUN /N ]
        lcExpOnBar = lcExpOnBar + lcFileExe
        &lcExpOnBar
 
               
        *- OPCIONES DE BAR DE MÓDULOS
        lnBarModulos = lnBarModulos + 1
        llLineaSeparador = .T.
 
 ENDIF
        
lnCont = lnCont +  1
 
ENDDO
 
RETURN

En nuestro ejemplo lo hemos hecho para incorporar una opción llamada módulos y a continuación ir poniendo cada uno de los módulos.

De todos modos, no costaría mucho hacer una variante de este programa que te permitiera añadir el módulo en cualquiera de los otras pad de los menues de tu aplicación.

Cuando estés haciendo pruebas, acuérdate que para volver al menú del sistema de Fox deberás escribir en la ventana de órdenes:

 
SET SYSMENU TO DEFAULT

El programa que se adjunta lo puedes probar con el menú del sistema de Fox pues realiza las mismas operaciones. En el gráfico que se adjunta se ven como las pruebas se han estado haciendo con el menú del Fox.

Francisco San Pablo Flash Software, S.L


© 1999 FoxPress. All rights reserved.