【问题标题】:VB.NET Console: Use ANSI Sequences (Console Virtual Terminal Sequences)VB.NET 控制台:使用 ANSI 序列(控制台虚拟终端序列)
【发布时间】:2021-03-01 18:04:03
【问题描述】:

我正在尝试在 VB.NET 中编写控制台应用程序(VS Studio Community 2019 & .Net framework 4.8) 我无法让它正确显示 ANSI Escape 序列。 我知道this suggestion 并已应用它。 (没有区别)

我可以使用设置颜色

Console.ResetColor()
Console.ForegroundColor = ConsoleColor.Red

和光标定位,使用

Console.SetCursorPosition(origCol + x, origRow + y)
Console.Write(s)

当我尝试这样做时

Console.WriteLine("\u001b[31mHello World!\u001b[0m")

它只是将其原始打印出来,而不解释 ANSI 序列。

Console.OutputEncoding = Text.Encoding.XXX 只给我有限的 XXX 选项,包括 Ascii、UTF8、16、32 和 Unicode。

我已经阅读了This 关于“控制台虚拟终端序列”的文章,这似乎是微软对 ANSI 代码的术语。本文参考setConsoleMode

还有这个C的sn-p,我在vb.net中找不到对应的

// Set output mode to handle virtual terminal sequences
    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    if (hOut == INVALID_HANDLE_VALUE)
    {
        return GetLastError();
    }

    DWORD dwMode = 0;
    if (!GetConsoleMode(hOut, &dwMode))
    {
        return GetLastError();
    }

    dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
    if (!SetConsoleMode(hOut, dwMode))
    {
        return GetLastError();
    }

我猜这两个之一可能是我的问题的答案,但我不知道如何在 VB.net 中处理此信息。

【问题讨论】:

    标签: c# c vb.net console ansi


    【解决方案1】:

    问题标题表明编程是VB.net。然而这个语句被显示了

    Console.WriteLine("\u001b[31mHello World!\u001b[0m")
    

    其中使用了 C# 样式的 unicode 转义序列,\u001b。 VB 不支持转义序列。使用字符串插值和ChrW Function 的正确 VB 语句是:

    Console.WriteLine($"{ChrW(&H1B)}[31mHello World!{ChrW(&H1B)}[0m")
    

    还有这个C的sn-p,我在vb.net中找不到对应的

    这将需要使用平台调用 (PInvoke) 功能来调用本机 api 函数。 sn-p 的直接转换包含在下面定义的SetVT100Mode 方法中。您可以在文档中或查看 Pinvoke.net 的示例中找到各种常量。

    Imports System.Runtime.InteropServices
    
    Module Module1
      Private Const STD_INPUT_HANDLE As Int32 = -10
      Private Const STD_OUTPUT_HANDLE As Int32 = -11
      Private Const STD_ERROR_HANDLE As Int32 = -12
      Private ReadOnly INVALID_HANDLE_VALUE As New IntPtr(-1)
      Private Const ENABLE_VIRTUAL_TERMINAL_PROCESSING As UInt32 = &H4
    
      Sub Main()
        Const Esc As Char = ChrW(27)
    
        If SetVT100Mode() = 0 Then
          Console.WriteLine($"{Esc}[31mHello World!{Esc}[0m")
        End If
    
        Console.ReadLine()
    
      End Sub
    
      Private Function SetVT100Mode() As Int32
        Dim hOut As IntPtr = GetStdHandle(STD_OUTPUT_HANDLE)
        If hOut = INVALID_HANDLE_VALUE Then
          Return Marshal.GetLastWin32Error()
        End If
    
        Dim mode As UInt32
        If Not GetConsoleMode(hOut, mode) Then
          Return Marshal.GetLastWin32Error()
        End If
    
        mode = mode Or ENABLE_VIRTUAL_TERMINAL_PROCESSING
        If Not SetConsoleMode(hOut, mode) Then
          Return Marshal.GetLastWin32Error()
        End If
        Return 0
      End Function
    
      <DllImport("kernel32.dll", SetLastError:=True)>
      Private Function GetConsoleMode(ByVal hConsoleHandle As IntPtr, ByRef lpMode As UInteger) As Boolean
      End Function
    
      <DllImport("kernel32.dll", SetLastError:=True)>
      Private Function SetConsoleMode(ByVal hConsoleHandle As IntPtr, ByVal dwMode As UInteger) As Boolean
      End Function
    
      <DllImport("kernel32.dll", SetLastError:=True)>
      Private Function GetStdHandle(ByVal nStdHandle As Integer) As IntPtr
      End Function
    
    End Module
    

    【讨论】:

    • 太棒了。谢谢!您指出的第一个问题,使用 ChrW(&H1B),对我来说是一个重大飞跃。我不知道为什么我以前在任何地方都没有发现它!
    • 您的“Pinvoke”代码,我保存为测试程序,它编译并运行完美!再次感谢您。
    猜你喜欢
    • 2017-10-18
    • 2022-09-29
    • 1970-01-01
    • 2015-10-08
    • 1970-01-01
    • 2015-05-15
    • 1970-01-01
    • 2013-12-21
    • 1970-01-01
    相关资源
    最近更新 更多