//*************************************************************** // From the book "Win32 System Services: The Heart of Windows 98 // and Windows NT" // by Marshall Brain // Published by Prentice Hall // // Copyright 1995, by Prentice Hall. // // This code shows how to handle raw input from a console so that // you can retrieve input one character at a time. This code also // demonstrates how to use a normal Wait function to wait for // input. //*************************************************************** // raw2.cpp #include #include void ErrorHandler(char *s, DWORD err) { cout << s << endl; cout << "Error number: " << err << endl; ExitProcess(err); } void ScrollOneLine(HANDLE stdout) { BOOL success; CONSOLE_SCREEN_BUFFER_INFO consoleInfo; SMALL_RECT scrollRect; CHAR_INFO consoleFill; COORD coord; // get current console size (may change) success = GetConsoleScreenBufferInfo(stdout, &consoleInfo); if (!success) ErrorHandler( "In GetConsoleScreenBufferInfo", GetLastError()); // Define the rectangle to scroll scrollRect.Top = 0; scrollRect.Left = 0; scrollRect.Bottom = consoleInfo.dwSize.Y - 1; scrollRect.Right = consoleInfo.dwSize.X - 1; // Define destination of scrolled rectangle coord.X = 0; coord.Y = -1; // Define how to fill blank line consoleFill.Attributes = consoleInfo.wAttributes; consoleFill.Char.AsciiChar = ' '; // Perform the scroll success = ScrollConsoleScreenBuffer(stdout, &scrollRect, 0, coord, &consoleFill); if (!success) ErrorHandler("In ScrollConsoleScreenBuffer", GetLastError()); } VOID HandleCR(HANDLE stdout) { CONSOLE_SCREEN_BUFFER_INFO consoleInfo; BOOL success; success = GetConsoleScreenBufferInfo(stdout, &consoleInfo); if (!success) ErrorHandler("In GetConsoleScreenBufferInfo", GetLastError()); // Move cursor to far left consoleInfo.dwCursorPosition.X = 0; // If the cursor is on the last line of // the console, then scroll the console, // else increment position if (consoleInfo.dwSize.Y - 1 == consoleInfo.dwCursorPosition.Y) ScrollOneLine(stdout); else consoleInfo.dwCursorPosition.Y += 1; // Update the console success = SetConsoleCursorPosition(stdout, consoleInfo.dwCursorPosition); if (!success) ErrorHandler("In SetConsoleCursorPosition", GetLastError()); } void ProcessIO(HANDLE consoleStdin, HANDLE consoleStdout) { char buffer; DWORD numRead, numWrite; INPUT_RECORD inputEvent; DWORD s; char *t="waiting\n"; do { // wait for the user to do something do { s = WaitForSingleObject(consoleStdin, 0); } while (s==WAIT_TIMEOUT); // look into the input queue PeekConsoleInput(consoleStdin, &inputEvent, 1, &numRead); if (numRead>0) { // Check the event. If it is unworthy, // then discard the event. Otherwise read // it and handle it normally. if (inputEvent.EventType != KEY_EVENT || inputEvent.Event. KeyEvent.bKeyDown==FALSE || inputEvent.Event.KeyEvent. uChar.AsciiChar==0) { ReadConsoleInput(consoleStdin, &inputEvent, 1, &numRead); } else { ReadFile(consoleStdin, &buffer, 1, &numRead, NULL); if (buffer == '\r') HandleCR(consoleStdout); else WriteFile(consoleStdout, &buffer, 1, &numWrite, NULL); } } } while (buffer != 'X'); } VOID main(void) { DWORD oldMode, newMode; BOOL success; HANDLE stdout, stdin; // Get handles for standard in and out stdin = GetStdHandle(STD_INPUT_HANDLE); stdout = GetStdHandle(STD_OUTPUT_HANDLE); if (stdin == stdout) //they must be invalid ErrorHandler("In GetStdHandle", GetLastError()); // Get current console mode so can modify it success = GetConsoleMode(stdin, &oldMode); if (!success) ErrorHandler("In GetConsoleMode", GetLastError()); newMode = oldMode & ~ENABLE_LINE_INPUT & ~ENABLE_ECHO_INPUT; success = SetConsoleMode(stdin, newMode); if (!success) ErrorHandler("In SetConsoleMode", GetLastError()); // Process user I/O ProcessIO(stdin, stdout); // put the old mode back success = SetConsoleMode(stdin, oldMode); if (!success) ErrorHandler("In SetConsoleMode", GetLastError()); }