Advertisement
Phr0zen_Penguin

A Perfect Console Menu

Aug 29th, 2014
332
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.30 KB | None | 0 0
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement