Страницы

Поиск по вопросам

четверг, 15 ноября 2018 г.

Получить уже написанный текст в консоль c#

Добрый день. Имеется такая проблема: Пишу консольный чат. Однако есть один неприятный баг: если пользователь пишет сообщение и в этот момент придет сообщение - то уже введенные данные затрутся. Клиент ожидает ввод функцией Console.ReadLine. Вопрос такой: с помощью чего можно получить уже введенные данные и как их вернуть обратно? P.S. Сообщения приходят из одного потока, а функция ввода работает в другом потоке


Ответ

Если использовать обычный построчный ввод/вывод в консоли, то никак.
Но решение есть. Вам придётся самостоятельно управлять положением курсора и позициями для ввода и вывода.
Самый простой вариант - выводить сообщения в верхних строках видимой части буфера консоли, а ввод текста - в нижней.

Как обещал, дополняю подробностями реализации.
Для управления положением курсора в консоли понадобится метод Console.SetCursorPosition(x,y). По умолчанию отображаемый размер экрана консоли 80х25 символов. Но это можно настроить. Правда есть один нюанс: увеличить размер можно на ходу, в любой момент работы программы, а уменьшить только системными настройками консоли перед запуском программы; при этом изменения сделанные по ходу выполнения программы не запоминаются после ее завершения. Система координат стандартная - левый верхний угол имеет координаты (0,0).
Также придется отказаться от Console.Read/Readline в пользу Console.ReadKey(true) для отключения эхо-вывода введенных символов.
Теперь нужно организовать два буфера вывода, один для входящих сообщений, другой для набираемых пользователем, да, вывод того что ввел пользователь делаем тоже руками. Размеры буферов вычисляем так, чтобы при выводе в консоль стандартным Console.Write/WriteLine выведенные строки в окне консоли не перемешались. Буфер создаем на основе StringBuilder с явным указанием размера. Если выводимый текст меньше буфера - дополняем пробелами, чтобы при выводе затереть предыдущий вывод.
Получение сообщений выполняем в отдельный буфер из которого и заполняем буфер вывода последними принятыми сообщениями.
Дальше все достаточно просто, когда поступает новое сообщение ставим курсор в положение (0,0) и выводим полученные сообщения, если пользователь начал набирать сообщение - выводим его текст по мере набора в нижней части экрана, например в положение (0,20). Основной цикл программы сводится к двум действиям - вывод полученных сообщений, если таковые были, и вывод введенного пользователем символа, если пользователь его ввел. В случае много-поточного решения, можно ограничиться проверкой флагов о необходимости вывода и выводу.
В принципе, при определенной доле упорства, можно организовать и сколлинг полученных сообщений, мы же руками обрабатываем нажатые клавиши, так что все в ваших руках.
В целом этой концепции вполне достаточно для реализации в коде, примеры отдельных действий несложно найти в MSDN в описании класса Console

Комментариев нет:

Отправить комментарий