【问题标题】:How do I manipulate console cursor position in dotnet core?如何在 dotnet core 中操作控制台光标位置?
【发布时间】:2015-12-15 05:22:27
【问题描述】:

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

据我在https://github.com/dotnet/corefx/blob/master/src/System.Console/src/System/Console.cs 中看到的,无法操纵光标位置。

这是否意味着它在 Windows 上是不可能的,而通过 ANSI 转义序列在 linux 上是可能的?

【问题讨论】:

  • 你想移动和控制鼠标等?
  • @Slashy 控制台光标是控制台窗口中的 .... 光标。 OP知道他在问什么。转义序列也应该在 Windows BTW 中工作
  • @PanagiotisKanavos Windows 控制台本身不支持 ANSI 转义序列。 You need to load some custom "driver".
  • @Christian.K duh - 我不得不定位控制台光标已经 20 年了!但是,这并不意味着如果 .NET 核心应用程序在 Linux 上运行,则不能使用转义序列。 Windows 上的非核心应用程序或 Linux 上的 Mono 也不需要它们,它可以使用定位方法
  • @PanagiotisKanavos:我指的是您声明转义序列“应该也适用于 Windows BTW”的部分。不是吹毛求疵,而是防止 OP 徒劳地走这条路。 ;-) 总而言之,目前,他必须在 Windows 上使用 Linux 的转义序列和 Win32 API(就像包装在完整的 .NET 框架中)。当然最好包裹在一些兼容层后面。

标签: c# .net .net-core


【解决方案1】:

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

【讨论】:

  • 不是说它不支持(确实是),但是使用 DllImport 和 .NET Core 上的 Win32 Api 原生可能不是一个好主意
  • 这仅适用于 Windows。我猜 OP 可以在不同的类中使用 Linux 实现(可能使用 ANSI 序列),就像 .NET 核心对 ConsolePal.Windows 和 ConsolePal.Unix.cs 所做的那样
  • @Jcl 检查存储库。 ConsolePal 一个具有特定平台专业化的核心类。 ConsolePal.Windows.cs 使用 Interop 而 ConsolePal.Unix 使用 POSIX 调用
  • 嗯...但是 ConsolePal 是一个内部类。他应该如何使用它(当然没有使用反射)。
  • 解决方案“仅适用于 windows”是可以的,只要我可以在 linux 版本中使用 ANSI 转义字符。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-12
相关资源
最近更新 更多