C++在用户按下箭头键时检测

q1qsirdb  于 2022-12-20  发布在  其他
关注(0)|答案(7)|浏览(193)

我在C++控制台应用程序中遇到了一个检测箭头键按下的问题。我已经尝试了所有我能找到的方法,包括这里和其他教程网站,但每当我按下箭头时,所有这些网站都给予我同样的结果:

Process returned 0 <0x0> execution time : 2.249 s
Press any key to continue.

以下是我尝试过的所有检测按键的方法,结果都是一样的。这是我的代码中仅剩下的两种方法,其他我尝试过的方法我都删除了,而不是注解掉。
方法一:

c1 = getch();
if(c1 == 0)
{

    c2 = getch();

    if(c2 == 72) {cout << endl << "Up Arrow" << endl;}
    else if(c2 == 80) {cout << endl << "Down Arrow" << endl;}
    else{cout << endl << "Incorrect Input" << endl;}

}

方法二:

switch(getch()) {
case 65:
       cout << endl << "Up" << endl;//key up
    break;
case 66:
    cout << endl << "Down" << endl;   // key down
    break;
case 67:
    cout << endl << "Right" << endl;  // key right
    break;
case 68:
    cout << endl << "Left" << endl;  // key left
    break;
}

我的代码中有什么错误让我回到了我的主方法,或者跳过了一些代码?有没有更快的方法来做到这一点?我几乎100%肯定我的其他代码与这个问题没有任何关系,因为我隔离了代码,使其不依赖于程序的任何其他方面,但我一直有同样的问题。
我又一次尝试了我能找到的每一种获得箭头键按下的方法,但我一直遇到同样的问题。如果有问题的话,我在Windows 8三星ATIV智能PC上使用键盘底座。
提前感谢您的帮助。

c9qzyr3d

c9qzyr3d1#

#include <conio.h>
#include <iostream>
using namespace std;

#define KEY_UP 72
#define KEY_DOWN 80
#define KEY_LEFT 75
#define KEY_RIGHT 77

int main()
{
    int c = 0;
    while(1)
    {
        c = 0;

        switch((c=getch())) {
        case KEY_UP:
            cout << endl << "Up" << endl;//key up
            break;
        case KEY_DOWN:
            cout << endl << "Down" << endl;   // key down
            break;
        case KEY_LEFT:
            cout << endl << "Left" << endl;  // key left
            break;
        case KEY_RIGHT:
            cout << endl << "Right" << endl;  // key right
            break;
        default:
            cout << endl << "null" << endl;  // not arrow
            break;
        }

    }

    return 0;
}

输出如下:

Up

Down

Right

Left

Up

Left

Right

Right

Up

检测到箭头键按下!

xxb16uws

xxb16uws2#

arboter之前的回答很接近,但忽略了箭头键(和其他特殊键)返回两个字符的扫描码的事实。第一个是(0)或(224),表明该键是一个扩展键;第二个包含扫描码值。
如果不考虑这一点,“H”、“K”、“M”和“P”的ASCII值会被错误地解释为“上”、“下”、“左”和“右.”
下面是arboter代码的修改版本,演示了当按下其中一个箭头键时阅读扩展值的过程:

#include <conio.h>
#include <iostream>
using namespace std;

#define KEY_UP    72
#define KEY_LEFT  75
#define KEY_RIGHT 77
#define KEY_DOWN  80

int main()
{
    int c, ex;

    while(1)
    {
        c = getch();

        if (c && c != 224)
        {
            cout << endl << "Not arrow: " << (char) c << endl;
        }
        else
        {
            switch(ex = getch())
            {
                case KEY_UP     /* H */:
                    cout << endl << "Up" << endl;//key up
                    break;
                case KEY_DOWN   /* K */:
                    cout << endl << "Down" << endl;   // key down
                    break;
                case KEY_LEFT   /* M */:
                    cout << endl << "Left" << endl;  // key left
                    break;
                case KEY_RIGHT: /* P */
                    cout << endl << "Right" << endl;  // key right
                    break;
                default:
                    cout << endl << (char) ex << endl;  // not arrow
                    break;
            }
        }
    }

    return 0;
}
wmomyfyw

wmomyfyw3#

// Example for inputting a single keystroke in C++ on Linux
// by Adam Pierce <adam@doctort.org> on http://www.doctort.org/adam/nerd-notes/reading-single-keystroke-on-linux.html
// This code is freeware. You are free to copy and modify it any way you like.
// Modify by me Putra Kusaeri

#include <iostream>
#include <termios.h>
#define STDIN_FILENO 0
using namespace std;
int main()
{
// Black magic to prevent Linux from buffering keystrokes.
    struct termios t;
    tcgetattr(STDIN_FILENO, &t);
    t.c_lflag &= ~ICANON;
    tcsetattr(STDIN_FILENO, TCSANOW, &t);

// Once the buffering is turned off, the rest is simple.
    cout << "Enter a character: ";
    char c,d,e;
    cin >> c;
    cin >> d;
    cin >> e;
    cout << "\nYour character was ";
// Using 3 char type, Cause up down right left consist with 3 character
    if ((c==27)&&(d==91)) {
        if (e==65) { cout << "UP";}
        if (e==66) { cout << "DOWN";}
        if (e==67) { cout << "RIGHT";}
        if (e==68) { cout << "LEFT";}
    }
    return 0;
}

reference

6gpjuf90

6gpjuf904#

这里有一个不用 getch() 使用 events 的替代方法(评论很好,我尽量使它简单)

#include <iostream>
#include <Windows.h>

int main(int argc, char *argv[]){

    HANDLE rhnd = GetStdHandle(STD_INPUT_HANDLE);  // handle to read console

    DWORD Events = 0;     // Event count
    DWORD EventsRead = 0; // Events read from console

    bool Running = true;

    //programs main loop
    while(Running) {

        // gets the systems current "event" count
        GetNumberOfConsoleInputEvents(rhnd, &Events);

        if(Events != 0){ // if something happened we will handle the events we want

            // create event buffer the size of how many Events
            INPUT_RECORD eventBuffer[Events];

            // fills the event buffer with the events and saves count in EventsRead
            ReadConsoleInput(rhnd, eventBuffer, Events, &EventsRead);

            // loop through the event buffer using the saved count
            for(DWORD i = 0; i < EventsRead; ++i){

                // check if event[i] is a key event && if so is a press not a release
                if(eventBuffer[i].EventType == KEY_EVENT && eventBuffer[i].Event.KeyEvent.bKeyDown){

                    // check if the key press was an arrow key
                    switch(eventBuffer[i].Event.KeyEvent.wVirtualKeyCode){
                        case VK_LEFT:
                        case VK_RIGHT:
                        case VK_UP:
                        case VK_DOWN:   // if any arrow key was pressed break here
                            std::cout<< "arrow key pressed.\n";
                            break;

                        case VK_ESCAPE: // if escape key was pressed end program loop
                            std::cout<< "escape key pressed.\n";
                            Running = false;
                            break;

                        default:        // no handled cases where pressed 
                            std::cout<< "key not handled pressed.\n";
                            break;
                    }
                }

            } // end EventsRead loop

        }

    } // end program loop

    return 0;
}

(感谢一位评论者,我现在知道这段代码不是标准的,尽管如果你用g++编译它会工作,更多信息在评论中)

ipakzgxi

ipakzgxi5#

这里给出的一些答案没有考虑到按下箭头键时接收到2个字符的事实。另外,需要注意的是,输入字符应该是unsigned char。这是因为要确定是否按下了箭头键,我们使用ASCII值224,它只能存储在8位字符(unsigned char)中,而不能存储在7位有符号字符中。
您可以使用下面的代码片段。2种类型的输入在这里处理。ch1是用户输入的第一个字符。这是用户正在输入的输入。但在箭头键的情况下,接收2个字符的序列ch1和ch2。ch1确定一些箭头键被按下,ch2确定特定的箭头键被按下。

const int KEY_ARROW_CHAR1 = 224;
const int KEY_ARROW_UP = 72;
const int KEY_ARROW_DOWN = 80;
const int KEY_ARROW_LEFT = 75;
const int KEY_ARROW_RIGHT = 77;

unsigned char ch1 = _getch();
if (ch1 == KEY_ARROW_CHAR1)
{
    // Some Arrow key was pressed, determine which?
    unsigned char ch2 = _getch();
    switch (ch2) 
    {
    case KEY_ARROW_UP:
        // code for arrow up
        cout << "KEY_ARROW_UP" << endl;
        break;
    case KEY_ARROW_DOWN:
        // code for arrow down
        cout << "KEY_ARROW_DOWN" << endl;
        break;
    case KEY_ARROW_LEFT:
        // code for arrow right
        cout << "KEY_ARROW_LEFT" << endl;
        break;
    case KEY_ARROW_RIGHT:
        // code for arrow left
        cout << "KEY_ARROW_RIGHT" << endl;
        break;
    }
}
else
{
    switch (ch1)
    {
        // Process other key presses if required.
    }
}
0vvn1miw

0vvn1miw6#

检查http://msdn.microsoft.com/en-us/library/windows/desktop/ms684961(v=vs.85).aspxhttp://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx

#include<windows.h>
#include <stdio.h>

int main()
{
    HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
    DWORD NumInputs = 0;
    DWORD InputsRead = 0;
    bool running = true;

    INPUT_RECORD irInput;

    GetNumberOfConsoleInputEvents(hInput, &NumInputs);

    ReadConsoleInput(hInput, &irInput, 1, &InputsRead);

    switch(irInput.Event.KeyEvent.wVirtualKeyCode)
    {
        case VK_ESCAPE:
        puts("Escape");
        break;

        case VK_LEFT:
        puts("Left");
        break;

        case VK_UP:
        puts("Up");
        break;

        case VK_RIGHT:
        puts("Right");
        break;

        case VK_DOWN:
        puts("Down");
        break;
    } 

}
mf98qq94

mf98qq947#

#include <iostream>
#include <conio.h>

const int KB_UP = 72;
const int KB_DOWN = 80;
const int KB_RIGHT = 77;
const int KB_LEFT = 75;
const int ESC = 27;

int main() {
    
    while (true) {
        int ch = _getch();
        if (ch == 224) {
            ch = _getch();
            switch (ch) {
            case KB_UP: 
                std::cout << "up\n";   
                break;
            case KB_DOWN:
                std::cout << "down\n";
                break;
            case KB_RIGHT:
                std::cout << "right\n";
                break;
            case KB_LEFT:
                std::cout << "left\n";
                break;
            default: std::cout << "unknown\n";
            }
        }
        else if (ch == ESC)
        {
            std::cout << "Escape pressed, going out!\n";
            break;
        }
    }
}

这与上面的一些示例非常相似,只是我使用了

_getchar()

代替

getchar()

Visual Studio(我用来编写和运行我代码)会给出关于的错误,而且我还将它放在一个循环中,直到您按Escape bottom。

相关问题