public static unsafe extern bool WriteConsoleOutput( IntPtr hConsoleOutput, CHAR_INFO *lpBuffer, //CHAR_INFO SMALL_COORD dwBufferSize, SMALL_COORD dwBufferCoord, SMALL_RECT *lpWriteRegion );
internal static unsafe extern bool WriteConsoleOutput(IntPtr hConsoleOutput, CHAR_INFO *buffer, COORD bufferSize, COORD bufferCoord, ref SMALL_RECT writeRegion);
public static extern int ReadConsoleOutputW([NativeTypeName("HANDLE")] IntPtr hConsoleOutput, [NativeTypeName("PCHAR_INFO")] CHAR_INFO *lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, [NativeTypeName("PSMALL_RECT")] SMALL_RECT *lpReadRegion);
public static extern int WriteConsoleOutputA([NativeTypeName("HANDLE")] IntPtr hConsoleOutput, [NativeTypeName("const CHAR_INFO *")] CHAR_INFO *lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, [NativeTypeName("PSMALL_RECT")] SMALL_RECT *lpWriteRegion);
public static extern int ScrollConsoleScreenBufferW([NativeTypeName("HANDLE")] IntPtr hConsoleOutput, [NativeTypeName("const SMALL_RECT *")] SMALL_RECT *lpScrollRectangle, [NativeTypeName("const SMALL_RECT *")] SMALL_RECT *lpClipRectangle, COORD dwDestinationOrigin, [NativeTypeName("const CHAR_INFO *")] CHAR_INFO *lpFill);
internal static extern unsafe bool ReadConsoleOutput(IntPtr hConsoleOutput, CHAR_INFO *pBuffer, COORD bufferSize, COORD bufferCoord, ref SMALL_RECT readRegion);
public void Refresh() { short w = BufferSize; short h = BufferSize; short x = 0; short y = 0; if (!_resizeFlag) { x = BufferSize - 1; y = x; short x2 = 0; short y2 = 0; for (short ix = 0; ix < BufferSize; ix++) { for (short iy = 0; iy < BufferSize; iy++) { var ofs = iy * BufferSize + ix; var xor = (_buffer[ofs].Attributes ^ _buffer2[ofs].Attributes) | (_buffer[ofs].Char ^ _buffer2[ofs].Char); if (xor != 0) { x = Math.Min(x, ix); y = Math.Min(y, iy); x2 = Math.Max(x2, ix); y2 = Math.Max(y2, iy); } } } if (x > x2) { x = (short)(x2 + 1); } if (y > y2) { y = (short)(y2 + 1); } w = (short)(x2 - x + 1); h = (short)(y2 - y + 1); } var info = new CONSOLE_SCREEN_BUFFER_INFO(); GetConsoleScreenBufferInfo(_stdout, ref info); var rect = new SMALL_RECT { Left = (short)(info.Window.Left + x), Top = (short)(info.Window.Top + y), Right = (short)(info.Window.Left + x + w - 1), Bottom = (short)(info.Window.Top + y + h - 1) }; Memset(new IntPtr(_buffer2), 0, BufferSize * BufferSize); WriteConsoleOutputW(_stdout, new IntPtr(_buffer), new COORD { X = BufferSize, Y = BufferSize }, new COORD { X = x, Y = y }, ref rect); if (!_resizeFlag) { var tbuf = _buffer2; _buffer2 = _buffer; _buffer = tbuf; } _resizeFlag = false; }
public WindowsNativeConsoleProvider() { _threadToken = new CancellationTokenSource(); _buffer = (CHAR_INFO *)Marshal.AllocHGlobal(BufferSize * BufferSize * CHAR_INFO.SizeOf).ToPointer(); _buffer2 = (CHAR_INFO *)Marshal.AllocHGlobal(BufferSize * BufferSize * CHAR_INFO.SizeOf).ToPointer(); _stdin = GetStdHandle(-10); _stdout = GetStdHandle(-11); { var info = new CONSOLE_SCREEN_BUFFER_INFO(); GetConsoleScreenBufferInfo(_stdout, ref info); WindowWidth = info.Window.Right - info.Window.Left + 1; WindowHeight = info.Window.Bottom - info.Window.Top + 1; _prevBuf = info.Size; SetConsoleScreenBufferSize(_stdout, new COORD { X = (short)WindowWidth, Y = (short)WindowHeight }); } new Thread(() => // window size monitor { while (!_threadToken.IsCancellationRequested) { Thread.Sleep(16); var info = new CONSOLE_SCREEN_BUFFER_INFO(); GetConsoleScreenBufferInfo(_stdout, ref info); int nw = info.Window.Right - info.Window.Left + 1, nh = info.Window.Bottom - info.Window.Top + 1; if (nw < 0) { nw = WindowWidth; } if (nh < 0) { nh = WindowHeight; // fukken winapi bugs } if (nw == WindowWidth && nh == WindowHeight) { continue; } var pw = WindowWidth; var ph = WindowHeight; _resizeFlag = true; WindowWidth = nw; WindowHeight = nh; SetConsoleScreenBufferSize(_stdout, new COORD { X = (short)WindowWidth, Y = (short)WindowHeight }); try { SizeChanged?.Invoke(this, new SizeChangedEventArgs(new Size(pw, ph), new Size(nw, nh))); } catch { /* Do not care if subscriber f****d up */ } //Refresh(); } }) { Priority = ThreadPriority.Lowest }.Start(); _keyboardThread = new Thread(() => // keyboard monitor { INPUT_RECORD *charBuf = stackalloc INPUT_RECORD[1]; var ptr = new IntPtr(charBuf); var sizeOf = Marshal.SizeOf(typeof(INPUT_RECORD)); while (!_threadToken.IsCancellationRequested) { try { uint nchars = 0; Memset(ptr, 0, sizeOf); ReadConsoleInputW(_stdin, ptr, 1, ref nchars); if (charBuf->EventType == 1 && nchars == 1 && charBuf->KeyEvent.KeyDown) { KeyPressed?.Invoke( this, new KeyPressedEventArgs(new ConsoleKeyInfo( charBuf->KeyEvent.Char, (ConsoleKey)charBuf->KeyEvent.KeyCode, (charBuf->KeyEvent.ControlKeyState & 0x10) > 0, (charBuf->KeyEvent.ControlKeyState & 0x03) > 0, (charBuf->KeyEvent.ControlKeyState & 0x0c) > 0 ))); } } catch { } } }); _keyboardThread.Start(); }
public static extern BOOL ReadConsoleOutputA(HANDLE hConsoleOutput, [NativeTypeName("PCHAR_INFO")] CHAR_INFO *lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, [NativeTypeName("PSMALL_RECT")] SMALL_RECT *lpReadRegion);
public static extern BOOL WriteConsoleOutputW(HANDLE hConsoleOutput, [NativeTypeName("const CHAR_INFO *")] CHAR_INFO *lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, [NativeTypeName("PSMALL_RECT")] SMALL_RECT *lpWriteRegion);