在dotnet core中如何操作控制台光标位置?

7

你想要移动和控制鼠标等吗? - Slashy
@Slashy 控制台光标是控制台窗口中的光标。OP 知道自己在问什么。顺便说一下,转义序列在 Windows 中也可以使用。 - Panagiotis Kanavos
@Christian.K 哎呀 - 我已经20年没必要定位控制台光标了!但这并不意味着转义序列不能使用,如果一个.NET Core应用程序在Linux上运行。非核心应用程序在Windows上或Linux上的Mono也不需要它们,可以使用定位方法。 - Panagiotis Kanavos
@Christian.K 看起来 .NET Core 已经有部分实现了,可以使用平台特定的覆盖.... - Panagiotis Kanavos
@PanagiotisKanavos 是的。但看起来它似乎被藏在名为“ConsolePal”的内部类中,没有公共API界面。很奇怪。 - Christian.K
显示剩余2条评论
1个回答

4
ConsolePal 类中,您有一个 private static IntPtr OutputHandle(即要移动光标的控制台的句柄),因此在这个类中,您需要公开一个设置光标位置的方法。 在此方法中,您需要调用系统API SetConsoleCursorPosition(IntPtr hConsoleOutput, COORD cursorPosition);COORD 是:
[StructLayout(LayoutKind.Sequential)]
internal struct COORD
{
    internal short X;
    internal short Y;
} 

您可以在Interop.mincore类中添加前面方法的DllImport(因为看起来这里是系统DllImport所在的地方),这样您就可以在需要的任何位置进行以下操作:
internal partial class Interop
{
    internal partial class mincore
    {
        [DllImport("kernel32.dll", SetLastError=true)]
        internal static extern bool SetConsoleCursorPosition(IntPtr hConsoleOutput, COORD cursorPosition);
    }
}

在ConsolePal中暴露方法的方式可能如下所示:
public static void SetCursorPosition(int left, int top)
{
    IntPtr consoleOutputHandle = OutputHandle;
    COORD cursorPosition = new COORD {
        X = (short) left,
        Y = (short) top
    };
    Interop.mincore.SetConsoleCursorPosition(consoleOutputHandle, cursorPosition;
}

注意:在方法中添加一些输入检查和对 Interop.mincore.SetConsoleCursorPosition 返回值的检查。

并在 Console 类中简单公开一个调用 ConsolePal.SetCursorPosition 方法的方法。

public static void SetCursorPosition(int left, int top)
{
     ConsolePal.SetCursorPosition(left, top);
}

我没有对上述代码进行测试,可能包含错误。

编辑

正如@Jcl所述,使用自定义版本的.NET可能不受欢迎。在这种情况下,您可以编写一个简单的类来移动光标(即使这个解决方案仅适用于Windows):

static class MyAwesomeConsoleExtensions
{
    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern IntPtr GetStdHandle(int nStdHandle);
    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool SetConsoleCursorPosition(IntPtr hConsoleOutput, COORD cursorPosition);
    [StructLayout(LayoutKind.Sequential)]
    private struct COORD
    {
        internal short X;
        internal short Y;
    }
    private const int STD_OUTPUT_HANDLE = -11;

    public static void SetCursorPos(int left, int top)
    {
        IntPtr consoleOutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
        COORD cursorPosition = new COORD
        {
            X = (short)left,
            Y = (short)top
        };
        SetConsoleCursorPosition(consoleOutputHandle, cursorPosition);
    }
}

1
不是说它不被支持(实际上是被支持的),但在.NET Core上使用DllImport和Win32 Api可能不是一个好主意。 - Jcl
1
这只能在Windows上运行。我猜OP可以在不同的类中使用Linux实现(可能使用ANSI序列),就像.NET Core在ConsolePal.Windows和ConsolePal.Unix.cs中所做的那样。 - Panagiotis Kanavos
@Jcl DllImport在.NET Core中被广泛使用。我建议将此调用添加到ConsolePal.Windows.cs中,以便针对特定平台进行操作,我认为这不会带来麻烦。 - Matteo Umili
总的来说,对于“旧”的 .NET Framework,我会支持那段代码...再次强调,我只是不太喜欢(但让我重申:这是个人原因),在 .NET Core(框架本身之外)使用 DllImport...但这确实是一个解决方案(适用于 Windows)。 - Jcl
1
只要我能在Linux版本中使用ANSI转义字符,"仅适用于Windows"的解决方案就可以。谢谢! - AlfeG
显示剩余8条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接