CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 5 of 5
  1. #1
    Join Date
    May 2012
    Posts
    2

    Detect arrow key press in c++ for linux only, 80% of the job is done.

    Hello all - here is my first post,

    I've googled this one to death.

    I'm trying to implement this on ubuntu, to compile and run only under ubuntu.

    I found 100s of other attempts at answering the general question of arrow key press in c++. Nothing solid.

    Some recommend using the Readline for the functionality I am trying to implement, but I need to stay clear of GNU licences if I
    can for this project. And some tips only work on projects for windows machines... for example the conio library.

    For linux there may be the option of using the ncurses library which I will take a look at, but I am stubborn and want to implement this myself. It should be an easy straight forward thing to do, which is why I am a bit frustrated at the moment.

    Here is my test code so far.

    My dirty code...

    Code:
    #include <iostream>
    #include <sstream>
    #include <stdio.h>
    #include <string.h>
    #include <termios.h>
    #include <unistd.h>
    
    using namespace std;
    
    int main(void)
    {
    
    char a;
    stringstream ss;
    string s;
    string s2;
    int i;
    const char * cs;
    
    // Here I attempt to set stdin to unbuffered, read directly from the keyboard.
    
        struct termios term;
        tcgetattr(STDIN_FILENO, &term);
        term.c_lflag &= ~ICANON;
        tcsetattr(STDIN_FILENO, TCSANOW, &term);
    
    // I wait and get each key press here, initialise to first keystroke.
    a=getchar();
    
    // While enter is not pressed, build a complete string.
    
    while(a != '\n')
    {s=s+a;
    a=getchar();
    ss << a;
    ss >> s2;
    cs = s2.c_str();
    
    //Here I output the ascii code number each time a key is pressed.
    i=cs[0];
    cout<< i;
    
    
    
    
    ss.clear();
    
    };
    
    //Restore buffer mode
    
    tcgetattr(STDIN_FILENO, &term);
    term.c_lflag |= ICANON;
    tcsetattr(STDIN_FILENO, TCSANOW, &term);
    
    
    
    
        return 0;
    }

    So! This works... 80% of the problem is solved.

    If you compile this, g++ under linux, ubuntu in my case, and run.

    Each keystroke reveals the correct key numbers.

    q=113
    w=119


    when I click on the up key I get,

    up = 279165

    GREAT! I thought, I can use this number is a if(int == '279165') to detect the up key.

    I was not so lucky... this int is not behaving like an int!

    So I modified the code to see it I could carry out an int operation on this number.

    I added a 100000 to int i.

    cout<< i + 100000;

    Code:
    #include <iostream>
    #include <sstream>
    #include <stdio.h>
    #include <string.h>
    #include <termios.h>
    #include <unistd.h>
    
    using namespace std;
    
    int main(void)
    {
    
    char a;
    stringstream ss;
    string s;
    string s2;
    int i;
    const char * cs;
    
    // Here I attempt to set stdin to unbuffered, read directly from the keyboard.
    
        struct termios term;
        tcgetattr(STDIN_FILENO, &term);
        term.c_lflag &= ~ICANON;
        tcsetattr(STDIN_FILENO, TCSANOW, &term);
    
    // I wait and get each key press here, initialise to first keystroke.
    a=getchar();
    
    // While enter is not pressed, build a complete string.
    
    while(a != '\n')
    {s=s+a;
    a=getchar();
    ss << a;
    ss >> s2;
    cs = s2.c_str();
    
    //Here I output the ascii code number each time a key is pressed.
    i=cs[0];
    cout<< i + 100000;
    
    
    
    
    ss.clear();
    
    };
    
    //Restore buffer mode
    
    tcgetattr(STDIN_FILENO, &term);
    term.c_lflag |= ICANON;
    tcsetattr(STDIN_FILENO, TCSANOW, &term);
    
    
    
    
        return 0;
    }
    Compiling and running this, and pressing the UP key gives the following number.

    100027100091100065

    !Ha! Some some sort of array, something like, [27][91][65].

    I tried all ways to access these individual numbers, actually the third one for comparison purposes,
    but no luck.

    For completeness sake I list the other arrows.

    UP = [27][91][65]
    DOWN = [27][91][66]
    LEFT = [27][91][68]
    RIGHT = [27][91][67]

    A little further digging shows that these numbers are derived from the representation of a "multi-char" constant, the data type
    given when pressing special characters...

    Now here is the main problem I have, I can find ANY decent documentation on how to handle and
    play with "multi-char"

    If I had that, I would feel happy.

    Any ideas anyone?

  2. #2
    Join Date
    Oct 2002
    Location
    Austria
    Posts
    1,284

    Re: Detect arrow key press in c++ for linux only, 80% of the job is done.

    You might want to read http://en.wikipedia.org/wiki/ANSI_escape_code
    Kurt

  3. #3
    Join Date
    May 2012
    Posts
    2

    Re: Detect arrow key press in c++ for linux only, 80% of the job is done.

    Quote Originally Posted by ZuK View Post
    Hi Kurt,

    Thanks for the fast reply. I will have a read - I may need to ask a few questions later on the ANSI_escape_code... i'm really curious to get my example working.


    As for a quick fix, for anyone googling a solution for detecting arrow keys, here's a working example I found that works on ubuntu.

    Code:
    #include <unistd.h>
    #include <stdlib.h>
    #include <ncurses.h>
    
    #define LOCAL_ESCAPE_KEY 27
    
    int main(void)
    {
    
    int key;
    
    initscr();
    crmode();
    keypad(stdscr, TRUE);
    noecho();
    clear();
    mvprintw(5,5, "Keypad demonstration. Press 'q' to quit");
    move(7,5);
    refresh();
    key = getch();
    
    while(key != ERR && key != 'q') {
    	move(7,5);
    	clrtoeol();
    
    	if ((key >= 'A' && key <= 'Z')||(key >= 'a' && key <= 'z')){
    	printw("Key was %c", (char)key);
    	}
    	else {
    	switch(key){
    	case LOCAL_ESCAPE_KEY: printw("%s", "Escape key"); break;
    	case KEY_END: printw("%s", "END key"); break;
    	case KEY_RIGHT: printw("%s", "RIGHT key"); break;
    	case KEY_LEFT: printw("%s", "LEFT key"); break;
    	case KEY_UP: printw("%s", "UP key");break;
    	case KEY_DOWN: printw("%s", "DOWN key"); break;
    	default: printw("Unmatched - %d", key); break;
    	}/* switch */
    	}/*else*/
    	
    	refresh();
    	key = getch();
    	}/* while */
    	endwin();
    exit(EXIT_SUCCESS);
    };
    
    
    //}

    Code:
    g++ example.cpp -I /usr/include -lncurses -o example

  4. #4
    Join Date
    Oct 2013
    Posts
    10

    Re: Detect arrow key press in c++ for linux only, 80% of the job is done.

    Here is a simple example to detecting a keypress in c++ using while loop and getch() hope it may be helpfull.

  5. #5
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,923

    Re: Detect arrow key press in c++ for linux only, 80% of the job is done.

    Quote Originally Posted by fahadmunir32 View Post
    Here is a simple example to detecting a keypress in c++ using while loop and getch() hope it may be helpfull.
    This uses the conio library which the OP didn't want to use as this is for windows whereas a Ubuntu solution was needed.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured