.net 有没有办法读取F控制台应用程序中特定行上的文本?

.net 有没有办法读取F控制台应用程序中特定行上的文本?,.net,f#,.net,F#,我想把文本从某一行放到一个变量中。我是否可以使用Console.CursorLeft和Console.CursorTop进行此操作?程序是否有可能知道光标当前所在的字母?我有一个程序,你可以使用箭头键来突出显示某一行,但它要求你已经知道该行的内容并重复它 到目前为止,这是一个有效的程序,你可以知道我在做什么 open System Console.BackgroundColor <- ConsoleColor.White Console.ForegroundColor <- Con

我想把文本从某一行放到一个变量中。我是否可以使用Console.CursorLeft和Console.CursorTop进行此操作?程序是否有可能知道光标当前所在的字母?我有一个程序,你可以使用箭头键来突出显示某一行,但它要求你已经知道该行的内容并重复它

到目前为止,这是一个有效的程序,你可以知道我在做什么

open System

Console.BackgroundColor <- ConsoleColor.White
Console.ForegroundColor <- ConsoleColor.Black
printfn "OPTION 1"
Console.BackgroundColor <- ConsoleColor.Black
Console.ForegroundColor <- ConsoleColor.White
printfn "Option 2"
printfn "Option 3"

Console.SetCursorPosition(0, 0)

let mutable exit = false

while not exit do
    let mutable key = Console.ReadKey()
    if key.Key.Equals(ConsoleKey.UpArrow) then
        Console.SetCursorPosition(0, Console.CursorTop - 1)
    if key.Key.Equals(ConsoleKey.DownArrow) then
        Console.SetCursorPosition(0, Console.CursorTop + 1)
    if key.Key.Equals(ConsoleKey.Enter) then
        let selected = Console.CursorTop + 1
        Console.SetCursorPosition(0, 3)
        printfn "You selected %i" (selected)
        exit <- true
    let mutable test = Console.CursorTop
    Console.SetCursorPosition(0, 0)
    printfn "Option 1"
    printfn "Option 2"
    printfn "Option 3"
    if test = 0 then
        Console.SetCursorPosition(0, 0)
        Console.BackgroundColor <- ConsoleColor.White
        Console.ForegroundColor <- ConsoleColor.Black
        printfn "OPTION 1"
    if test = 1 then
        Console.SetCursorPosition(0, 1)
        Console.BackgroundColor <- ConsoleColor.White
        Console.ForegroundColor <- ConsoleColor.Black
        printfn "OPTION 2"
    if test = 2 then
        Console.SetCursorPosition(0, 2)
        Console.BackgroundColor <- ConsoleColor.White
        Console.ForegroundColor <- ConsoleColor.Black
        printfn "OPTION 3"
    Console.BackgroundColor <- ConsoleColor.Black
    Console.ForegroundColor <- ConsoleColor.White
    Console.SetCursorPosition(0, test)

Console.Read() |> ignore

鉴于评论中的澄清,我认为绝对没有理由以需要阅读打印到控制台的文本的方式编写应用程序

如果您这样做了,您将基本上依赖于控制台文本来维护应用程序的状态。换句话说,您正在将您的状态保持在有限大小的2D字符数组中

更好的方法是使用F类型来表示状态。例如,您可以定义一条记录,记录您的菜单选项、选择和是否进行了选择的标志:

type State = 
  { Options : string list
    Selection : int
    Completed : bool }
现在,您可以定义一个打印状态的函数:

let printMenu menu = 
  Console.SetCursorPosition(0, 0)
  for i, option in Seq.indexed menu.Options do
    if i = menu.Selection then
      Console.BackgroundColor <- ConsoleColor.White
      Console.ForegroundColor <- ConsoleColor.Black
    printfn "%s" option
    Console.BackgroundColor <- ConsoleColor.Black
    Console.ForegroundColor <- ConsoleColor.Gray
while not state.Completed do
  printMenu state
  let key = Console.ReadKey()
  state <- handleKey key state

Console.SetCursorPosition(0, 3)
printfn "You selected %i" state.Selection
最后,您可以使用菜单选项定义初始状态。我将保留您的while循环,因此这将是一个可变变量:

let mutable state = 
  { Options = ["Option 1"; "Option 2"; "Option 3"] 
    Completed = false
    Selection = 0 }      
现在,主要的应用程序逻辑超级简单。只要在状态为“完成”时保持循环即可。如果“完成”为false,请打印菜单,读取一个键并更新状态:

let printMenu menu = 
  Console.SetCursorPosition(0, 0)
  for i, option in Seq.indexed menu.Options do
    if i = menu.Selection then
      Console.BackgroundColor <- ConsoleColor.White
      Console.ForegroundColor <- ConsoleColor.Black
    printfn "%s" option
    Console.BackgroundColor <- ConsoleColor.Black
    Console.ForegroundColor <- ConsoleColor.Gray
while not state.Completed do
  printMenu state
  let key = Console.ReadKey()
  state <- handleKey key state

Console.SetCursorPosition(0, 3)
printfn "You selected %i" state.Selection

这种构造应用程序的方式更加清晰,因为它将状态保持为显式数据类型,并且与在其上运行的各种函数分开。

可能使用自定义流作为输出,既写入控制台,又跟踪以StringBuilder之类的方式写入的所有内容,然后根据自定义流的数据版本处理击键?@AaronM.Eshbach这是我的第一次,但您认为这是减少此代码的唯一方法吗?我真的希望有一种方法可以读取控制台上的内容。如果您是以管理员身份运行的,您可以让您的进程实际生成一个带有重定向输入/输出流的单独进程。如果您愿意,我不知道如何做,您可以将其放入答案中。否则,我想我只做你的第一个建议。@Alanay出于好奇,你为什么要从控制台读取文本,而不是维护自己的数据结构来跟踪你想在屏幕上显示的内容?然后,您可以使用此数据结构来打印和读取内容。我能想到的唯一原因是,您正在使用一些无法控制的代码,但如果不是这样,我绝对会使用数据结构,而不是从控制台读取。