在 C# 中删除控制台滚动条后留下的 space

Remove space left after console scrollbars in C#

我正在 Visual Studio 中用 C# 制作主机游戏,我想让游戏在完整的主机中运行 window。

我调整了缓冲区的大小和window大小相同,但它看起来像滚动条保留后的space,看起来可能真的很烦人。我想知道是否有任何方法可以删除 C# 中的空白 space,或者至少添加变灰的滚动条。我看到一个类似的线程,但它是在 C++ 中。

这是一个可重现的例子:

using Microsoft.Win32.SafeHandles;
using System;
using System.IO;
using System.Runtime.InteropServices;

namespace ConsoleTest1
{
    class Program
    {
        [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        static extern SafeFileHandle CreateFile(
            string fileName,
            [MarshalAs(UnmanagedType.U4)] uint fileAccess,
            [MarshalAs(UnmanagedType.U4)] uint fileShare,
            IntPtr securityAttributes,
            [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
            [MarshalAs(UnmanagedType.U4)] int flags,
            IntPtr template);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool WriteConsoleOutput(
          SafeFileHandle hConsoleOutput,
          CharInfo[] lpBuffer,
          Coord dwBufferSize,
          Coord dwBufferCoord,
          ref SmallRect lpWriteRegion);

        [StructLayout(LayoutKind.Sequential)]
        public struct Coord
        {
            public short X, Y;

            public Coord(short x, short y)
            {
                X = x;
                Y = y;
            }
        }

        [StructLayout(LayoutKind.Explicit)]
        public struct CharUnion
        {
            [FieldOffset(0)] public char UnicodeChar;
            [FieldOffset(0)] public byte AsciiChar;
        }

        [StructLayout(LayoutKind.Explicit)]
        public struct CharInfo
        {
            [FieldOffset(0)] public CharUnion Char;
            [FieldOffset(2)] public short Attributes;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct SmallRect
        {
            public short Left, Top, Right, Bottom;

            public SmallRect(short width, short height)
            {
                Left = Top = 0;
                Right = width;
                Bottom = height;
            }
        }


        [STAThread]
        static void Main(string[] args)
        {
            short width = 50, height = 20;
            SafeFileHandle handle = CreateFile("CONOUT$", 0x40000000, 2, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);
            CharInfo[] buffer = new CharInfo[width * height];
            SmallRect writeRegion = new SmallRect(width, height);

            Console.SetWindowSize(width, height);
            Console.SetBufferSize(width, height);

            for (int i = 0; i < buffer.Length; ++i)
            {
                buffer[i].Attributes = 0xb0;
                buffer[i].Char.UnicodeChar = ' ';
            }

            WriteConsoleOutput(handle, buffer, new Coord(width, height), new Coord(0, 0), ref writeRegion);
            Console.ReadKey();
        }
    }
}

我真的不知道该怎么做,甚至不知道是否可以删除这种语言中的黑色 space。

终于,经过一番摸索,我想我已经解决了这个问题。首先,我必须添加一些额外的 WinAPI 方法:

[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr GetStdHandle(int nStdHandle);

[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool GetConsoleScreenBufferInfoEx(
    IntPtr hConsoleOutput,
    ref ConsoleScreenBufferInfoEx ConsoleScreenBufferInfo);

[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetConsoleScreenBufferInfoEx(
    IntPtr hConsoleOutput,
    ref ConsoleScreenBufferInfoEx ConsoleScreenBufferInfoEx);

和结构:

[StructLayout(LayoutKind.Sequential)]
private struct ConsoleScreenBufferInfoEx
{
    public uint cbSize;
    public Coord dwSize;
    public Coord dwCursorPosition;
    public short wAttributes;
    public SmallRect srWindow;
    public Coord dwMaximumWindowSize;
    public ushort wPopupAttributes;
    public bool bFullscreenSupported;

    public Colorref black, darkBlue, darkGreen, darkCyan, darkRed, darkMagenta, darkYellow, gray, darkGray, blue, green, cyan, red, magenta, yellow, white;
}

[StructLayout(LayoutKind.Sequential)]
private struct Colorref
{
    public uint ColorDWORD;
}

之后,是时候修改缓冲区和 window 调整大小的部分了:

Console.SetWindowSize(width - 2, height);
Console.SetBufferSize(width, height);

IntPtr stdHandle = GetStdHandle(-11);
ConsoleScreenBufferInfoEx bufferInfo = new ConsoleScreenBufferInfoEx();
bufferInfo.cbSize = (uint)Marshal.SizeOf(bufferInfo);
GetConsoleScreenBufferInfoEx(stdHandle, ref bufferInfo);
++bufferInfo.srWindow.Right;
++bufferInfo.srWindow.Bottom;
SetConsoleScreenBufferInfoEx(stdHandle, ref bufferInfo);

就是这样!不再有丑陋的黑色 space(至少在我的电脑上,还没有在其他 Windows 版本上测试过)。