Окно консоли и экранный буфер
И в заключение обсуждения особенностей работы с консольными приложениями поясним, что представляет собой экранный буфер консоли и какие средства представляет API Win32 для работы с ним.
Для того чтобы читатель мог легко понять соотношение понятий "окно консоли" и "экранный буфер консоли", представьте себе офисный календарь, на котором текущее число отмечается квадратной рамкой, закрепленной на прозрачной целлофановой ленте и перемещающейся вдоль нее. Теперь представим, что содержимое листа календаря вне этой рамки невидимо, то есть доступно только через окошко, которое образует рамка. Для того чтобы увидеть содержимое всего листа календаря, необходимо двигать рамку. В контексте этой ассоциации – лист календаря – это экранный буфер, а площадь внутри рамки – окно консоли, то есть видимая часть экранного буфера.
Возможна поддержка нескольких экранных буферов, связанных с данной консолью, но только один из них может подвергаться отображению в окне консоли – его называют активным экранным буфером. Другие экранные буферы, если они были созданы, являются неактивными. Для создания экранного буфера используется функция CreateConsoleScreenBuffer. К неактивным экранным буферам можно обращаться для чтения и записи, но отображаться в окне консоли будет только активный экранный буфер (или его часть). Для того чтобы сделать экранный буфер активным, используется функция SetConsoleActiveScreenBuffer. Функция CreateConsoleScreenBuffer имеет показанный ниже формат.
HANDLE CreateConsoleScreenBuffer(DWORD dwDesiredAccess, DWORD dwShareMode, CONST LPSECURITY_ATTRIBUTES ipSecurityAttributes. DWORD dwFlags. LPVOID lpScreenBufferData):
Параметры функции:
- dwDesiredAccess – определяет желаемый тип доступа к экранному буферу консоли, этот параметр может быть либо одним из следующих значений либо их комбинацией:
- GENERIC_READ=80000000h – запрашивается доступ по чтению к экранному буферу консоли для того, чтобы разрешить процессу прочитать данные из буфера;
- GENERIC_WRITE=40000000h – запрашивается доступ для записи к экранному буферу консоли для того, чтобы разрешить процессу записать данные в буфер;
- dwShareMode – определяет возможность разделения этого экранного буфера консоли; нулевое значение этого параметра указывает, что буфер не может быть разделен, ненулевое состояние этого буфера может быть одним из следующих значений или их комбинацией:
- FILESHAREREAD – другие операции открытия могут быть выполнены для экранного буфера консоли с доступом для чтения;
- FILESHAREWRITE – другие операции открытия могут быть выполнены для экранного буфера консоли с доступом для записи;
- IpSecurityAttributes – указатель на структуру SECURITY_ATTRIBUTES, которая определяет, может ли возвращаемый функцией CreateConsoleScreenBuffer дескриптор наследоваться дочерними процессами – если lpSecurityAttributes=NULL, то дескриптор не может быть унаследован;
- dwFlags – определяет тип создаваемого экранного буфера консоли, в настоящее время поддерживается только один такой тип – CONSOLE_TEXTMODE_ BUFFER=1;
- lpScreenBufferData – зарезервирован и должен быть равен NULL.
Функция CreateConsoleScreenBuffer формирует дескриптор созданного экранного буфера, который затем используется функциями для доступа к этому буферу.
Для того чтобы сделать буфер активным, используют функцию SetConsoleActiveScreenBuffer.
B00L SetConsoleActiveScreenBuffertHANDLE hConsoleOutput):
Функция имеет единственный параметр – hConsoleOutput – дескриптор экранного буфера, созданного функцией CreateConsoleScreenBuffer. Как уже было отмечено, консоль может иметь много экранных буферов. Функция SetConsoleActiveScreenBuffer определяет, какой из них будет отображен. Приложение может производить запись в неактивный экранный буфер и затем использовать функцию SetConsoleActiveScreenBuffer для отображения содержимого буфера.
Чтение и запись в неактивный (и активный тоже) экранный буфер производится функциями низкоуровневого ввода-вывода – WriteConsoleOutputNWriteConsoleOutputCharacter и ReadConsoleOutput\ReadConsoleOutputCharacter, которым при вызове передается дескриптор нужного экранного буфера, полученного предварительно функцией CreateConsoleScreenBuffer.
Каждый из созданных экранных буферов поддерживает собственный текущий прямоугольник окна, определяемый координатами верхней левой и нижней правой символьных ячеек, которые будут отображены в окне консоли. Для определения видимого в окне консоли прямоугольника экранного буфера используется функция GetConsoleScreenBufferlnfo.
B00L GetConsoleScreenBufferInfo(HANDLE hConsoleOutput. PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferlnfo);
Параметрами этой функции являются:
- hConsoleOutput – дескриптор экранного буфера, созданного функцией CreateConsoleScreenBuffer; дескриптор должен иметь тип доступа GENERICREAD;
- lpConsoleScreenBufferlnfo – указатель на структуру CONSOLE_SCREEN_BUFFER_ INFO, в которую помещается информация об экранном буфере.