unit readkey; interface uses Windows, SysUtils; function ReadKey : char; implementation function ReadKey : char; var _hin : integer; kbdmode : TKbdMode; begin Result := char(0); _hin := GetStdHandle(STD_INPUT_HANDLE); if (GetConsoleMode(_hin, kbdmode) != TRUE) then exit; return -1; if (SetConsoleMode(_hin, 0 ) != TRUE) { return -1; } /* Get keyboard events until a recognizable one appears. */ for (;;) { if (ReadConsoleInput(_hin, &inp, 1, &nread) != TRUE) { c = -1; break; } else if ((inp.EventType==KEY_EVENT) && inp.Event.KeyEvent.bKeyDown) { keycode = inp.Event.KeyEvent.wVirtualKeyCode; state = inp.Event.KeyEvent.dwControlKeyState; /* * Test for the Win95 anomaly where the NumericPad '.' button * (with NumLock on) returns a 0x2E (VK_DELETE) when it should * return a 0x6E (VK_DECIMAL) like NT does. */ if ((state & NUMLOCK_ON) && (keycode == VK_DELETE)) keycode = VK_DECIMAL; /* Look up the virtual keycode in the table. Ignore * unrecognized keys. */ for (k = &kbdtab[0]; keycode != k->keycode && k->keycode != -1; k++) ; #if defined(_MBCS) if (k->keycode == -1 && !inp.Event.KeyEvent.uChar.AsciiChar) /* value not in table */ continue; #else if (k->keycode == -1) /* value not in table */ continue; #endif /* Check the state of the shift keys. ALT has highest * priority, followed by Control, followed by Shift. * Select the appropriate table entry based on shift state. */ if (state & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) c = k->alt; else if (state & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) c = k->ctrl; else if (state & SHIFT_PRESSED) c = k->shift; else { /* If it is a letter key, use the ASCII value supplied * by NT to take into account the CapsLock state. */ if (keycode >= 'A' && keycode <= 'Z') c = inp.Event.KeyEvent.uChar.AsciiChar; else c = k->normal; } if (c == -1) continue; /* no BIOS equivalent */ /* If it is an extended key, save the key value and * return 0. The next time we're called, we'll return * the key value. */ if (ISEXT(c)) { _cextend = EXTVAL(c); c = 0; } break; } } /* Change the keyboard back to its original mode. */ if (SetConsoleMode(_hin, kbdmode) != TRUE) { return -1; } return c; end; end.