menus en turbo c++

Iniciado por sowher, 30 Abril 2005, 04:58 AM

0 Miembros y 1 Visitante están viendo este tema.

sowher

Hola me gustaria saber como se pude crear menus en modo texto, asi como la misma interface q el turbo c++...

Gracias

Diabliyo

#1
Hola:

Pues no entiendo bien del todo, pero creo que a esto te refieres.

C
#include <stdio.h>
#include <stdlib.h>

int main()
         {
         char _op='a';

         while( _op!='5' )
                  {
                  system( "clear" );
                  printf( "1. Menu 1" );
                  printf( "\n2. Menus 2" );
                  printf( "\n3. Menu 3" );
                  printf( "\n4. Menu 4" );
                  printf( "\n5. Salir" );
                  _op= getchar();
                  switch( _op )
                           {
                           case '1':
                                    break;
                           case '2':
                                    break;
                           case '3':
                                    break;
                           case '4':
                                    break;
                           }
                  }
         printf( "\n\nPulsa para salir.." );
         getchar();
         return 0;
         }


C++
#include <iostream.h>
#include <stdlib.h>

int main()
         {
         char _op='a';

         while( _op!='5' )
                  {
                  system( "clear" );
                  cout<< "1. Menu 1";
                  cout<< "\n2. Menus 2";
                  cout<< "\n3. Menu 3";
                  cout<< "\n4. Menu 4";
                  cout<< "\n5. Salir";
                  _op= cin.get();
                  switch( _op )
                           {
                           case '1':
                                    break;
                           case '2':
                                    break;
                           case '3':
                                    break;
                           case '4':
                                    break;
                           }
                  }
         cout<< "\n\nPulsa para salir..";
         cin.get();
         return 0;
         }

sowher

Gracias men por la ayudita, pero ese codigo ya lo se lo q quiero es menus deplegables como la misma interface de trubo c++ gracias saludos

Blue_box

Podrias poner el menu, y pedir la opcion ha seleccionar y despues imprimir nuevamente el menu con el submenu.



int menu(int modo)
{
int opcion;

system( "clear" );
cout<< "1. Menu 1";
cout<< "\n2. Menus 2";
cout<< "\n3. Menu 3";
cout<< "\n4. Menu 4";
cout<< "\n5. Salir";

if(modo)
{
   cin>>opcion;
   return(0);
}
else
  return(0);
}

void subMenu1(void)
{
.......
}

main()
{
......

int opcion;

do
{
  switch((opcion=menu(1)))
  {
    case 1: menu(0);
               subMenu1();
  }

}while();
}
El verdadero conocimiento no es bueno o malo sino una combinación de ambos.
Deja de ver lo que te han puesto frente a ti y mejor ve lo que realmente es.

sowher

hola lo q me dices esta genial pero eso no es mi espectativa lo q quiero es un menu desplegable como el mismo de trubo c++, gracias de todas maneras...

Juan_Perez

Si quieres lograr el mismo efecto que los menus de Turbo C++ de borland necesitas manejar punteros directos a la memoria de video. En los antiguas máquinas, antes de Windows 95, podías acceder directamente a la memoria de video. En las de ahora, con Windows 98, ME, 2000 y XP no lo puedes hacer, pero estos SO's hacen una simulación de DOS, el antiguo sistema operativo que usaban esas máquinas; de modo que cuando corres en modo consola un programa que hace uso directamente de la memoria de video, éste corre transparentemente sin que te des cuenta de la simulación, por lo que para ti es como si la estuvieras direccionando realmente. Te paso el código de un programa de demostración de menus que saqué del libro C: Guía para usuarios expertos del autor Herbert Schildt y editorial McGraw Hill/Interamericana de España del año 1989 El código lo modifiqué ligeramente para ponerle colores y sombras y para usar la función cls (), ya que en el código original el autor usaba una interrupción de DOS (otra cosa que no puedes usar pero que simula Windows), pero al correr el programa en modo consola con Windows XP, la función nada hacía. El código me compiló sin problemas con el Turbo C v2.01, en el modelo Large. El programa no maneja el ratón, pero es fácil manejarlo en modo consola, con las funciones que para el manejo de éste proporciona Windows. Si te interesa por ahí tengo un pequeño programa de demostración del uso del ratón.

/*
   Programa ejemplo que utiliza las rutinas de un menu encadenado
   en el modo texto
*/

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <dos.h>

#define BORDE        1
#define ESC         27
#define MAX_MENU    10
#define VID_INV   0x70
#define INT_VID   0x0F
#define NORM_VID     7
#define COLOR_LETRA        0x09
#define COLOR_PRIMLETRA    0x04

void pd_driver (void);
void inicializaVideo (void);
int menu_encadenado (int num);
int crea_menu (int num, char *menu[], char *teclas, int contador,
                                    int x, int y, int borde, int colorfondo);
void visualiza_menu (int num);
void pon_sombra (int num);
void dibuja_borde (int num);
int obtiene_resp (int num);
void escribe_cadena (int x, int y, char *p, int atrib);
void escribe_char (int x, int y, char ch, int atrib);
void guarda_video (int num);
void restaura_video (int num);
void cls (void);
void vete_xy (int x, int y);
int modo_video (void);
int esta_en (char *s, char c);

char far *mem_vid;

struct estructura_menu {
   int comienzax, finx, comienzay, finy;
   unsigned char *p;
   char **menu;
   char *teclas;
   int borde, contador;
   int activo, colorfondo;
} estructura[MAX_MENU];

char *fruta[] = {
   "Manzana... ",
   "Naranja    ",
   "Albaricoque",
   "Fresa...   ",
   "Pera       ",
   "Uva        "
};

char *color[] = {
   "Roja... ",
   "Amarilla",
   "Naranja ",
   "Verde   "
};

char *tipo_manzana[] = {
   "Rojo delicias",
   "Gallega      ",
   "Asturiana    ",
   "Jonatan      "
};

char *tipo_fresa[] = {
   "Salvaje   ",
   "Huelva    ",
   "Freson    ",
   "Rojo fuego"
};

void main (void)
{

   int i;

   inicializaVideo ();
   cls ();
   for (i = 0; i < 80; i++) {
      escribe_char (1, i, ' ', NORM_VID);
      escribe_char (24, i, ' ', NORM_VID);
   }
   escribe_cadena (1, 1, "Seleccione su fruta:", COLOR_LETRA);

   /* crea primero las estructuras de los menus */
   crea_menu (0, fruta, "mnafpu", 6, 5, 20, BORDE, 0x10);
   crea_menu (1, color, "ranv", 4, 9, 28, BORDE, 0x70);
   crea_menu (2, tipo_manzana, "rjwr", 4, 12, 32, BORDE, 0x50);
   crea_menu (3, tipo_fresa, "ahfr", 4, 9, 10, BORDE, 0x80);

   pd_driver (); /* activa el sistema de menus */

}

void pd_driver (void)
{
   int eleccion1, eleccion2, seleccion;

   /* se activa si se necesita */
   while ((eleccion1 = menu_encadenado (0)) != -1) {
      switch (eleccion1) {
         case 0: /* quiere una manzana */
            eleccion2 = menu_encadenado (1);
            if (eleccion2 != -1)
               if (eleccion2 != 0) {
                  char str[80] = "                                         ";
                  escribe_cadena (1, 22, str, NORM_VID);
                  strcpy (str, estructura[0].menu[0]);
                  sprintf (str + strlen (str) - 4, " %s", estructura[1].menu[eleccion2]);
                  escribe_cadena (1, 22, str, NORM_VID);
               } else {
                  seleccion = menu_encadenado (2); /* manzana roja */
                  if (seleccion != -1) {
                     char str[80] = "                                      ";
                     escribe_cadena (1, 22, str, NORM_VID);
                     strcpy (str, estructura[0].menu[0]);
                     sprintf (str + strlen (str) - 4, " %s", estructura[1].menu[0]);
                     sprintf (str + strlen (str) - 4, " %s", estructura[2].menu[seleccion]);
                     escribe_cadena (1, 22, str, NORM_VID);
                  }
                  restaura_video (2);
               }
            restaura_video (1);
            break;
         case 3: /* quiere una fresa */
            seleccion = menu_encadenado (3);
            if (seleccion != -1) {
                  char str[80] = "                                         ";
                  escribe_cadena (1, 22, str, NORM_VID);
                  strcpy (str, estructura[0].menu[3]);
                  sprintf (str + strlen (str) - 6, " %s", estructura[3].menu[seleccion]);
                  escribe_cadena (1, 22, str, NORM_VID);
            }
            restaura_video (3);
            break;
         default:
            escribe_cadena (1, 22, "                             ", NORM_VID);
            escribe_cadena (1, 22, estructura[0].menu[eleccion1], NORM_VID);
            break;
      }
   }
   restaura_video (0);
}

/* inicializa la variable que apunta a la memoria de video */
void inicializaVideo (void)
{
   int modov;

   modov = modo_video ();
   if (modov != 2 && modov != 3 && modov && 7) {
      printf ("Video en modo texto de 80 columnas");
      exit (1);
   }

   /* inicializa la dirección de la memoria RAM de video */
   if (modov == 7) mem_vid = (char far *)0xB0000000;
   else mem_vid = (char far *)0xB8000000;
}

/* visualiza un menu encadenado y devuelve la selección */
/* num   - número del menu */
int menu_encadenado (int num)
{
   int eleccion;

   /* obtiene la ventana activa */
   if (!estructura[num].activo) { /* no está en uso */
      guarda_video (num); /* guarda la pantalla actual */
      estructura[num].activo = 1; /* activa el flag */
   }

   if (estructura[num].borde) dibuja_borde (num);

   visualiza_menu (num); /* visualiza el menu menu */
   pon_sombra (num); /* pone una sombra a la derecha y abajo */
   return obtiene_resp (num); /* devuelve la respuesta */
}

/*
   Construye la estructura de un menu encadenado.
   un 1 se regresa si puede ser encadenada la estructura del menu
   de lo contrario se devuelve un 0
   int menu           - número del menu
   char *menu[]       - texto del menu
   char *teclas       - teclas clave
   int contador       - número de ítems del menu
   int x, y           - coordenadas X, Y de la esquina superior izquiera
   int borde          - sin borde si es 0
*/
int crea_menu (int num, char *menu[], char *teclas, int contador,
                                     int x, int y, int borde, int colorfondo)
{
   register int i, len;
   int finx, finy, eleccion, modov;
   unsigned char *p;

   if (num > MAX_MENU) {
      printf ("Demasiados menus\n");
      return 0;
   }

   if (x > 24 || x < 0 || y > 79 || y < 0) {
      printf ("Error de rango\n");
      return 0;
   }

   /* calcula el tamaño */
   len = 0;
   for (i = 0; i < contador; i++)
      if (strlen (menu[i]) > len) len = strlen (menu[i]);
   finy = len + 3 + y;
   finx = contador + 1 + x;
   if ((finx + 1 > 24) || (finy + 1 > 179)) {
      printf ("No cabe el menu\n");
      return 0;
   }

   /* asignar suficiente memoria para almacenarlo */
   p = (unsigned char *)malloc (2 * (finx - x + 2) * (finy - y + 2));
   if (!p) exit (1); /* ponga aqu¡ su propio manejador de errores */

   /* construye la estructura */
   estructura[num].comienzax = x; estructura[num].finx = finx;
   estructura[num].comienzay = y; estructura[num].finy = finy;
   estructura[num].p = p;
   estructura[num].menu = (char **)menu;
   estructura[num].borde = borde;
   estructura[num].teclas = teclas;
   estructura[num].contador = contador;
   estructura[num].activo = 0;
   estructura[num].colorfondo = colorfondo;
   return 1;
}

/* visualiza el menu en su posición */
void visualiza_menu (int num)
{
   register int i, x;
   char **m;

   x = estructura[num].comienzax + 1;
   m = estructura[num].menu;

   for (i = 0; i < estructura[num].contador; i++, x++) {
      escribe_cadena (x, estructura[num].comienzay + 2, m[i],
                                   COLOR_LETRA | estructura[num].colorfondo);
      escribe_char (x, estructura[num].comienzay + 2, m[i][0],
                               COLOR_PRIMLETRA | estructura[num].colorfondo);
   }
}

void pon_sombra (int num)
{
   register int i;
   char far *v;

   v = mem_vid + (estructura[num].comienzax * 160) + (estructura[num].finy + 1) * 2 + 1;
   for (i = estructura[num].comienzax+1; i <= estructura[num].finx+1; i++) {
      v += 160;
      *v = NORM_VID;
   }
   v = mem_vid + ((estructura[num].finx + 1) * 160) + estructura[num].comienzay*2 + 1;
   for (i = estructura[num].comienzay+1; i <= estructura[num].finy+1; i++) {
      v += 2;
      *v = NORM_VID;
   }
}

void dibuja_borde (int num)
{
   register int i;
   char far *v, far *t;

   v = mem_vid;
   t = v;
   for (i = estructura[num].comienzax + 1; i < estructura[num].finx; i++) {
      v += (i * 160) + estructura[num].comienzay * 2;
      *v++ = 179;
      *v = estructura[num].colorfondo;
      v = t;
      v += (i * 160) + estructura[num].finy * 2;
      *v++ = 179;
      *v = estructura[num].colorfondo;
      v = t;
   }
   for (i = estructura[num].comienzay + 1; i < estructura[num].finy; i++) {
      v += estructura[num].comienzax * 160 + i*2;
      *v++ = 196;
      *v = estructura[num].colorfondo;
      v = t;
      v += (estructura[num].finx * 160) + i*2;
      *v++ = 196;
      *v = estructura[num].colorfondo;
      v = t;
   }
   escribe_char (estructura[num].comienzax, estructura[num].comienzay, 218, estructura[num].colorfondo);
   escribe_char (estructura[num].comienzax, estructura[num].finy, 191, estructura[num].colorfondo);
   escribe_char (estructura[num].finx, estructura[num].comienzay, 192, estructura[num].colorfondo);
   escribe_char (estructura[num].finx, estructura[num].finy, 217, estructura[num].colorfondo);
}

/* obtiene la selección del usuario */
int obtiene_resp (int num)
{
   union inkey {
      char ch[2];
      int i;
   } c;
   int flecha = 0, oldflecha = 0, tecla_elegida;
   int x, y;

   x = estructura[num].comienzax + 1;
   y = estructura[num].comienzay + 2;

   /* sobre-ilumina la primera selección */
   vete_xy (x, y);
   escribe_cadena (x, y, estructura[num].menu[0], INT_VID);
   escribe_char (x, y-1, ' ', INT_VID);
   escribe_char (x, estructura[num].finy-1, ' ', INT_VID);

   for (;;) {
      while (!bioskey (1)); /* espera hasta pulse tecla */
      c.i = bioskey (0);    /* lee la tecla */

      if (c.ch[0]) { /* es una tecla normal */
         /* ve si es una tecla clave */
         tecla_elegida = esta_en (estructura[num].teclas, tolower (c.ch[0]));
         if (tecla_elegida) return tecla_elegida - 1;
         /* comprueba ENTER o un espacio */
         if (c.ch[0] == ' ')
            flecha++;
         else if (c.ch[0] == '\r' || c.ch[0] == ESC) {
            escribe_char (x + flecha, y-1, ' ', estructura[num].colorfondo);
            escribe_char (x + flecha, estructura[num].finy-1, ' ', estructura[num].colorfondo);
            return (c.ch[0] == '\r') ? flecha : -1;
         }
      } else { /* es una tecla especial */
         switch (c.ch[1]) {
            case 72: flecha--; /* flecha arriba */
               break;
            case 80: flecha++; /* flecha abajo */
               break;
         }
      }
      if (flecha == oldflecha)
         continue;
      /* inicializa el modo normal de video */
      escribe_cadena (x + oldflecha, y, estructura[num].menu[oldflecha], estructura[num].colorfondo | COLOR_LETRA);
      escribe_char (x + oldflecha, y, estructura[num].menu[oldflecha][0], estructura[num].colorfondo | COLOR_PRIMLETRA);
      escribe_char (x + oldflecha, y-1, ' ', estructura[num].colorfondo);
      escribe_char (x + oldflecha, estructura[num].finy-1, ' ', estructura[num].colorfondo);

      if (flecha == estructura[num].contador) flecha = 0;
      if (flecha < 0) flecha = estructura[num].contador - 1;
      oldflecha = flecha;

      /* sobre-ilumina la proxima selección */
      vete_xy (x + flecha, y);
      escribe_cadena (x + flecha, y, estructura[num].menu[flecha], INT_VID);
      escribe_char (x + flecha, y-1, ' ', INT_VID);
      escribe_char (x + flecha, estructura[num].finy-1, ' ', INT_VID);
   }
}

/* visualiza una cadena con atributo especificado */
void escribe_cadena (int x, int y, char *p, int atrib)
{
   register int i;
   char far *v;

   v = mem_vid;
   v += (x * 160) + y*2; /* calcula la direcci¢n */
   for (i = y; *p; i++) {
      *v++ = *p++; /* escribe el caracter */
      *v++ = atrib; /* escribe el atributo */
   }
}

/* Escribe caracter con atributo especificado */
void escribe_char (int x, int y, char ch, int atrib)
{
   register int i;
   char far *v;

   v = mem_vid;
   v += (x * 160) + y*2; /* calcula la dirección */
   *v++ = ch; /* escribe el caracter */
   *v   = atrib; /* escribe el atributo */
}

/* guarda una porción de la pantalla */
void guarda_video (int num)
{
   register int i, j;
   char far *v, far *t;
   char *ptr_buf;

   ptr_buf = estructura[num].p;
   v = mem_vid;
   for (i = estructura[num].comienzay; i <= estructura[num].finy+1; i++)
      for (j = estructura[num].comienzax; j <= estructura[num].finx+1; j++) {
         t = (v + (j * 160) + i*2);
         *ptr_buf++ = *t++;
         *ptr_buf++ = *t;
         if (i != estructura[num].finy+1 && j != estructura[num].finx+1) {
            *(t-1) = ' '; /* limpia la ventana */
            *t = estructura[num].colorfondo;
         }
      }
   estructura[num].activo = 0; /* desactiva */
}

/* restaura una porción de la pantalla */
void restaura_video (int num)
{
   register int i, j;
   char far *v, far *t;
   char *ptr_buf;

   ptr_buf = estructura[num].p;
   v = mem_vid;
   t = v;
   for (i = estructura[num].comienzay; i <= estructura[num].finy+1; i++)
      for (j = estructura[num].comienzax; j <= estructura[num].finx+1; j++) {
         v = t;
         v += (j * 160) + i*2; /* calcula la direcci¢n */
         *v++ = *ptr_buf++;    /* escribe el caracter */
         *v = *ptr_buf++;      /* escribe el atributo */
      }
   estructura[num].activo = 0; /* desactiva */
}

/* limpia la pantalla */
void cls (void)
{
   int i, j;

   for (i = 0; i < 25; i++)
      for (j = 0; j < 80; j++)
escribe_char (i, j, 0xB1, 0x0F);
}

/* enviar el cursor a x, y */
void vete_xy (int x, int y)
{
   union REGS r;

   r.h.ah = 2; /* función de direccionamiento del cursor */
   r.h.dl = y; /* coordenadas de la columna */
   r.h.dh = x; /* coordenadas de la fila */
   r.h.bh = 0; /* página de video */
   int86 (0x10, &r, &r);
}

/* devuelve el modo actual de video */
int modo_video (void)
{
   union REGS r;

   r.h.ah = 15; /* obtiene el modo de video */
   return int86 (0x10, &r, &r) & 255;
}

int esta_en (char *s, char c)
{
   register int i;

   for (i = 0; *s; i++)
      if (*s++ == c)
return i + 1;
   return 0;
}

sowher

Gracias Juan_Perez el codigo se asemeja a lo q queria... no creo q sea nunguna molestia si me pasaras el codigo del mouse...

Gracias

ABSO5777

muy bueno Juan_Perez  me puede servir solo te faltaron las cabeseras

#include <string.h>
#include <bios.h>
;D

sowher

me parece q eso de las cabeceras es algo insignificante, pero el codigo esta buenazo ya lo he revisado y te felicito Juan_Perez.....suerte


Gracias

Juan_Perez

Gracias por sus felicitaciones pero el mérito es del autor del libro Herbert Schildt, que fue el que escribió el código del programa, yo solamente lo modifiqué un poco. ABSO5777 tiene razón cuando dice que me faltaron esas cabeceras, lo que pasa es que el compilador de Turbo C v2.01 en donde compilé el programa no se queja cuando uno usa funciones como strcpy o int86 y otras que necesitan los encabezados mencionados y compila sin errores y genera el ejecutable del programa. Sowher, con respecto al código que maneja el ratón aquí te lo paso, sólo que me estoy fijando que éste hace uso de las funciones de consola las cuales vienen en la librería que proporciona el compilador de Microsoft Visual C++ y no sé qué tanto te podrían servir si estás programando en Turbo C++. Este programa viene en el libro Schildt's Windows 95 Programming in C and C++ del mismo autor Herbert Schildt, y fue impreso en el año 1995 por la editorial Osborne McGraw-Hill (ahora si está tal como viene en el libro, no lo modifiqué excepto por los comentarios y letreros que venían en inglés). Lo compilé sin problemas con el Visual C++ v6. De hecho, con las funciones que proporciona la consola no es necesario el truco de direccionar directamente a la memoria de video ni de usar interrupciones (como en int86), pues aquí hay funciones para escribir cadenas con su color y atributos y lo hace igual de rápido como en las funciones que se usaron en el código anterior que te pasé.

/* Manejando el ratón desde la consola */
/*
#include <windows.h>
#include <string.h>
#include <stdio.h>

main ()
{
HANDLE hStdin, hStdout;
char str[80] = "Presione una tecla para terminar.";
DWORD result;
COORD coord;
int x = 0, y = 0;
INPUT_RECORD inBuf;

/* Libera la vieja consola y comienza con una nueva * /
FreeConsole ();
AllocConsole ();

/* Le pone a la ventana de consola un título * /
SetConsoleTitle ("Demostración de ratón con la consola");

/* Obtiene los manejadores estándar * /
hStdin  = GetStdHandle (STD_INPUT_HANDLE);
hStdout = GetStdHandle (STD_OUTPUT_HANDLE);

WriteConsole (hStdout, str, strlen (str), &result, NULL);

/* muestra los eventos del ratón hasta que se presiona una tecla * /
do {
ReadConsoleInput (hStdin, &inBuf, 1, &result);
/* Reporta si ocurre un evento del ratón * /
if (inBuf.EventType == MOUSE_EVENT) {
sprintf (str, "Estado del botón: %lu, X, Y: %3lu, %3lu\n",
inBuf.Event.MouseEvent.dwButtonState,
inBuf.Event.MouseEvent.dwMousePosition.X,
inBuf.Event.MouseEvent.dwMousePosition.Y);
coord.X = 0;
coord.Y = 1;
SetConsoleCursorPosition (hStdout, coord);
WriteConsole (hStdout, str, strlen (str), &result, NULL);

/* Reporta si se dio un doble click * /
if (inBuf.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK) {
sprintf (str, "Doble click\a");
coord.X = inBuf.Event.MouseEvent.dwMousePosition.X;
coord.Y = inBuf.Event.MouseEvent.dwMousePosition.Y;
SetConsoleCursorPosition (hStdout, coord);
WriteConsole (hStdout, str, strlen (str), &result, NULL);
Sleep (600); /* espera * /
SetConsoleCursorPosition (hStdout, coord);
strcpy (str, "               "); /* borra mensaje * /
WriteConsole (hStdout, str, strlen (str), &result, NULL);
}
}
} while (inBuf.EventType != KEY_EVENT);

return 0;
}


Si estás interesado te puedo pasar las funciones de consola necesarias para que modifiques el código de menu.