2017-01-13 36 views
0

我試圖做一個基本的菜單C.我應該這樣做與ncurses lib。我與本教程: Video On YouTube基本的Ncurses菜單

但我的版本也存在一些問題: 1)菜單將無法正確打印,只有在選擇菜單項就會顯示出來。然後突出顯示不會關閉 2)菜單上的選項不會打印在頂部

您能幫我嗎?菜單的想法是好還是我應該尋找其他教程(任何幫助?)。

#include <stdio.h> 
#include <ncurses.h> 
#include <string.h> 
#include <menu.h> 
int main(int argc, char **argv) 
{ 
    int i, c; 
    char powitanie[]="SLOWNIK UNIWERSALNY"; 
    int szer, dlug; //wartosci dlugosci i szerokosci terminalu 
    initscr(); //Inizjalizacja całości ncurses, kolory itp 
    raw(); 
    noecho(); 
    keypad(stdscr, TRUE); 
    start_color(); 
    //init_pair(1, COLOR_BLUE, COLOR_BLACK); //wybór kolorów 
    getmaxyx(stdscr, szer, dlug); //pobranie rozmiarów terminalu 
    move(szer/2, (dlug-strlen(powitanie))/2); //przesuwamy kursor na środek (tak aby się ładnie wydrukowało) 
    //attron(COLOR_PAIR(1)); //Aktywujemy wybrane kolory 
    printw(powitanie); //Drukujemy powitanie 
    //attroff(COLOR_PAIR(1));//Dezaktywujemy kolory 
    refresh();//Odswiezamy (inaczej się nie wyswietli) 
    WINDOW * menuwin=newwin(6, dlug-12, szer-8, 6); //Definiujemy i tworzymy 'okno' 
    box(menuwin, 0, 0); 
    refresh();//ponownie odświeżamy aby okno się pojawiło 
    wrefresh(menuwin);//odświeżamy samo okno 
    keypad(menuwin, TRUE);//umozliwiamy dzialanie klawiatury w oknie 
    char *opcje[] = { 
         "Tlumacz z Polskiego na Angielski", 
         "Tlumacz z Angielskiego na Polski", 
         "Edystuj slownik", 
         "Wybierz slownik", 
         "Wyjdz", 
        }; 
    int wybor; 
    int zaznacz=0; 
    while(1)//cala ta petla sluzy ciaglemu tworzeniu menu z podswietleniem wybranego elementu 
    { 
     for(i=0; i<5; i++) 
     { 
      if(i==zaznacz) 
      { 
       wattron(menuwin, A_REVERSE); 
       mvwprintw(menuwin, i+1, 1, opcje[i]); 
       wattroff(menuwin, A_REVERSE); 
      } 
      wybor = wgetch(menuwin); 
      switch(wybor) 
      { 
       case KEY_UP: 
       zaznacz--; 
       if(zaznacz==-1) zaznacz=0;//zabezpieczenie przed wyjsciem "poza" menu 
       break; 
       case KEY_DOWN: 
       zaznacz++; 
       if(zaznacz==5) zaznacz=4; 
       break; 
       default: 
       break; 
      } 
      if(wybor==10) break; 
     } 
     printw("Wybrano:%s", opcje[zaznacz]); 
    } 
    return(0); 
} 

PS:代碼註釋不是英語,但我希望不會是必要的

回答

1

這裏有相當多的問題。我已經包含了一個可用的代碼的修改版本,我將嘗試描述這些更改。

有一些未使用的變量,即argc,argvc,所以我將它們轉換爲void以便消除編譯器警告。如果您願意,您可以刪除c並更改爲int main(void),完全刪除這些變量。

我已將stdlib.h頭文件添加到您的#include中,以獲得exit()函數。這用於添加到代碼中的新錯誤函數fail()。您應該始終檢查在C編程時調用的任何函數的返回值。在此,首先檢查終端是否支持has_colors()函數的顏色,以及如果start_color()的調用成功,則特別重要。如果其中任何一個失敗,將調用fail()函數並顯示一條錯誤消息,程序將以EXIT_FAILURE的值退出。函數has_colors()返回bool,並且start_color()函數返回int(如果成功則返回OK,否則返回ERR)。

現在顏色已經初始化,我看到菜單選擇窗口的下邊框被菜單文本覆蓋。爲了解決這個問題,我改變了窗口的大小,使之成爲高一行:

WINDOW * menuwin=newwin(7, dlug-12, szer-9, 6); 

您報告是因爲for循環放錯地方的支柱控制菜單的印刷不當印刷的基本問題項目。我藉此機會重新組織循環,現在只有一個呼叫mvwprintw()。如果當前項目也是選定項目,則在打印前設置A_REVERSE屬性,並且在打印後再次取消設置。

我也將switch聲明中的極限測試從平等變爲不等式。在這種情況下,最好使用if (zaznacz < 0)而不是if (zaznacz == -1)。 我在最後的printw()格式字符串的開頭添加了一個換行符,因爲某些選擇太長而無法放在標題末尾的窗口中。你可以隨意移動這個輸出。

最後,我添加了最後printw()聲明後refresh()getch()等待用戶打ENTER再退出程序。在退出NCurses程序之前,通過調用endwin()進行清理非常重要。此功能可以反轉程序運行時由NCurses對終端所做的更改,如果不執行此操作可能會導致終端不愉快。

#include <stdio.h> 
#include <ncurses.h> 
#include <string.h> 
#include <menu.h> 
#include <stdlib.h>   // added for exit() function 

void fail(char *msg) { 
    endwin(); 
    puts(msg); 
    exit(EXIT_FAILURE); 
} 

int main(int argc, char **argv) 
{ 
    /* Commandline argument currently unused */ 
    (void) argc; 
    (void) argv; 

    int i, c; 
    (void) c;      // c is currently unused 
    char powitanie[]="SLOWNIK UNIWERSALNY"; 
    int szer, dlug; //wartosci dlugosci i szerokosci terminalu 

    initscr(); //Inizjalizacja całości ncurses, kolory itp 
    raw(); 
    noecho(); 
    keypad(stdscr, TRUE); 

    /* Test to see if terminal has colors */ 
    if (has_colors() == false) { 
     fail("Colors unavailable\n"); 
    } 

    if (start_color() != OK) { 
     fail("Unable to start colors\n"); 
    } 

    //init_pair(1, COLOR_BLUE, COLOR_BLACK); //wybór kolorów 

    getmaxyx(stdscr, szer, dlug); //pobranie rozmiarów terminalu 
    move(szer/2, (dlug-strlen(powitanie))/2); //przesuwamy kursor na środek (tak aby się ładnie wydrukowało) 
    //attron(COLOR_PAIR(1)); //Aktywujemy wybrane kolory 
    printw(powitanie); //Drukujemy powitanie 
    //attroff(COLOR_PAIR(1));//Dezaktywujemy kolory 
    refresh();//Odswiezamy (inaczej się nie wyswietli) 
    WINDOW * menuwin=newwin(7, dlug-12, szer-9, 6); //Definiujemy i tworzymy 'okno' 
    box(menuwin, 0, 0); 
    refresh();//ponownie odświeżamy aby okno się pojawiło 
    wrefresh(menuwin);//odświeżamy samo okno 
    keypad(menuwin, TRUE);//umozliwiamy dzialanie klawiatury w oknie 

    char *opcje[] = { 
     "Tlumacz z Polskiego na Angielski", 
     "Tlumacz z Angielskiego na Polski", 
     "Edystuj slownik", 
     "Wybierz slownik", 
     "Wyjdz", 
    }; 
    int wybor; 
    int zaznacz=0; 

    while(1)//cala ta petla sluzy ciaglemu tworzeniu menu z podswietleniem wybranego elementu 
    { 
     for(i = 0; i < 5; i++) { 
      if(i == zaznacz) 
       wattron(menuwin, A_REVERSE); 
      mvwprintw(menuwin, i+1, 1, opcje[i]); 
      if (i == zaznacz) 
       wattroff(menuwin, A_REVERSE); 
     } 

     wybor = wgetch(menuwin); 
     switch(wybor) 
     { 
     case KEY_UP: 
      zaznacz--; 
      if(zaznacz < 0) zaznacz = 0;//zabezpieczenie przed wyjsciem "poza" menu 
      break; 
     case KEY_DOWN: 
      zaznacz++; 
      if(zaznacz > 4) zaznacz = 4; 
      break; 
     default: 
      break; 
     } 

     if(wybor==10) break; 
    } 

    printw("\nWybrano:%s", opcje[zaznacz]); 
    refresh(); 

    /* Wait for user to press enter to exit */ 
    getch(); 

    /* Need to cleanup before exit */ 
    endwin(); 

    return 0; 
} 
+1

的menu.h頭是在本例中未使用的。 –