首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >同时使用Readline()和ReadKey()

同时使用Readline()和ReadKey()
EN

Stack Overflow用户
提问于 2012-01-09 22:06:43
回答 3查看 4.2K关注 0票数 8

有没有办法同时检测readline和ReadKey,以便在大多数情况下,除了一些需要检测的特殊键输入之外,它的行为就像Readline一样?

我需要一些“并行”的实现来引入同时性。下面的代码是同步的,不能满足我的需求

代码语言:javascript
复制
while ((line = Console.ReadLine()) != "x")
{    
    if (line == "BLABLA")
    {
        //Stuff
    }

    else
    {
        //Stuff
    }

    ConsoleKeyInfo ki = Console.ReadKey(true);
    if ((ki.Key == ConsoleKey.V) && (ki.Modifiers == ConsoleModifiers.Control))
    {
        //Stuff
    }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-09-20 02:28:02

这是我刚刚创建的一个函数。

现在它只处理退格键、回车键和Esc键,但如果你认为有必要的话,可以很容易地修改它来处理其他键。

代码语言:javascript
复制
    // returns null if user pressed Escape, or the contents of the line if they pressed Enter.
    private static string ReadLineOrEsc()
    {
        string retString = "";

        int curIndex = 0;
        do
        {
            ConsoleKeyInfo readKeyResult = Console.ReadKey(true);

            // handle Esc
            if (readKeyResult.Key == ConsoleKey.Escape)
            {
                Console.WriteLine();
                return null;
            }

            // handle Enter
            if (readKeyResult.Key == ConsoleKey.Enter)
            {
                Console.WriteLine();
                return retString;
            }

            // handle backspace
            if (readKeyResult.Key == ConsoleKey.Backspace)
            {
                if (curIndex > 0)
                {
                    retString = retString.Remove(retString.Length - 1);
                    Console.Write(readKeyResult.KeyChar);
                    Console.Write(' ');
                    Console.Write(readKeyResult.KeyChar);
                    curIndex--;
                }
            }
            else
            // handle all other keypresses
            {
                retString += readKeyResult.KeyChar;
                Console.Write(readKeyResult.KeyChar);
                curIndex++;
            }
        }
        while (true);
    }
票数 4
EN

Stack Overflow用户

发布于 2012-01-09 22:28:45

不,不是这样的。这两种方法都会阻塞,直到用户在控制台上输入内容。因此,即使你能找到一种方法让两者并行运行,也不会确定哪一个得到了第一个镜头。

有一个(不明显的)类似的问题:如何在没有用户输入的情况下使Console.ReadLine()在一段时间后中止/中断。

这里已经多次尝试解决此问题:

大多数都是围绕创建添加超时的ReadLine函数的您自己的版本(或者在您的例子中是对某些字符(代码)的特殊处理)或使用某种线程来建模的。

这两种方式要么都不是微不足道的,要么都有自己的问题(确保你审查了评论,即使是被接受的答案)。

简而言之,我认为你需要推出你自己的ReadLine版本,基于Console.ReadKey,包含你的特殊处理,以及你所需要的真正的Console.ReadLine行为。请注意,这甚至包括诸如回车键、箭头键、退格键等基本内容。

UNIX更新:有来自Mono projectgetline.cs代码,它实现了行编辑功能,就像一些古老的UNIX shell提供的功能一样(如果您关心,可以使用EMACS模式)。为此,我认为它将需要实现某种ReadLine替代,尽管我还没有检查过。也许你可以以此为起点。

票数 2
EN

Stack Overflow用户

发布于 2019-01-31 04:48:54

为了响应@Overlord Zurd,我改进了用户提供的代码。

代码语言:javascript
复制
public class ConsoleOutput
{
    private ConsoleOutputType OutputType { get; set; }
    private object MyObject { get; }

    private static bool IsInserting { get; set; }
    public string KeyName => IsKey() && (ConsoleKeyInfo)MyObject != null ? ((ConsoleKeyInfo)MyObject).Key.ToString() : "Null";
    public string OutputString => !IsKey() && MyObject != null ? (string)MyObject : string.Empty;

    public static event Action<string> ReadInput = delegate { };

    public static event Action<ConsoleKeyInfo> ReadKey = delegate { };

    private ConsoleOutput()
    {
    }

    public ConsoleOutput(object obj)
    {
        MyObject = obj;

        OutputType = obj is ConsoleKeyInfo ? ConsoleOutputType.Key : ConsoleOutputType.Value;
    }

    public bool IsKey()
    {
        return OutputType == ConsoleOutputType.Key;
    }

    public bool IsExitKey()
    {
        if (!IsKey())
            return false;

        var info = ((ConsoleKeyInfo)MyObject);
        return (info.Modifiers & ConsoleModifiers.Control) != 0 && info.Key == ConsoleKey.B;
    }

    public string GetValue()
    {
        return (string)MyObject;
    }

    // returns null if user pressed Escape, or the contents of the line if they pressed Enter.
    public static ConsoleOutput ReadLineOrKey()
    {
        string retString = "";

        int curIndex = 0;
        do
        {
            ConsoleKeyInfo readKeyResult = Console.ReadKey(true);

            // handle Enter
            if (readKeyResult.Key == ConsoleKey.Enter)
            {
                ReadInput?.Invoke(retString);

                Console.WriteLine();
                return new ConsoleOutput(retString);
            }

            // handle backspace
            if (readKeyResult.Key == ConsoleKey.Backspace)
            {
                if (curIndex > 0)
                {
                    retString = retString.Remove(retString.Length - 1);

                    Console.Write(readKeyResult.KeyChar);
                    Console.Write(' ');
                    Console.Write(readKeyResult.KeyChar);

                    --curIndex;
                }
            }
            else if (readKeyResult.Key == ConsoleKey.Delete)
            {
                if (retString.Length - curIndex > 0)
                {
                    // Store current position
                    int curLeftPos = Console.CursorLeft;

                    // Redraw string
                    for (int i = curIndex + 1; i < retString.Length; ++i)
                        Console.Write(retString[i]);

                    // Remove last repeated char
                    Console.Write(' ');

                    // Restore position
                    Console.SetCursorPosition(curLeftPos, Console.CursorTop);

                    // Remove string
                    retString = retString.Remove(curIndex, 1);
                }
            }
            else if (readKeyResult.Key == ConsoleKey.RightArrow)
            {
                if (curIndex < retString.Length)
                {
                    ++Console.CursorLeft;
                    ++curIndex;
                }
            }
            else if (readKeyResult.Key == ConsoleKey.LeftArrow)
            {
                if (curIndex > 0)
                {
                    --Console.CursorLeft;
                    --curIndex;
                }
            }
            else if (readKeyResult.Key == ConsoleKey.Insert)
            {
                IsInserting = !IsInserting;
            }
#if DEBUG
            else if (readKeyResult.Key == ConsoleKey.UpArrow)
            {
                if (Console.CursorTop > 0)
                    --Console.CursorTop;
            }
            else if (readKeyResult.Key == ConsoleKey.DownArrow)
            {
                if (Console.CursorTop < Console.BufferHeight - 1)
                    ++Console.CursorTop;
            }
#endif
            else
            // handle all other keypresses
            {
                if (IsInserting || curIndex == retString.Length)
                {
                    retString += readKeyResult.KeyChar;
                    Console.Write(readKeyResult.KeyChar);
                    ++curIndex;
                }
                else
                {
                    // Store char
                    char c = readKeyResult.KeyChar;

                    // Write char at position
                    Console.Write(c);

                    // Store cursor position
                    int curLeftPos = Console.CursorLeft;

                    // Clear console from curIndex to end
                    for (int i = curIndex; i < retString.Length; ++i)
                        Console.Write(' ');

                    // Go back
                    Console.SetCursorPosition(curLeftPos, Console.CursorTop);

                    // Write the chars from curIndex to end (with the new appended char)
                    for (int i = curIndex; i < retString.Length; ++i)
                        Console.Write(retString[i]);

                    // Restore again
                    Console.SetCursorPosition(curLeftPos, Console.CursorTop);

                    // Store in the string
                    retString = retString.Insert(curIndex, new string(c, 1));

                    // Sum one to the cur index (we appended one char)
                    ++curIndex;
                }
            }

            if (char.IsControl(readKeyResult.KeyChar) &&
                readKeyResult.Key != ConsoleKey.Enter &&
                readKeyResult.Key != ConsoleKey.Backspace &&
                readKeyResult.Key != ConsoleKey.Tab &&
                readKeyResult.Key != ConsoleKey.Delete &&
                readKeyResult.Key != ConsoleKey.RightArrow &&
                readKeyResult.Key != ConsoleKey.LeftArrow &&
                readKeyResult.Key != ConsoleKey.Insert)
            {
#if DEBUG
                if (readKeyResult.Key == ConsoleKey.UpArrow || readKeyResult.Key == ConsoleKey.DownArrow)
                    continue;
#endif

                ReadKey?.Invoke(readKeyResult);

                Console.WriteLine();
                return new ConsoleOutput(readKeyResult);
            }
        }
        while (true);
    }
}

如你所见,我实现了插入、箭头控制、删除等。(Insert是一件很重要的事情,因为如果你用这段代码写任何文本,你会看到插入键提供的行为)。

以及使用示例:

代码语言:javascript
复制
internal class Program
{
    private static void Main(string[] args)
    {
        Console.Write("Write test string: ");
        var test = ConsoleOutput.ReadLineOrKey();

        if (test.IsKey())
            Console.WriteLine(test.KeyName);
        else
            Console.WriteLine($"Output string: {test.OutputString}");
        Console.Read();
    }
}

您可以随时更新on this link (这是我目前所在的lib的链接)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8789646

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档