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

时间:2014-06-25 14:47:53

标签: c# input console focus

我一直在尝试将数据发送到控制台窗口而没有焦点。我从这里使用了一个简单的键盘钩: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);

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

1 个答案:

答案 0 :(得分:0)

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