상위 수준 입력 및 출력 함수 사용
Important
이 문서에서는 더 이상 에코시스템 로드맵의 일부가 되지 않는 콘솔 플랫폼 기능에 대해 설명합니다. 이 콘텐츠를 신제품에서 사용하지 않는 것이 좋지만, 무기한 앞으로도 기존 사용을 계속 지원할 것입니다. 선호하는 최신 솔루션은 플랫폼 간 시나리오에서 최대 호환성을 위해 가상 터미널 시퀀스에 중점을 둡니다. 이 디자인 결정에 대한 자세한 내용은 클래식 콘솔과 가상 터미널 문서에서 확인할 수 있습니다.
다음 예제에서는 콘솔 I/O에 대해 상위 수준 콘솔 I/O 함수를 사용합니다. 상위 수준 콘솔 I/O 함수에 대한 자세한 내용은 상위 수준 콘솔 I/O를 참조하세요.
이 예제에서는 ReadFile 및 WriteFile 함수에 대한 첫 번째 호출에 대해 기본 I/O 모드가 처음에 적용된다고 가정합니다. 그런 다음, ReadFile 및 WriteFile에 대한 두 번째 호출에 대해 입력 모드가 오프라인 입력 모드 및 에코 입력 모드를 끄도록 변경됩니다. SetConsoleTextAttribute 함수는 이후에 작성된 텍스트가 표시되는 색을 설정하는 데 사용됩니다. 종료하기 전에 프로그램은 원래 콘솔 입력 모드 및 색 특성을 복원합니다.
이 예제의 NewLine
함수는 줄 입력 모드를 사용하지 않도록 설정할 때 사용됩니다. 커서 위치를 다음 행의 첫 번째 셀로 이동하여 캐리지 리턴을 처리합니다. 커서가 콘솔 화면 버퍼의 마지막 행에 이미 있는 경우 콘솔 화면 버퍼의 내용이 한 줄 위로 스크롤됩니다.
#include <windows.h>
void NewLine(void);
void ScrollScreenBuffer(HANDLE, INT);
HANDLE hStdout, hStdin;
CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
int 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;
// Get handles to STDIN and STDOUT.
hStdin = GetStdHandle(STD_INPUT_HANDLE);
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdin == INVALID_HANDLE_VALUE ||
hStdout == INVALID_HANDLE_VALUE)
{
MessageBox(NULL, TEXT("GetStdHandle"), TEXT("Console Error"),
MB_OK);
return 1;
}
// Save the current text colors.
if (! GetConsoleScreenBufferInfo(hStdout, &csbiInfo))
{
MessageBox(NULL, TEXT("GetConsoleScreenBufferInfo"),
TEXT("Console Error"), MB_OK);
return 1;
}
wOldColorAttrs = csbiInfo.wAttributes;
// Set the text attributes to draw red text on black background.
if (! SetConsoleTextAttribute(hStdout, FOREGROUND_RED |
FOREGROUND_INTENSITY))
{
MessageBox(NULL, TEXT("SetConsoleTextAttribute"),
TEXT("Console Error"), MB_OK);
return 1;
}
// Write to STDOUT and read from STDIN by using the default
// modes. Input is echoed automatically, and ReadFile
// does not return until a carriage return is typed.
//
// The default input modes are line, processed, and echo.
// The default output modes are processed and wrap at EOL.
while (1)
{
if (! WriteFile(
hStdout, // output handle
lpszPrompt1, // prompt string
lstrlenA(lpszPrompt1), // string length
&cWritten, // bytes written
NULL) ) // not overlapped
{
MessageBox(NULL, TEXT("WriteFile"), TEXT("Console Error"),
MB_OK);
return 1;
}
if (! ReadFile(
hStdin, // input handle
chBuffer, // buffer to read into
255, // size of buffer
&cRead, // actual bytes read
NULL) ) // not overlapped
break;
if (chBuffer[0] == 'q') break;
}
// Turn off the line input and echo input modes
if (! GetConsoleMode(hStdin, &fdwOldMode))
{
MessageBox(NULL, TEXT("GetConsoleMode"), TEXT("Console Error"),
MB_OK);
return 1;
}
fdwMode = fdwOldMode &
~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
if (! SetConsoleMode(hStdin, fdwMode))
{
MessageBox(NULL, TEXT("SetConsoleMode"), TEXT("Console Error"),
MB_OK);
return 1;
}
// ReadFile returns when any input is available.
// WriteFile is used to echo input.
NewLine();
while (1)
{
if (! WriteFile(
hStdout, // output handle
lpszPrompt2, // prompt string
lstrlenA(lpszPrompt2), // string length
&cWritten, // bytes written
NULL) ) // not overlapped
{
MessageBox(NULL, TEXT("WriteFile"), TEXT("Console Error"),
MB_OK);
return 1;
}
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;
}
// Restore the original console mode.
SetConsoleMode(hStdin, fdwOldMode);
// Restore the original text colors.
SetConsoleTextAttribute(hStdout, wOldColorAttrs);
return 0;
}
// The NewLine function handles carriage returns when the processed
// input mode is disabled. It gets the current cursor position
// and resets it to the first cell of the next row.
void NewLine(void)
{
if (! GetConsoleScreenBufferInfo(hStdout, &csbiInfo))
{
MessageBox(NULL, TEXT("GetConsoleScreenBufferInfo"),
TEXT("Console Error"), MB_OK);
return;
}
csbiInfo.dwCursorPosition.X = 0;
// If it is the last line in the screen buffer, scroll
// the buffer up.
if ((csbiInfo.dwSize.Y-1) == csbiInfo.dwCursorPosition.Y)
{
ScrollScreenBuffer(hStdout, 1);
}
// Otherwise, advance the cursor to the next line.
else csbiInfo.dwCursorPosition.Y += 1;
if (! SetConsoleCursorPosition(hStdout,
csbiInfo.dwCursorPosition))
{
MessageBox(NULL, TEXT("SetConsoleCursorPosition"),
TEXT("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 - (SHORT)x;
srctScrollRect.Bottom = csbiInfo.dwSize.Y - (SHORT)x;
// The destination for the scroll rectangle is one row up.
coordDest.X = 0;
coordDest.Y = 0;
// The clipping rectangle is the same as the scrolling rectangle.
// The destination row is left unchanged.
srctClipRect = srctScrollRect;
// Set the fill character and attributes.
chiFill.Attributes = FOREGROUND_RED|FOREGROUND_INTENSITY;
chiFill.Char.AsciiChar = (char)' ';
// Scroll up one line.
ScrollConsoleScreenBuffer(
h, // screen buffer handle
&srctScrollRect, // scrolling rectangle
&srctClipRect, // clipping rectangle
coordDest, // top left destination cell
&chiFill); // fill character and color
}