SHARE
TWEET

A Perfect Console Menu

Phr0zen_Penguin Aug 29th, 2014 220 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*==================================================================================================
  2.   --------------------------------------------------------------------------------------------------
  3.   [perfectConMenu.cpp]
  4.         A pretty decent, unflinching (in terms of imperfections), console menu.
  5.  
  6.                 (c) Damion 'Phr0z3n.dev' Tapper, 2014.
  7.                 Email: Phr0z3n.Dev@Gmail.com
  8.   --------------------------------------------------------------------------------------------------
  9.   ==================================================================================================*/
  10.  
  11. /**
  12.  * These definitions will be used to select code based on OS environment.  Standard library definitions
  13.  * could be utilised but, being that some compilers and architectures are still undergoing the 32 -> 64 bit
  14.  * transition, I guess its best to stay on the safe side for the time being.
  15.  **/
  16. #define _WINDOWS        0x001
  17. #define _NIX            0x002
  18.  
  19. /**
  20.  * Comment/uncomment as required.
  21.  **/
  22. #define _MY_ENV WINDOWS
  23. //#define       _MY_ENV _NIX
  24.  
  25. #include <iostream>
  26. #include <string>
  27.  
  28. #if _MY_ENV == WINDOWS
  29.         #include <windows.h>
  30.  
  31.         #define CSBI    CONSOLE_SCREEN_BUFFER_INFO
  32. /**
  33.  * This directive is almost never required for the 'system' function is almost always accessible anyway.
  34.  **/
  35. #elif _MY_ENV == _NIX
  36.         #include <cstdlib>
  37.         #include <unistd.h>
  38.         #include <term.h>
  39. #endif
  40.  
  41. /*===============================================--=================================================
  42.                                                                                 FUNCTION PROTOTYPES
  43.   ==================================================================================================*/
  44. int mainMenu(void);
  45. void sysAdmin(void);
  46. inline void clearScreen(void);
  47.  
  48. int main(void)
  49. {
  50.                 if(mainMenu() == 0)
  51.                 {
  52.                         exit(EXIT_SUCCESS);
  53.                 }
  54.  
  55.         return 0;
  56. }
  57.  
  58. /*===============================================--=================================================
  59.                                                                                 THE MAIN MENU FUNCTION
  60.   ==================================================================================================*/
  61. int mainMenu(void)
  62. {
  63.         std::string *mainMenuOptBuffer = new std::string; /* Why 'string' and not 'char'? */
  64.  
  65.                 /**
  66.                  * std::cin.get() (not pertaining to certain overloaded versions), accepts (and store) only one
  67.                  * character at a time (ONLY when ENTER is pressed).  This bit of logic
  68.                  * does not hinder the fact that more than one characters can still be entered at an std::cin.get()
  69.                  * prompt.
  70.                  *
  71.                  * In its true sense, expecting a '1' menu option and even accepting a '1abc' option instead,
  72.                  * is in no way, logical.  std::cin.getline() will store all options entered, and the relative logic
  73.                  * implemented, will evaluate and differentiate between '1' and '1abc' (&| an option of length 1 || > 1).
  74.                  *
  75.                  * It is the latter-mentioned logic, which is actually implemented in this code, that makes this
  76.                  * program foolproof.
  77.                  **/
  78.                 while(mainMenuOptBuffer->length() != 1)
  79.                 {
  80.                         /**
  81.                          * Console menu recursion without logic to clear the screen is redundantly messy.  No pun intended.
  82.                          **/
  83.                         clearScreen();
  84.  
  85.                         std::cout << "SELECT OPTION (1-8)" << std::endl << std::endl;
  86.                         std::cout << "[COLOR]" << std::endl;
  87.                         std::cout << "1. " << "Red" << std::endl;
  88.                         std::cout << "2. " << "Green" << std::endl;
  89.                         std::cout << "3. " << "Blue" << std::endl;
  90.                         std::cout << "4. " << "Cyan" << std::endl;
  91.                         std::cout << "5. " << "Magenta" << std::endl;
  92.                         std::cout << "6. " << "Yellow" << std::endl << std::endl;
  93.  
  94.                         std::cout << "[SYSTEM]" << std::endl;
  95.                         std::cout << "7. " << "Admin" << std::endl;
  96.                         std::cout << "8. " << "Exit" << std::endl << std::endl;
  97.  
  98.                         std::cout << ">: ";
  99.  
  100.                         std::getline(std::cin, *mainMenuOptBuffer, '\n');
  101.                 }
  102.  
  103.         std::cout << std::endl;
  104.  
  105.                 switch(mainMenuOptBuffer->data()[0])
  106.                 {
  107.                         case '1':
  108.                                 std::cout << "You selected 'Red'";
  109.                                 break;
  110.                         case '2':
  111.                                 std::cout << "You selected 'Green'";
  112.                                 break;
  113.                         case '3':
  114.                                 std::cout << "You selected 'Blue'";
  115.                                 break;
  116.                         case '4':
  117.                                 std::cout << "You selected 'Cyan'";
  118.                                 break;
  119.                         case '5':
  120.                                 std::cout << "You selected 'Magenta'";
  121.                                 break;
  122.                         case '6':
  123.                                 std::cout << "You selected 'Yellow'";
  124.                                 break;
  125.                         case '7':
  126.                                 sysAdmin();
  127.                                 break;
  128.                         case '8':
  129.                                 return 0;       /* The program returns to 'main' to exit.  More than just cool stuff. */
  130.                         default:
  131.                                 /**
  132.                                  * If no option matches the main menu is redisplayed.
  133.                                  * Notice how the function did not recurse.  That technique can prove a bit elusive under
  134.                                  * certain coding circumstances.  This method is so superior, it should be considered
  135.                                  * de jure or boilerplate.
  136.                                  **/
  137.                                 mainMenu();
  138.                 }
  139.  
  140.         /**
  141.          * NOTE:
  142.          * You may or may not want to implement code here to store the main menu option globally, in case
  143.          * the operations of other sections of your program depend on it.
  144.          *
  145.          * 'CMainMenu::setMainMenuOption(mainMenuOptBuffer->data()[0])', for instance.
  146.          **/
  147.  
  148.         /**
  149.          * A coding guru once told me that clean code is superior coding practice, not only in its logic but
  150.          * also in its manifestation.  Hence, the disposal of unneeded variables.
  151.          **/
  152.         delete mainMenuOptBuffer;
  153.  
  154.         return 0;
  155. }
  156.  
  157. /*===============================================--=================================================
  158.                                                                 THE 'Admin' OPTION FUNCTION EXAMPLE
  159.   ==================================================================================================*/
  160. void sysAdmin(void)
  161. {
  162.     std::cout << "Congrats!  You made it in the system...";
  163. }
  164.  
  165. /*===============================================--=================================================
  166.                                                                         THE CLEAR SCREEN FUNCTION
  167.   ==================================================================================================*/
  168. inline void clearScreen(void)
  169. {
  170. #if _MY_ENV == WINDOWS
  171.         /**
  172.          * NOTE:
  173.          * This particular function is a nifty little snippet anyone can use, with minor alterations
  174.          * (function name), to clear the console screen on Windows, without having to depend on the
  175.          * predefined non-standard ones in particular IDEs.  All that is required is the inclusion of the
  176.          * 'windows.h' header file.
  177.          **/
  178.         COORD   coordScreen = {0, 0}; /* Home for the cursor. */
  179.         DWORD   cCharsWritten;
  180.  
  181.         /**
  182.          * NOTE:
  183.          * CSBI is originally defined as CONSOLE_SCREEN_BUFFER_INFO in (windows.h) 'wincon.h' but I suspected
  184.          * that the abbreviated redefinition (in 'simpleCrypto.hpp') would make the code neater.
  185.          **/
  186.         CSBI    csbi;
  187.         DWORD   dwConSize;
  188.         HANDLE  hConsoleOut = GetStdHandle(STD_OUTPUT_HANDLE);
  189.  
  190.         /* Get the number of character cells in the current buffer. */
  191.         if(!GetConsoleScreenBufferInfo(hConsoleOut, &csbi))
  192.                 return;
  193.  
  194.         dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
  195.  
  196.         /* Fill the entire screen with blanks. */
  197.         if(!FillConsoleOutputCharacter(hConsoleOut, ' ', dwConSize, coordScreen, &cCharsWritten))
  198.                 return;
  199.  
  200.         /* Get the current text attribute. */
  201.         if(!GetConsoleScreenBufferInfo(hConsoleOut, &csbi))
  202.                 return;
  203.  
  204.         /* Set the buffer's attributes accordingly. */
  205.         if(!FillConsoleOutputAttribute(hConsoleOut, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten))
  206.                 return;
  207.  
  208.         /* Put the cursor at its home coordinates. */
  209.         SetConsoleCursorPosition(hConsoleOut, coordScreen);
  210. #elif _MY_ENV == _NIX
  211.                 if(!cur_term)
  212.                 {
  213.                         int result;
  214.                         setupterm(NULL, STDOUT_FILENO, &result);
  215.                         if(result <= 0) return;
  216.                 }
  217.  
  218.         putp(tigetstr("clear"));
  219. #endif // _MY_ENV
  220. }
RAW Paste Data
Top