Avatar billede danielhep Nybegynder
08. maj 2004 - 00:30 Der er 11 kommentarer og
1 løsning

Konvertere til Linux C++

/* Midgaard */
#include <windows.h>
#include <stdlib.h>

/* This is an key element, it contains elements needed to handle one menu or submen item */
/* Each item has a text (title) and a associated function OR submenu                    */
/* If both function AND submenu are NULL we will jump one level up                      */
/* So our menu structure will be build as a tree of these                                */
typedef struct menu_item
{
  const char *title;
  struct menu_item const *submenu;
  void(*function)(void);
}menu_item;

HANDLE Console;
HANDLE ConsoleIn;

#define NORM_ATTR (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
#define INVR_ATTR (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)
#define EMPTY_LINE "                                                                                "

void text_out(short attr, int x, int y, const char *text)
{
  DWORD Dummy;
  COORD Coord;
  SetConsoleTextAttribute(Console, NORM_ATTR);
  Coord.X = x + 5;
  Coord.Y = y + 5;
  SetConsoleCursorPosition(Console, Coord);
  WriteConsole(Console, EMPTY_LINE, strlen(EMPTY_LINE), &Dummy, 0);

  SetConsoleCursorPosition(Console, Coord);
  SetConsoleTextAttribute(Console, attr);
  WriteConsole(Console, text, strlen(text), &Dummy, 0);
}

void show_status(const char *msg)
{
  text_out(NORM_ATTR, 0, 12, msg);
}

int get_key(void)
{
  INPUT_RECORD Input;
  DWORD NumRead;
  do
  { /* Wait for key release */
    ReadConsoleInput(ConsoleIn, &Input, 1, &NumRead);
  }
  while(Input.EventType != KEY_EVENT && Input.Event.KeyEvent.bKeyDown);

  do
  { /* Read The Key */
    ReadConsoleInput(ConsoleIn, &Input, 1, &NumRead);
  }
  while(Input.EventType != KEY_EVENT && !Input.Event.KeyEvent.bKeyDown);
  return Input.Event.KeyEvent.wVirtualKeyCode;
}

#define DUMMY_FUNC(name) \
static void name(void)          \
{                        \
  show_status(#name);    \
}

DUMMY_FUNC(func_11)
DUMMY_FUNC(func_21)
DUMMY_FUNC(func_22)
DUMMY_FUNC(func_231)
DUMMY_FUNC(func_232)
DUMMY_FUNC(func_233)

void exit_func(void)
{
  SetConsoleTextAttribute(Console, NORM_ATTR);
  exit(0);
}

/* These are the menu's, will have to start from the buttom  */
menu_item const pb_list_menu[] =
{
  {"Ole",  NULL, func_231},
  {"Peter", NULL, func_232},
  {"Poul",  NULL, func_233},
  {"Back",  NULL, NULL},
  {NULL,    NULL, NULL}
};

menu_item const phonebook_menu[] =
{
  {"AddEntry", NULL, func_11},
  {"List",    pb_list_menu, NULL},
  {"Back",    NULL, NULL},
  {NULL,      NULL, NULL}
};

menu_item const sub_menu_2[] =
{
  {"New SMS", NULL, func_21},
  {"List",    NULL, func_22},
  {"Back",    NULL, NULL},
  {NULL,      NULL, NULL}
};

menu_item const main_menu[] =
{
  {"PhoneBook", phonebook_menu, NULL},
  {"SMS",      sub_menu_2,    NULL},
  {"Exit",      NULL,          exit_func},
  {NULL,        NULL,          NULL}
};

void exec(menu_item const * menu);

void clear_menu_window(void)
{
  int i;
  for(i = 0; i < 15; i++)
  {
    text_out(NORM_ATTR, 0, i, "");
  }
}

int main(void)
{
  int i;
  DWORD Dummy;
  COORD Coord;
  Console = GetStdHandle(STD_OUTPUT_HANDLE);
  ConsoleIn = GetStdHandle(STD_INPUT_HANDLE);
  SetConsoleMode(ConsoleIn, 0);

  SetConsoleTextAttribute(Console, NORM_ATTR);
  Coord.X = 1;
  Coord.Y = 1;
  SetConsoleCursorPosition(Console, Coord);

  for(i = 0; i < 80; i++)
    WriteConsole(Console, EMPTY_LINE, strlen(EMPTY_LINE), &Dummy, 0);

  text_out(NORM_ATTR, -4, -4, "Simple menu demo Press UP/Down, Enter to select");

  exec(main_menu);

  SetConsoleTextAttribute(Console, NORM_ATTR);
  return EXIT_SUCCESS;
}

/* This is the main menu executer, it will call itself to execute submenus */
void exec(menu_item const * menu)
{
  int ch;
  int i;
  int state = 0;
  clear_menu_window();
  do
  {
    /* I'm lazy so I'll update the complete menu each time */
    for(i = 0; menu[i].title; i++)
    {
      if(i == state)
        text_out(INVR_ATTR, 0, i, menu[i].title);
      else
        text_out(NORM_ATTR, 0, i, menu[i].title);
    }
    ch = get_key();
    switch(ch)
    {
      case VK_RETURN:  /* Enter */
        if(menu[state].function)
          menu[state].function();
        else if(menu[state].submenu)
        { /* It's a submenu */
          exec(menu[state].submenu);
          clear_menu_window();
        }
        else
        { /* It is a back menu item */
          return;
        }
        break;
      case VK_UP:
        if(state != 0)
          state--;
        break;
      case VK_DOWN:
        if(menu[state + 1].title)
          state++;
        break;
    }
  }
  while(1);
}


Hvis dette skulle konverteres til Linux, hvad for nogle
biblioteker, og bla bla...skal ændres ??

Koden kan også ses online her:
http://home20.inet.tele.dk/midgaard/snip/menu.html

Tak midgård, sej hjemmeside :)
Avatar billede bertelbrander Novice
08. maj 2004 - 00:37 #1
På linux ville man nok bruge ncurses. Det er lidt bøvlet, men jeg bør vist have et ncurses eksempel på min hjemmeside, så måske burde jeg lave det.
Avatar billede danielhep Nybegynder
08. maj 2004 - 00:46 #2
hvad skulle det eksemplen helt præcist hedde på din homesite ?
Avatar billede bertelbrander Novice
08. maj 2004 - 00:51 #3
Jeg har ikke et eksempel med curses på min hjemmeside, men jeg bør lave et.

Jeg vil lave menuen med ncurses, den bliver sansynligvis færdig i morgen aften.

Jeg har ikke linux, så jeg kan kun teste det men cygwin.
Avatar billede danielhep Nybegynder
08. maj 2004 - 00:57 #4
ok...jamen så venter jeg gerne... :) takker for det
Avatar billede bertelbrander Novice
08. maj 2004 - 01:57 #5
Jeg har lavet et første udkast, det ser ud til at virke med cygwin på PC. Måske er taste koderne for UP og DOWN anderledes på Linux.

#include <curses.h>
#include <stdlib.h>

enum VirtKeys
{
  VK_RETURN = 10,
  VK_UP = 65 | 0x100,
  VK_DOWN = 66 | 0x100
};


/* This is an key element, it contains elements needed to handle one menu or submen item */
/* Each item has a text (title) and a associated function OR submenu                    */
/* If both function AND submenu are NULL we will jump one level up                      */
/* So our menu structure will be build as a tree of these                                */
typedef struct menu_item
{
  const char *title;
  struct menu_item const *submenu;
  void(*function)(void);
}menu_item;

WINDOW *StatusWin;
WINDOW *MenuWin;

#define NORM_ATTR A_NORMAL
#define INVR_ATTR A_STANDOUT
#define EMPTY_LINE "                                                                                "

void text_out(WINDOW *win, int attr, int x, int y, const char *text)
{
  while(*text)
  {
    wmove(win, y, x++);
    waddch(win, attr | *text);
    text++;
  }
  wrefresh(win);
}

void show_status(const char *msg)
{
  wclear(StatusWin);
  text_out(StatusWin, NORM_ATTR, 1, 1, msg);
}

int get_key(void)
{
  int i = getch();
  if(i == 27)
  { /* Special keys return three values, 27 + 91 + the real key */
    if(getch() == 91)
      return getch() | 0x100; /* To let the receiver know a VK_UP from a 'A' */
  }
  return i;
}

#define DUMMY_FUNC(name) \
static void name(void)          \
{                        \
  show_status(#name);    \
}

DUMMY_FUNC(func_11)
DUMMY_FUNC(func_21)
DUMMY_FUNC(func_22)
DUMMY_FUNC(func_231)
DUMMY_FUNC(func_232)
DUMMY_FUNC(func_233)

void exit_func(void)
{
  exit(0);
}

/* These are the menu's, will have to start from the buttom  */
menu_item const pb_list_menu[] =
{
  {"Ole",  NULL, func_231},
  {"Peter", NULL, func_232},
  {"Poul",  NULL, func_233},
  {"Back",  NULL, NULL},
  {NULL,    NULL, NULL}
};

menu_item const phonebook_menu[] =
{
  {"AddEntry", NULL, func_11},
  {"List",    pb_list_menu, NULL},
  {"Back",    NULL, NULL},
  {NULL,      NULL, NULL}
};

menu_item const sub_menu_2[] =
{
  {"New SMS", NULL, func_21},
  {"List",    NULL, func_22},
  {"Back",    NULL, NULL},
  {NULL,      NULL, NULL}
};

menu_item const main_menu[] =
{
  {"PhoneBook", phonebook_menu, NULL},
  {"SMS",      sub_menu_2,    NULL},
  {"Exit",      NULL,          exit_func},
  {NULL,        NULL,          NULL}
};

void exec(menu_item const * menu);

void clear_menu_window(void)
{
  wclear(MenuWin);
  box(MenuWin, ACS_VLINE, ACS_HLINE);
}

int main(void)
{
  initscr();
  cbreak();
  noecho();
  intrflush(stdscr, FALSE);
  MenuWin = subwin(stdscr, 10, 20, 1, 1);
  StatusWin = subwin(stdscr, 2, 60, 20, 1);
  intrflush(MenuWin, FALSE);
  wcolor_set(MenuWin, 3, 0);
  box(MenuWin, ACS_VLINE, ACS_HLINE);
  show_status("Simple menu demo Press UP/Down, Enter to select");

  exec(main_menu);

  return EXIT_SUCCESS;
}

/* This is the main menu executer, it will call itself to execute submenus */
void exec(menu_item const * menu)
{
  int ch;
  int i;
  int state = 0;
  clear_menu_window();
  do
  {
    /* I'm lazy so I'll update the complete menu each time */
    for(i = 0; menu[i].title; i++)
    {
      if(i == state)
        text_out(MenuWin, INVR_ATTR, 1, i + 1, menu[i].title);
      else
        text_out(MenuWin, NORM_ATTR, 1, i + 1, menu[i].title);
    }
    ch = get_key();
    switch(ch)
    {
      case VK_RETURN:  /* Enter */
        if(menu[state].function)
          menu[state].function();
        else if(menu[state].submenu)
        { /* It's a submenu */
          exec(menu[state].submenu);
          clear_menu_window();
        }
        else
        { /* It is a back menu item */
          return;
        }
        break;
      case VK_UP:
        if(state != 0)
          state--;
        break;
      case VK_DOWN:
        if(menu[state + 1].title)
          state++;
        break;
    }
  }
  while(1);
}
Avatar billede bertelbrander Novice
08. maj 2004 - 02:00 #6
Hvis ikke du kan få UP og DOWN til at virke, kan du prøve at køre følgende program og se hvad den skriver når du trykker op og ned, tryk på 'q' for at afslutte programmet.

#include <curses.h>
#include <stdio.h>

int main(void)
{
  int i;
  initscr();
  cbreak();
  noecho();
  intrflush(stdscr, FALSE);
  refresh();
  do
  {
    i = getch();
    printf(">%d\r\n", i);
    refresh();
  }
  while(i != 'q');
  return 0;
}
Avatar billede danielhep Nybegynder
08. maj 2004 - 03:59 #7
og du vil vel stadigvæk ikke have point ?
Avatar billede bertelbrander Novice
08. maj 2004 - 14:00 #8
Jeg vil hellere vide om du fik det til at virke på linux.
Avatar billede danielhep Nybegynder
08. maj 2004 - 16:05 #9
jeg er i gang med at installer een Red Hat 9.0 på en Intel maskine LIGE NU :)
Så om ca. 30 min kan jeg fortælle dig om det virkeede.. :)
Avatar billede bertelbrander Novice
08. maj 2004 - 17:21 #10
Du skal huske at linke med curses, f.ex:

gcc cmenu.cpp -lcurses
Avatar billede danielhep Nybegynder
08. maj 2004 - 18:09 #11
Dit eksemplen virker 100 % under Linux :) har lige prøvet det..menuen virker fint :)

skal jeg så bare lukke og tage point selv ?
Avatar billede danielhep Nybegynder
08. maj 2004 - 21:11 #12
tja
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester