通过字符输入正确的字符?

时间:2013-03-29 21:29:55

标签: c++ winapi command-prompt

为了更好地熟悉C ++,我正在重做旧的大学操作系统任务:编写自己的shell。我解决的第一件事是接受命令,但我的方法留下了一些需要的功能。这就是我所拥有的:

string GetLine() {
    string line;
    char input = _getch();
    while (input != 13) {
        switch (input) {
        case 8: // backspace
            if (line.length() != 0) {
                line = line.substr(0, line.length() - 1);
                cout << "\b \b";
            }
            break;
        case -32: // all arrows' first byte
            input = _getch(); // distinctly different arrow byte
            switch (input) {
                case 72: // up
                    break;
                case 80: // down
                    break;
                case 75: // left
                    break;
                case 77: // right
                    break;
            }
            break;
        case 9: // tab
            break;
        default:
            line += input;
            cout << input;
            break;
        }
        input = _getch();
    }
    cout << endl;
    return line;
}

它工作得很好,我知道我更多地使用箭头键(如果我甚至正确地区分它们)。我要问的主要问题是光标已经包裹到终端上的下一行的某种情况。旨在模拟cmd.exe我打印一个提示并在结束时等待用户的输入。当此提示很长时,在我的命令跨越两行之前只需要几个字符。如果我只是输入它并让它环绕并按回车一切正常。如果我换行到第二行并想要退回到第一行,则光标停在它新行的第一个字符处,并且不会像我希望的那样“解包”回到第一行。我可以在这做什么来实现这种展开行为?

我认为问题在于尝试打印'\ b'不会打开包装,但我不知道替代方案,我希望我不必将此作为特殊情况处理将在行中间退格的代码也将在行的开头处起作用。

1 个答案:

答案 0 :(得分:1)

你需要使用winapi,SetConsoleCursorPosition会帮助你。这是一个将光标从当前位置向上移动一行的最小示例:

#include <iostream>
#include <windows.h> 

int main() {
    std::cout << "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
        "aaaaaaaaaaaaaaa";
    HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);

    CONSOLE_SCREEN_BUFFER_INFO csbiInfo; 
    GetConsoleScreenBufferInfo(hStdout, &csbiInfo);
    csbiInfo.dwCursorPosition.Y -= 1; // Move Y coordinate up by one
    SetConsoleCursorPosition(hStdout, csbiInfo.dwCursorPosition);

    std::cin.get();
}

此外,Console Functions包含控制控制台的所有必要功能的完整列表。您将需要在程序中使用这些。

您需要使用CreateConsoleScreenBuffer创建自己的屏幕缓冲区,然后将其设置为缓冲区。然后在处理完所有内容并自行从控制台读取。