-1

I'm making a console game in C# in Visual Studio and I want to make the game to be in the full console window.

I resized the buffer and window to be the same size, but it looks like the space after the scrollbars remained, which will probably be really annoying to look at. I wonder if there's any way to remove that blank space in C#, or at least add grayed-out scrollbars. I saw a similar thread, but it was in C++.

Scrollbars

Here's a reproducible example:

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();
        }
    }
}

I don't really know how to do this or even if it's possible to remove the black space in this language.

Volper
  • 644
  • 6
  • 14

1 Answers1

2

Finally, after a lot of head-scratching, I think I've solved this issue. Firstly, I had to add some additional WinAPI methods:

[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);

and structs:

[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;
}

After that, it was time to modify the part where the buffer and window were resized:

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);

And that's it! No more ugly black space (at least on my computer, haven't tested it on other Windows versions).

It works.

Volper
  • 644
  • 6
  • 14