Как мне создать пользовательскую графическую консоль / терминал в Windows? - PullRequest
30 голосов
/ 22 февраля 2012

Интерфейс консоли Windows (кажется, окно cmd) представляет собой довольно простой графический интерфейс пользователя. Однако уровень эффективности, с которым он обрабатывает рендеринг, пользовательский ввод и прокрутку, очень высок. Методы, использованные для создания этого интерфейса, несомненно, сильно отличаются от традиционных графических интерфейсов настольных компьютеров.

Я заинтересован в создании собственной настраиваемой консоли / терминала для Windows, предпочтительно с использованием технологий на C # и .NET (например, управляемого GDI + или WPF). В качестве отправной точки я бы просто хотел воссоздать стандартную простую оболочку Windows. Я мог бы тогда расширить вещи и добавить функции оттуда.

Я ищу общее руководство по созданию такого интерфейса консоли, но некоторые конкретные моменты включают в себя:

  • Какую модель рендеринга я должен использовать? Цикл рендеринга? Частичные обновления (например, WPF)? Модель WinForms (не знаю, как это работает)?

  • Какой тип кэширования используется в модели рендеринга?

  • Как загружаются шрифты и как они отображаются? Это стандартные шрифты TrueType, растровые шрифты или что-то еще?

  • Как прокрутка выполняется так эффективно?

  • Все, что вы считаете актуальным!

Любое объяснение того, как встроенный пользовательский интерфейс консоли Windows (или даже превосходящий пользовательский интерфейс терминала Linux) делает эти вещи - и как я мог их эмулировать - было бы на самом деле идеальным.

Редактировать: Чтобы было ясно, я действительно хочу сделать это полностью с нуля. Основан на графической структуре, такой как GDI + или WPF, но не более.

Ответы [ 7 ]

20 голосов
/ 28 февраля 2012

Я однажды реализовал окно вывода текста с нуля - я хотел, чтобы оно работало подобно окну вывода в Visual Studio.Это оказалось сложнее, чем я ожидал, и это было без каких-либо возможностей ввода.

К сожалению, код на C ++ и принадлежит бывшему работодателю, поэтому я не могу поделиться им с вами.Но я могу дать вам представление о том, чего ожидать.

Вам нужен способ хранить строки вывода, которые вы можете быстро проиндексировать.Если вы собираетесь наложить ограничение на количество отображаемых строк, вам также необходимо будет легко удалить строки сверху.В C ++ deque<string> был идеальным, я не знаю, каков эквивалент (если есть) в C #.

Вам понадобятся обработчики для следующих сообщений Windows, в произвольном порядке.

  • WM_LBUTTONDOWN - начать выбор.Используйте SetCapture для отслеживания мыши, когда кнопка нажата.
  • WM_LBUTTONUP - для завершения выбора.
  • WM_RBUTTONUP - перевод в WM_CONTEXTMENU.
  • WM_CONTEXTMENU - для отображения меню сКопировать / вырезать / вставить и все, что вы хотите.
  • WM_KEYDOWN - чтобы ответить на 4 клавиши курсора, Home / End, PageUp / PageDown.Ctrl-A / Ctrl-C / Ctrl-X / Ctrl-V / Ctrl-D.
  • WM_PAINT - рисовать содержимое окна.
  • WM_SIZE - обновлять полосы прокрутки, когдаизменяется размер окна.
  • WM_VSCROLL - для обновления видимой части окна при вертикальной прокрутке.
  • WM_HSCROLL - для обновления видимой части окна при горизонтальной прокрутке.
  • WM_CREATE - для инициализации при создании окна.
  • WM_SETFOCUS - для создания системной каретки для отображения текущей позиции в окне.
  • WM_KILLFOCUS - для уничтожения каретки, поскольку только в текущем окнедолжен показывать символ каретки.
  • WM_MOUSEMOVE - отслеживать изменения выбора, когда левая кнопка мыши нажата.
  • WM_CAPTURECHANGED - завершать выбор.
  • WM_TIMER - для автоматического-croll, когда курсор покидает окно во время выделения.
  • WM_GETDLGCODE - чтобы добавить DLGC_WANTARROWS, чтобы клавиши со стрелками проходили.
  • WM_MOUSEWHEEL -чтобы прокрутить колесико мыши для прокрутки.

По мере добавления строк в текстовый буфер настройте диапазон полос прокрутки.Диапазон вертикальной полосы прокрутки будет общим числом строк, а диапазон горизонтальной полосы прокрутки будет шириной самой широкой строки.

Лучше всего иметь один шрифт, который является моноширинным - это значительно усложняет вычисления.Полегче.Технология специальных шрифтов не имеет большого значения.Вам просто нужно иметь возможность отслеживать положение символов.

Как прокрутка выполняется так эффективно?Вы отслеживаете верхнюю и нижнюю линии окна по мере его прокрутки, а когда появляется сообщение о рисовании, вы рисуете только те линии, которые в данный момент видны.Другие все еще в буфере, но они не трогают.Можно прокручивать содержимое окна, когда оно прокручивается, и рисовать только те части, которые входят сверху или снизу, но с современными процессорами это напрасная трата - окно выполнит полную перерисовку так быстро, что вы не заметите.

Редактировать: По совпадению я наткнулся на это руководство Microsoft по полосам прокрутки, которые должны быть важными для чтения этой задачи.http://msdn.microsoft.com/en-us/library/windows/desktop/bb787527.aspx

8 голосов
/ 01 марта 2012

Если вы хотите создать красивую замену командной строки на основе .NET, тогда я предлагаю взглянуть на http://poshconsole.codeplex.com/ Он использует WPF для графических элементов и реализует хост скрипта PowerShell.PowerShell - это замена Microsoft почтенной командной строке.PowerShell по умолчанию устанавливается вместе с Windows 7, но вы можете загрузить его для XP и Vista.PowerShell обладает широкими возможностями расширения, но позволяет напрямую использовать объекты .NET.Он также может быть встроен в другие программы.

WPF + PowerShell будет отличной отправной точкой для того, что вы хотите сделать.Если вы хотите, вы можете заменить PowerShell на собственный движок команд / скриптов.Если бы вы были действительно амбициозны, вы могли бы попытаться внедрить свой собственный язык сценариев в DLR, чтобы действовать как ваш командный интерпретатор.

Удачи.

4 голосов
/ 29 февраля 2012

Взгляните на Консоль проект с открытым исходным кодом. Это делает много, и делает это очень хорошо. Он предоставляет унифицированную консоль для всего, что основано на символах. Я запускаю cmd, bash и python в каждой вкладке.

Он написан на C ++ и, тем не менее, не даст вам удовольствия написать его самостоятельно.

3 голосов
/ 28 февраля 2012

Если скорость имеет первостепенное значение, то XNA - это очень быстрый способ (минимальное кодирование) для рисования текста с высокой скоростью.Он может обрабатывать тысячи спрайтов со скоростью 100 кадров в секунду.Используя SpriteBatch :: DrawString () и SpriteFont, вы можете получить высокоскоростную «консоль» с минимальными усилиями по написанию кода.Стандартный класс «Игры» можно изменить, чтобы по требованию перерисовывать только субрегионы экрана.Предостережения включают несовершенный кернинг, который придает тексту размытый вид (вы можете исправить это, отключив сглаживание и следя за тем, чтобы ваши проекции и размещение спрайтов были осторожны).Если это проблема, то, возможно, Direct2D предлагает лучшее решение (или любое из уже упомянутых решений).

3 голосов
/ 28 февраля 2012

У меня был большой успех с RichTextBox для вывода.На самом деле он делает все, что вы пожелаете: настройка цвета, эффективный рендеринг и прокрутка, операции с буфером обмена и т. Д. Ввод был организован путем перехвата событий окна KeyPress.

2 голосов
/ 22 февраля 2012

В качестве первого и простого подхода я бы использовал TextBox в многострочном режиме. Следите за событиями TextChanged или KeyPressed или KeyUp и действуйте соответственно. Позже вы можете создать свой собственный элемент управления, например, получая его из простого Panel элемента управления. Рендеринг происходит путем переопределения метода OnPaint (WinForms). Цикл не требуется, просто вызов Invalidate или Refresh.

Используйте строковый массив или List<string> или LinkedList<string> в качестве буфера строки или просто используйте текст, хранящийся в текстовом поле.

Если вы создаете свой собственный элемент управления с помощью WinForms, System.Windows.Forms.TextRenderer является хорошим выбором для рендеринга текста. Будет использоваться в OnPaint.

Прокрутка - это сложная вещь, если вы создаете собственный контроль. System.Windows.Controls.Panel уже содержит поддержку прокрутки, однако вы все равно должны указать элементу управления, как размещать и изменять размер кнопок полосы прокрутки при изменении текста. С другой стороны, вы должны перемещать текст, когда пользователь перемещает полосы прокрутки, и соответственно обновлять отображение. Производительность не должна быть проблемой для такого простого управления.

1 голос
/ 01 января 2018

FastColoredTextBox проект на github имеет пример Console .Это:

  • Эффективно и быстро
  • Цветной
  • Доступно в WPF и WinForm
  • На C # и легко читается

Я думаю, что чтение кода вам очень поможет.

...