2013-03-29 2 views
-1

Чтобы лучше ознакомиться с C++, я переделываю старое назначение ОС: программируйте свою собственную оболочку. Первое, что я рассматривал, это принятие команд, но мой подход оставляет желать лучшего. Вот что у меня есть:Правильный характер ввода символа?

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' не разворачивается, но у меня нет идеи для альтернативы, и я надеюсь, что мне не нужно рассматривать это как особый случай и этот код, который будет backspace в середине строки, также будет работать в начале строки.

+0

Вы можете использовать libreadline? Это избавит вас от большой боли при работе с этим и имеет целый пакет трюков (например, история команд и т. Д.). –

ответ

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, а затем установить его как буфер сначала. Затем после этого ручка все будет написано и прочитано с консоли самостоятельно.

+0

Это выглядит как мой единственный выбор. –

+0

@CoreyOgburn: В окнах это, наверное, лучший выбор. Unix-подобные системы упрощают работу с терминалами. Еще одна альтернатива - использование [ncurses for windows] (http://gnuwin32.sourceforge.net/packages/ncurses.htm) с функцией [wmove] (http://hughm.cs.ukzn.ac.za/~ murrellh/OS/примечание/ncurses.html # курсор). –

Смежные вопросы