C# 如何在没有焦点的情况下将密钥数据发送到控制台窗口

C# 如何在没有焦点的情况下将密钥数据发送到控制台窗口,c#,input,console,focus,C#,Input,Console,Focus,我一直在尝试将数据发送到控制台窗口,但它没有焦点。我在这里使用了一个简单的键盘挂钩: 我修改了该页面答案中提供的代码,以显示已按下键的unicode值;我的修改如下: private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) { if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN) { var vkCode

我一直在尝试将数据发送到控制台窗口,但它没有焦点。我在这里使用了一个简单的键盘挂钩:

我修改了该页面答案中提供的代码,以显示已按下键的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);

简而言之,我想做的是允许用户向控制台输入数据,而不考虑窗口焦点。

您可以用自己的输入流替换标准输入流,然后写入。为此,请使用新流调用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);

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


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

控制台应用程序是由您的进程启动的吗?如果是,则您可以在ProcessStartInfo中设置RedirectStandardInput,获取StandardInput流并将字符写入其中。@Gusman控制台应用程序是由用户启动的,而不是由另一个进程启动的。好的,控制台应用程序是您的控制台应用程序,我以为它是第三个应用程序。让我写一个回复。你知道我将如何把这个应用到上面提到的代码中吗?当程序到达Application.Run()时;它不允许我运行任何进一步的代码,因为它已进入消息循环。是的,在创建您自己的流类型并将其设置为Console.SetIn而不是Console.Write(Line)之后,再执行您的stream.Write(Line)