问题
I've been trying to send data to a console window without it having focus. I've used a simple Keyboard Hook from here: Capture keystroke without focus in console
I've modified the code provided from the answer on that page to display the unicode values of keys that have been pressed; my modifications are as follows:
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);
}
The console does write what is being typed regardless of window focus, which is what is intended, however the issue is I have no idea how to allow the input and processing of data, like you would normally do using Console.ReadLine().
I am using the following code to put the program in a message loop for the hook to work:
_hookID = SetHook(_proc);
Application.Run();
UnhookWindowsHookEx(_hookID);
In a nutshell, what I want to do is allow users to input data to the console regardless of window focus.
回答1:
You can replace the standard input stream with your own and then write to it. To do that call Console.SetIn with your new stream.
Here is a very little example:
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);
}
Only problem here is you must control the stream's position and if the Console reaches the end of the stream it will continue returning a null value.
There are many solutions for those problems, from handling the null values at the console app level to creating a custom StreamReader which locks until a line has been written (Console uses by default a stream of type SyncTextReader, but it's private).
来源:https://stackoverflow.com/questions/24411887/how-to-send-keys-data-to-a-console-window-without-having-focus