Изменение размеров буфера консольного окна

SetConsoleScreenBufferSize: изменение размеров буфера консольного окнаПривет! Это второй пост, который был потерян когда-то в июле в связи с переездом на другой хостинг.
Речь пойдёт о так называемом Screen Buffer.
Консольное окно само по себе имеет определенные размеры, обычно 24 на 80 символов.

Также справа есть полоса прокрутки, с помощью неё можно увидеть то, что вышло за рамки экрана, так как когда мы всё пишем и пишем, например с помощью процедуры writeln, доходим до строки номер 24 и пишем дальше, то всё сдвигается. Или когда с помощью api функции SetConsoleCursorPosition или через GotoXY из модуля crt для delphi ставим курсор на место, расположенное ниже досягаемого нами пространства.
Всё, что можно увидеть с помощью прокрутки, и есть Screen Buffer.

Чтобы поменять его размеры, нужно познакомиться с ним поближе.

Что нам о нём известно?

Его размеры можно получить с помощью api функции GetConsoleScreenBufferInfo, вот её синтаксис:

function GetConsoleScreenBufferInfo(hConsoleOutput: THandle; var lpConsoleScreenBufferInfo: TConsoleScreenBufferInfo): BOOL;

По порядку:
hConsoleOutput: THandle — handle вывода консольного окна, его нам вернёт api функция GetStdHandle с параметром STD_OUTPUT_HANDLE;
lpConsoleScreenBufferInfo: TConsoleScreenBufferInfo — сюда передаём объект типа TConsoleScreenBufferInfo

Структура CONSOLE_SCREEN_BUFFER_INFO, она же TConsoleScreenBufferInfo, она же _CONSOLE_SCREEN_BUFFER_INFO:

  _CONSOLE_SCREEN_BUFFER_INFO = packed record
    dwSize: TCoord;
    dwCursorPosition: TCoord;
    wAttributes: Word;
    srWindow: TSmallRect;
    dwMaximumWindowSize: TCoord;
  end;

Функция GetConsoleScreenBufferInfo её нам заполнила, что мы получили:
dwSize: TCoord — размер буфера, вот он! (по умолчанию 80 на 300 символов)
dwCursorPosition: TCoord — положение курсора, тоже полезно, вполне заменит паскалевские WhereX и WhereY, они также реализованы в моём модуле crt
wAttributes: Word — не экспериментировал с этим, вроде цвета
srWindow: TSmallRect — тоже не экспериментировал, по msdn это координаты окна, уточни какого и напиши в комментарии, ок?
dwMaximumWindowSize: TCoord — максимальный размер буфера, в символах, естественно.

Меняем размер Screen Buffer

Ну и кульминация, функция SetConsoleScreenBufferSize:

SetConsoleScreenBufferSize(hConsoleOutput: THandle; dwSize: TCoord): BOOL;

Передаём тот же handle вывода, и структуру TCoord с нужным нам размером.

Как же без примера?

const
  NewSize: TCoord = (x: 80; y: 10000);

...
  SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), NewSize);

Здесь размер буфера окна стал 80 на 10000.

Постовой:
А тем временем Zdez Bil Ya в своём добром-добром блоге пишет про delphi и пароли в qip.

16 ответов к «Изменение размеров буфера консольного окна»

  1. Эх помню писал когда-то на Delphi… но потом забил на кодинг и вообще считалось что Delphi скоро умрет. Ан нет — живее всех живых. Что не может не радовать.

  2. Статья конечно ничего. Если бы не 2 НО.
    1) В JCL есть прекрасный класс, инкапсулирующий работу с консолью
    2) Само по себе изменение размера буфера собственно и не нужно, ну разве что для каких-то текстовых интерфейсов в стиле Turbo Vision. А для обычных программ с writeln обычного буфера хватает по уши.

  3. wAttributes — это цветовой атрибут, т.е. цвет символа плюс цвет фона. Для него в модуле windows.pas есть цветовые константы, с помощью которых легко составить свой цветовой атрибут, например:
    wAttribute:=FOREGROUND_GREEN+BACKGROUND_BLUE //Зелёные буквы на синем фоне
    Константами определены только цвета красный, зелёный, синий (RGB), остальные цвета составляются из комбинации этих самых RGB. :)

  4. Неплохой пример/перевод help’а win32, только есть риторический вопрос.
    Зачем под Delphi Писать Консольное Приложение?
    Просто интересно :)

    1. Как по мне, так это удобно реализовать диалог с пользователем или поэтапный вывод информации.
      А иногда, когда пишешь на коленке, не очень хочется заморачиваться с компонентами, хочется написать writeln и всё, но это другой случай :)
      А если важен размер программы, то тут тоже выбор невелик — или на winapi делать форму, компоненты, или написать {$apptype console} и радоваться жизни

  5. Если не секрет, зачем это надо?

    Если подразумевается большой вывод в МОЕЙ программе — он идет в файл.
    Если мне надо сохранить вывод ЧУЖОЙ программы — я его в файл перенаправляю.

    Есть конкретный пример применения этой возможности?

    1. Когда я копался с сокетами, я выводил ответ от сервера в консоль, а так как потом идёт html-код, то само тело ответа, которое перед ним, уходило в небытие. Конечно, я мог писать в файл, но так удобнее, так как и файл искать не нужно, и открывать лишний раз тоже.
      А если глобально, то изначально я начал копать в эту сторону по просьбе одного человека, который делал то ли курсовую, то ли еще какую научную работу, в общем, требовалось вывести много строк. Кстати, по сравнению с TMemo это и быстрее и удобней.

  6. Сразу видно большинство комментаторов очень юны. Все еще думают что есть только одно единственно-правильное решения — то что они используют, но как не обидно никто из нас не совершенство, да и путей решений редко бывает только одно единственное… Это так лирическое отступление.

    Что касается буфера, помню обсуждали прошлой весной, по-моему. Я разрабатывал интерпретатор паскале-подобного языка. И нужно было выводить очень много статистической информации: результаты лексического и синтаксического анализов, кода виртуальной машины, результатов работы интерпретатора, хеш-таблицы переменных скрипта… И как понимаете стандартного размера буфера для этого не всегда хватает. Появилась необходимость увеличить размера буфера. Эта необходимость вылилась в беседу с crystalbit, а после в ту самую статью что вы только что прочитали.

  7. а я не согласен, что всё по детски, блог мне нравится, очень толково написаны статьи, во всяком случае мне интересно(не все»серьёзные» блоги могут похвастаться таким интересом со стороны посетителей)

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *