public static unsafe void SetWindowSize(int width, int height) { if (width <= 0) throw new ArgumentOutOfRangeException(nameof(width), width, SR.ArgumentOutOfRange_NeedPosNum); if (height <= 0) throw new ArgumentOutOfRangeException(nameof(height), height, SR.ArgumentOutOfRange_NeedPosNum); // Get the position of the current console window Interop.Kernel32.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(); // If the buffer is smaller than this new window size, resize the // buffer to be large enough. Include window position. bool resizeBuffer = false; Interop.Kernel32.COORD size = new Interop.Kernel32.COORD(); size.X = csbi.dwSize.X; size.Y = csbi.dwSize.Y; if (csbi.dwSize.X < csbi.srWindow.Left + width) { if (csbi.srWindow.Left >= short.MaxValue - width) throw new ArgumentOutOfRangeException(nameof(width), SR.ArgumentOutOfRange_ConsoleWindowBufferSize); size.X = (short)(csbi.srWindow.Left + width); resizeBuffer = true; } if (csbi.dwSize.Y < csbi.srWindow.Top + height) { if (csbi.srWindow.Top >= short.MaxValue - height) throw new ArgumentOutOfRangeException(nameof(height), SR.ArgumentOutOfRange_ConsoleWindowBufferSize); size.Y = (short)(csbi.srWindow.Top + height); resizeBuffer = true; } if (resizeBuffer) { if (!Interop.Kernel32.SetConsoleScreenBufferSize(OutputHandle, size)) throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error()); } Interop.Kernel32.SMALL_RECT srWindow = csbi.srWindow; // Preserve the position, but change the size. srWindow.Bottom = (short)(srWindow.Top + height - 1); srWindow.Right = (short)(srWindow.Left + width - 1); if (!Interop.Kernel32.SetConsoleWindowInfo(OutputHandle, true, &srWindow)) { int errorCode = Marshal.GetLastWin32Error(); // If we resized the buffer, un-resize it. if (resizeBuffer) { Interop.Kernel32.SetConsoleScreenBufferSize(OutputHandle, csbi.dwSize); } // Try to give a better error message here Interop.Kernel32.COORD bounds = Interop.Kernel32.GetLargestConsoleWindowSize(OutputHandle); if (width > bounds.X) throw new ArgumentOutOfRangeException(nameof(width), width, SR.Format(SR.ArgumentOutOfRange_ConsoleWindowSize_Size, bounds.X)); if (height > bounds.Y) throw new ArgumentOutOfRangeException(nameof(height), height, SR.Format(SR.ArgumentOutOfRange_ConsoleWindowSize_Size, bounds.Y)); throw Win32Marshal.GetExceptionForWin32Error(errorCode); } }
[System.Security.SecuritySafeCritical] // auto-generated public static void SetBufferSize(int width, int height) { // Ensure the new size is not smaller than the console window Interop.Kernel32.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(); Interop.Kernel32.SMALL_RECT srWindow = csbi.srWindow; if (width < srWindow.Right + 1 || width >= short.MaxValue) throw new ArgumentOutOfRangeException(nameof(width), width, SR.ArgumentOutOfRange_ConsoleBufferLessThanWindowSize); if (height < srWindow.Bottom + 1 || height >= short.MaxValue) throw new ArgumentOutOfRangeException(nameof(height), height, SR.ArgumentOutOfRange_ConsoleBufferLessThanWindowSize); Interop.Kernel32.COORD size = new Interop.Kernel32.COORD(); size.X = (short)width; size.Y = (short)height; if (!Interop.Kernel32.SetConsoleScreenBufferSize(OutputHandle, size)) { throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error()); } }
public static void SetCursorPosition(int left, int top) { // Note on argument checking - the upper bounds are NOT correct // here! But it looks slightly expensive to compute them. Let // Windows calculate them, then we'll give a nice error message. if (left < 0 || left >= short.MaxValue) throw new ArgumentOutOfRangeException(nameof(left), left, SR.ArgumentOutOfRange_ConsoleBufferBoundaries); if (top < 0 || top >= short.MaxValue) throw new ArgumentOutOfRangeException(nameof(top), top, SR.ArgumentOutOfRange_ConsoleBufferBoundaries); Contract.EndContractBlock(); IntPtr hConsole = OutputHandle; Interop.Kernel32.COORD coords = new Interop.Kernel32.COORD(); coords.X = (short)left; coords.Y = (short)top; if (!Interop.Kernel32.SetConsoleCursorPosition(hConsole, coords)) { // Give a nice error message for out of range sizes int errorCode = Marshal.GetLastWin32Error(); Interop.Kernel32.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(); if (left < 0 || left >= csbi.dwSize.X) throw new ArgumentOutOfRangeException(nameof(left), left, SR.ArgumentOutOfRange_ConsoleBufferBoundaries); if (top < 0 || top >= csbi.dwSize.Y) throw new ArgumentOutOfRangeException(nameof(top), top, SR.ArgumentOutOfRange_ConsoleBufferBoundaries); throw Win32Marshal.GetExceptionForWin32Error(errorCode); } }
public static void Clear() { Interop.Kernel32.COORD coordScreen = new Interop.Kernel32.COORD(); Interop.Kernel32.CONSOLE_SCREEN_BUFFER_INFO csbi; bool success; int conSize; IntPtr hConsole = OutputHandle; if (hConsole == s_InvalidHandleValue) throw new IOException(SR.IO_NoConsole); // get the number of character cells in the current buffer // Go through my helper method for fetching a screen buffer info // to correctly handle default console colors. csbi = GetBufferInfo(); conSize = csbi.dwSize.X * csbi.dwSize.Y; // fill the entire screen with blanks int numCellsWritten = 0; success = Interop.Kernel32.FillConsoleOutputCharacter(hConsole, ' ', conSize, coordScreen, out numCellsWritten); if (!success) throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error()); // now set the buffer's attributes accordingly numCellsWritten = 0; success = Interop.Kernel32.FillConsoleOutputAttribute(hConsole, csbi.wAttributes, conSize, coordScreen, out numCellsWritten); if (!success) throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error()); // put the cursor at (0, 0) success = Interop.Kernel32.SetConsoleCursorPosition(hConsole, coordScreen); if (!success) throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error()); }
public static unsafe void MoveBufferArea(int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight, int targetLeft, int targetTop, char sourceChar, ConsoleColor sourceForeColor, ConsoleColor sourceBackColor) { if (sourceForeColor < ConsoleColor.Black || sourceForeColor > ConsoleColor.White) throw new ArgumentException(SR.Arg_InvalidConsoleColor, nameof(sourceForeColor)); if (sourceBackColor < ConsoleColor.Black || sourceBackColor > ConsoleColor.White) throw new ArgumentException(SR.Arg_InvalidConsoleColor, nameof(sourceBackColor)); Contract.EndContractBlock(); Interop.Kernel32.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(); Interop.Kernel32.COORD bufferSize = csbi.dwSize; if (sourceLeft < 0 || sourceLeft > bufferSize.X) throw new ArgumentOutOfRangeException(nameof(sourceLeft), sourceLeft, SR.ArgumentOutOfRange_ConsoleBufferBoundaries); if (sourceTop < 0 || sourceTop > bufferSize.Y) throw new ArgumentOutOfRangeException(nameof(sourceTop), sourceTop, SR.ArgumentOutOfRange_ConsoleBufferBoundaries); if (sourceWidth < 0 || sourceWidth > bufferSize.X - sourceLeft) throw new ArgumentOutOfRangeException(nameof(sourceWidth), sourceWidth, SR.ArgumentOutOfRange_ConsoleBufferBoundaries); if (sourceHeight < 0 || sourceTop > bufferSize.Y - sourceHeight) throw new ArgumentOutOfRangeException(nameof(sourceHeight), sourceHeight, SR.ArgumentOutOfRange_ConsoleBufferBoundaries); // Note: if the target range is partially in and partially out // of the buffer, then we let the OS clip it for us. if (targetLeft < 0 || targetLeft > bufferSize.X) throw new ArgumentOutOfRangeException(nameof(targetLeft), targetLeft, SR.ArgumentOutOfRange_ConsoleBufferBoundaries); if (targetTop < 0 || targetTop > bufferSize.Y) throw new ArgumentOutOfRangeException(nameof(targetTop), targetTop, SR.ArgumentOutOfRange_ConsoleBufferBoundaries); // If we're not doing any work, bail out now (Windows will return // an error otherwise) if (sourceWidth == 0 || sourceHeight == 0) return; // Read data from the original location, blank it out, then write // it to the new location. This will handle overlapping source and // destination regions correctly. // Read the old data Interop.Kernel32.CHAR_INFO[] data = new Interop.Kernel32.CHAR_INFO[sourceWidth * sourceHeight]; bufferSize.X = (short)sourceWidth; bufferSize.Y = (short)sourceHeight; Interop.Kernel32.COORD bufferCoord = new Interop.Kernel32.COORD(); Interop.Kernel32.SMALL_RECT readRegion = new Interop.Kernel32.SMALL_RECT(); readRegion.Left = (short)sourceLeft; readRegion.Right = (short)(sourceLeft + sourceWidth - 1); readRegion.Top = (short)sourceTop; readRegion.Bottom = (short)(sourceTop + sourceHeight - 1); bool r; fixed (Interop.Kernel32.CHAR_INFO* pCharInfo = data) r = Interop.Kernel32.ReadConsoleOutput(OutputHandle, pCharInfo, bufferSize, bufferCoord, ref readRegion); if (!r) throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error()); // Overwrite old section Interop.Kernel32.COORD writeCoord = new Interop.Kernel32.COORD(); writeCoord.X = (short)sourceLeft; Interop.Kernel32.Color c = ConsoleColorToColorAttribute(sourceBackColor, true); c |= ConsoleColorToColorAttribute(sourceForeColor, false); short attr = (short)c; int numWritten; for (int i = sourceTop; i < sourceTop + sourceHeight; i++) { writeCoord.Y = (short)i; r = Interop.Kernel32.FillConsoleOutputCharacter(OutputHandle, sourceChar, sourceWidth, writeCoord, out numWritten); Debug.Assert(numWritten == sourceWidth, "FillConsoleOutputCharacter wrote the wrong number of chars!"); if (!r) throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error()); r = Interop.Kernel32.FillConsoleOutputAttribute(OutputHandle, attr, sourceWidth, writeCoord, out numWritten); if (!r) throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error()); } // Write text to new location Interop.Kernel32.SMALL_RECT writeRegion = new Interop.Kernel32.SMALL_RECT(); writeRegion.Left = (short)targetLeft; writeRegion.Right = (short)(targetLeft + sourceWidth); writeRegion.Top = (short)targetTop; writeRegion.Bottom = (short)(targetTop + sourceHeight); fixed (Interop.Kernel32.CHAR_INFO* pCharInfo = data) Interop.Kernel32.WriteConsoleOutput(OutputHandle, pCharInfo, bufferSize, bufferCoord, ref writeRegion); }
internal static extern bool SetConsoleScreenBufferSize(IntPtr hConsoleOutput, Interop.Kernel32.COORD size);