|
-
May 13th, 2012, 11:57 AM
#1
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?
-
May 13th, 2012, 01:41 PM
#2
Re: Detect arrow key press in c++ for linux only, 80% of the job is done.
-
May 13th, 2012, 02:03 PM
#3
Re: Detect arrow key press in c++ for linux only, 80% of the job is done.
 Originally Posted by ZuK
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
-
November 22nd, 2014, 06:11 PM
#4
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.
-
November 23rd, 2014, 04:22 AM
#5
Re: Detect arrow key press in c++ for linux only, 80% of the job is done.
 Originally Posted by fahadmunir32
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|