在 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 版本上测试过)。
我正在 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 版本上测试过)。