Hejka!
Kiedyś chciałem zrobić takie fajne menu sterowane strzałkami w moim programie w C++. Jako, że programuję pod Linuksem nie mam dostępu do bibliotek Windowsowych, które (jednak) ułatwiły by sprawę. Zmuszony więc byłem do własnoręcznego napisania kilku funkcji…
int kbhit()
{
struct termios oldt, newt;
int ch;
int oldf;
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
ch = getchar();
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
fcntl(STDIN_FILENO, F_SETFL, oldf);
if(ch != EOF)
{
ungetc(ch, stdin);
return 1;
}
return 0;
}
int mygetch() {
struct termios oldt,
newt;
int ch;
tcgetattr( STDIN_FILENO, &oldt );
newt = oldt;
newt.c_lflag &= ~( ICANON | ECHO );
tcsetattr( STDIN_FILENO, TCSANOW, &newt );
ch = getchar();
tcsetattr( STDIN_FILENO, TCSANOW, &oldt );
return ch;
}
Funkcja kbhit sprawdza, czy wciśnięty został klawisz. To podstawa. Natomiast funkcja mygetch() czyta z bufora jego kod. To już mamy. Ale, jak to zaimplementować? A konkretniej, jak to działa? I dlaczego nie działa?
Już odpowiadam:
int main() {
int ile,polowa;
int pk1 = 0;
int pk2 = 0;
int k;
int index = 0;
int side = 0;
while(k != 10) {
while(!kbhit()) { usleep(250); }
pk1 = pk2;
pk2 = k;
k = mygetch();
if(pk1 == 27 && pk2 == 91) {
switch(k) {
case 65: { index--; if(index < 0) index = 0; break; } // Strzałka w górę
case 66: { index++; if(index == polowa) index = polowa - 1; break; } // Strzałka w dół
case 67: { if(side == 0) side = 1; break; } // Strzałka w prawo
case 68: { if(side == 1) side = 0; break; } // Strzałka w lewo
}
// Obsługa menu
}
}
return false;
}
Co robi ten kod? Pierwsza pętla while() sprawdza, czy ostatni klawisz to ESC. Jeśli tak, pętla się nie wykona. Następne while() co 250 milisekund sprawdza, czy wciśnięto klawisz. Jeśli tak, program kontynuuje pracę. Następnie mamy obsługę „dwu klawiszy” poprzednich. O tym za chwilę. Następnie pobieramy kod klawisza i obsługujemy go.
Okej, ale dlaczego pk1 == 27 i pk2 == 97? Wciśnięcie strzałki powoduje wysłanie aż czterech „kodów” (czytaj: bajtów). Dopiero trzeci bajt zawiera interesujący nas koszt klawisza. Następnie za pomocą instrukcji switch obsługujemy akcje odpowiednie dla każdej ze strzałek.
Dalej piszemy sobie już obsługę wedle życzenia. Wiem, że kod jest brzydki i prawdopodobnie napisany źle, ale jakoś działa. Poza tym, pisany był na szybko podczas zajęć z programowania. :D
Być może komuś pomogłem. Pozdrawiam i uważajcie na buffer overflow!