【问题标题】:How to send keys data to a Console window without having focus如何在没有焦点的情况下将键数据发送到控制台窗口
【发布时间】:2014-08-16 04:57:12
【问题描述】:

我一直试图在没有焦点的情况下将数据发送到控制台窗口。我在这里使用了一个简单的键盘挂钩:Capture keystroke without focus in console

我已经修改了该页面上答案提供的代码,以显示已按下键的 unicode 值;我的修改如下:

private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
    if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
    {
        var vkCode = Marshal.ReadInt32(lParam);

        var key = (Keys) vkCode;

        if (key == Keys.LShiftKey || key == Keys.RShiftKey)
            shift = true;

        if (key == Keys.RMenu)
            altgr = true;

        if (key == Keys.Return || key == Keys.Enter)
        {
            Console.WriteLine();
            input = "";
        }else if (key == Keys.Back)
        {
            if (input.Length > 0)
            {
                input = input.Substring(0, input.Length - 1);
                Console.Write("\b \b");
            }
        }
        else
        {
            input += GetCharsFromKeys(key);

            Console.Write(GetCharsFromKeys(key));
        }
    }

    if (nCode >= 0 && wParam == (IntPtr) WM_KEYUP)
    {
        var vkCode = Marshal.ReadInt32(lParam);

        var key = (Keys)vkCode;

        if (key == Keys.LShiftKey || key == Keys.RShiftKey)
            shift = false;

        if (key == Keys.RMenu)
            altgr = false;
    }
    return CallNextHookEx(_hookID, nCode, wParam, lParam);
}

无论窗口焦点如何,控制台都会写入正在键入的内容,这是预期的,但问题是我不知道如何允许输入和处理数据,就像您通常使用 Console.ReadLine( )。

我正在使用以下代码将程序放入消息循环中以使挂钩起作用:

_hookID = SetHook(_proc);
Application.Run();
UnhookWindowsHookEx(_hookID);

简而言之,我想做的是允许用户在控制台中输入数据,而不管窗口焦点如何。

【问题讨论】:

  • 控制台应用程序是否由您的进程启动?如果是,那么您可以在 ProcessStartInfo 中设置 RedirectStandardInput,获取 StandardInput 流并将字符写入其中。
  • @Gusman 控制台应用程序由用户启动,而不是其他进程。
  • 好的,控制台应用程序是您的控制台应用程序,我以为它是第三个应用程序。让我写一个回复。

标签: c# input console focus


【解决方案1】:

您可以用自己的标准输入流替换标准输入流,然后写入它。为此,请使用您的新流调用 Console.SetIn。

这是一个很小的例子:

    static void Main(string[] args)
    {

        MemoryStream ms = new MemoryStream();
        StreamReader sr = new StreamReader(ms);
        StreamWriter sw = new StreamWriter(ms);
        Console.SetIn(sr);


        sw.WriteLine("Hi all!");
        ms.Seek(0, SeekOrigin.Begin);
        string line = Console.ReadLine();

        Console.WriteLine(line);

    }

这里唯一的问题是您必须控制流的位置,如果控制台到达流的末尾,它将继续返回空值。

对于这些问题有许多解决方案,从在控制台应用程序级别处理 null 值到创建自定义 StreamReader,该 StreamReader 会锁定直到写入一行(控制台默认使用 SyncTextReader 类型的流,但它是私有的)。

【讨论】:

  • 知道如何将其应用于上述代码吗?当程序到达 Application.Run();它不允许我运行任何进一步的代码,因为它已进入消息循环。
  • 是的,在创建自己的流类型并将其设置为 Console.SetIn 而不是执行 Console.Write(Line) 之后,然后执行 YourStream.Write(Line)
猜你喜欢
  • 2020-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-21
  • 1970-01-01
相关资源
最近更新 更多