Использование высокоуровневых функций ввода и вывода
Нижеследующий пример использует высокоуровневые консольные функции I/O для консольного ввода - вывода. Для получения дополнительной информации о высокоуровневых консольных функциях I/O, см. статью Высокоуровневый консольный ввод - вывод I/O).
В примере предполагается, что заданные по умолчанию режимы ввода - вывода (I/O) являются по существу вначале для первого вызова функций ReadFile и WriteFile. Затем для второго вызова ReadFile и WriteFile режим ввода данных изменяется, выключается режим построчного ввода данных и отраженный режим ввода данных. Функция SetConsoleTextAttribute используется для, установки цвета, которым впоследствии письменный текст будет показан на экране. Перед выходом, программа восстанавливает исходный консольный режим ввода данных и атрибуты цвета.
Функция NewLine примера используется тогда, когда отключается режим построчного ввода данных. Она обрабатывает возвраты каретки, перемещая позицию курсора в первую ячейку следующей строки. Если курсор находится уже в последней строке экранного буфера консоли, содержание экранного буфера консоли прокручивается вверх на одну строку.
|
Обратите внимание! на то, что MyErrorExit - групповой символ - заместитель для определяемой программой функции, которая показывает на экране и обрабатывает аварийные ситуации. |
#include <windows.h>
void NewLine(void);
void ScrollScreenBuffer(HANDLE, INT);
HANDLE hStdout, hStdin;
CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
void main(void)
{
LPSTR lpszPrompt1 = "Type a line and press Enter, or q to quit: ";
LPSTR lpszPrompt2 = "Type any key, or q to quit: ";
CHAR chBuffer[256];
DWORD cRead, cWritten, fdwMode, fdwOldMode;
WORD wOldColorAttrs;
// Получим дескрипторы для STDIN и STDOUT.
hStdin = GetStdHandle(STD_INPUT_HANDLE);
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdin == INVALID_HANDLE_VALUE || hStdout == INVALID_HANDLE_VALUE)
{
MessageBox(NULL, "GetStdHandle", "Console Error", MB_OK);
return;
}
// Сохраним текущий цвет текста.
if (! GetConsoleScreenBufferInfo(hStdout, &csbiInfo))
{
MessageBox(NULL, "GetConsoleScreenBufferInfo", "Console Error", MB_OK);
return;
}
wOldColorAttrs = csbiInfo.wAttributes;
// Установим атрибуты текста которые пишут красный текст по черному фону.
if (! SetConsoleTextAttribute(hStdout, FOREGROUND_RED|FOREGROUND_INTENSITY))
{
MessageBox(NULL, "SetConsoleTextAttribute", "Console Error", MB_OK);
return;
}
// Запишем в STDOUT и прочитаем из STDIN, используя режим по умолчанию.
// При вводе данных эхо-режим осуществляется автоматически, а функция ReadFile
// не возвращает значения до тех пор, пока не напечатается каретка возврата.
//
// Режим ввода по умолчанию - построчный, обрабатываемый и эхо-режим.
// Режим вывода по умолчанию - обрабатываемый и с автопереносом в конце строки EOL.
while (1)
{
if (! WriteFile(
hStdout, // дескриптор вывода
lpszPrompt1, // строка приглашения к вводу
lstrlen(lpszPrompt1), // длина строки
&cWritten, // записано байтов
NULL) ) // не перекрывающееся
{
MessageBox(NULL, "WriteFile", "Console Error", MB_OK);
return;
}
if (! ReadFile(
hStdin, // дескриптор ввода
chBuffer, // буфер для передачи
255, // размер буфера
&cRead, // действительно прочитанные байты
NULL) ) // не перекрывающееся
break;
if (chBuffer[0] == 'q')
break;
}
// Выключим построчный режим ввода и эхо-режим.
if (! GetConsoleMode(hStdin, &fdwOldMode))
{
MessageBox(NULL, "GetConsoleMode", "Console Error", MB_OK);
return;
}
fdwMode = fdwOldMode & ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
if (! SetConsoleMode(hStdin, fdwMode))
{
MessageBox(NULL, "SetConsoleMode", "Console Error", MB_OK);
return;
}
// Без эхо-режима и построчного ввода, ReadFile возвращает значение,
// когда доступен какой либо ввод данных. Возврат каретки должен
// обрабатываться, а WriteFile используется в эхо-режиме для ввода данных.
NewLine();
while (1)
{
if (! WriteFile(
hStdout, // дескриптор вывода
lpszPrompt2, // строка приглашения к вводу
lstrlen(lpszPrompt2), // длина строки
&cWritten, // записано байтов
NULL) ) // не перекрывающееся
{
MessageBox(NULL, "WriteFile", "Console Error", MB_OK);
return;
}
if (! ReadFile(hStdin, chBuffer, 1, &cRead, NULL))
break;
if (chBuffer[0] == '\r')
NewLine();
else if (! WriteFile(hStdout, chBuffer, cRead,
&cWritten, NULL))
break;
else
NewLine();
if (chBuffer[0] == 'q')
break;
}
// Восстанавливаем исходный режим консоли.
SetConsoleMode(hStdin, fdwOldMode);
// Восстанавливаем исходный режим текста.
SetConsoleTextAttribute(hStdout, wOldColorAttrs);
}
// Функция NewLine обрабатывает возврат каретки тогда, когда режим обработки
// вводимых данных отключается. Она получает текущую позицию курсора
// и сбрасывает ее до позиции первой ячейки следующей строки.
void NewLine(void)
{
if (! GetConsoleScreenBufferInfo(hStdout, &csbiInfo))
{
MessageBox(NULL, "GetConsoleScreenBufferInfo", "Console Error", MB_OK);
return;
}
csbiInfo.dwCursorPosition.X = 0;
// Если это последняя строка в буфере экрана, прокручивает буфер вверх.
if ((csbiInfo.dwSize.Y-1) == csbiInfo.dwCursorPosition.Y)
{
ScrollScreenBuffer(hStdout, 1);
}
// Иначе, продвигает вперед курсор к следующей строке
else csbiInfo.dwCursorPosition.Y += 1;
if (! SetConsoleCursorPosition(hStdout,
csbiInfo.dwCursorPosition))
{
MessageBox(NULL, "SetConsoleCursorPosition", "Console Error", MB_OK);
return;
}
}
void ScrollScreenBuffer(HANDLE h, INT x)
{
SMALL_RECT srctScrollRect, srctClipRect;
CHAR_INFO chiFill;
COORD coordDest;
srctScrollRect.Left = 0;
srctScrollRect.Top = 1;
srctScrollRect.Right = csbiInfo.dwSize.X - x;
srctScrollRect.Bottom = csbiInfo.dwSize.Y - x;
// Назначение для прямоугольника прокрутки - одна строка вверх coordDest.X = 0;
coordDest.Y = 0;
// Прямоугольник отсечения по границам тот же самый, что и прокручивающийся прямоугольник. // Строка назначения оставлена неизменной
srctClipRect = srctScrollRect;
// Установим символ - заполнитель и атрибуты
chiFill.Attributes = FOREGROUND_RED|FOREGROUND_INTENSITY;
chiFill.Char.AsciiChar = ' ';
// Прокрутим вверх на одну строку.
ScrollConsoleScreenBuffer(
h, // дескриптор экранного буфера
&srctScrollRect, // прямоугольник прокрутки
&srctClipRect, // прямоугольник отсечения
coordDest, // верхняя левая ячейка назначения
&chiFill); // символ-заполнитель и цвет
}
|