Read keyboard inputs without always having my console application focused? - c#

is it possible to read keyboard inputs without always having my console application focused?
I would like to do something with a button without always going to the console.
Doesn't that somehow work with events? Unfortunately I only found unsightly solutions with Forms.
This solution from #Siarhei Kuchuk didn't help me either:
Global keyboard capture in C# application
The OnKeyPressed event is activated but is not triggered.
Does somebody has any idea?

That's possible. You may google "keyloggers" and find many examples but I'm gonna give you a very rough bare boned one.
But first you have to add a refrence to System.Windows.Forms.dll for this to work
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Threading;
namespace ConsoleApp1
{
class Program
{
[DllImport("User32.dll")]
private static extern short GetAsyncKeyState(System.Int32 vKey);
static void Main(string[] args)
{
while (true)
{
Thread.Sleep(500);
for (int i = 0; i < 255; i++)
{
int state = GetAsyncKeyState(i);
if (state != 0)
{
string pressedKey= ((System.Windows.Forms.Keys)i).ToString();
switch (pressedKey)
{
default:
Console.WriteLine("You have pressed: " + pressedKey);
break;
}
}
}
}
}
}
}

Related

Calling static class member

I have the following code and cant figure out how to call the function (GetPageCount), which by way i found here. I have tried more than several methods how ever none have worked. Would appreciated some assistance with the line the calls the function and information on what i need to brush up on, i though I had preformed this previously. Thank you in advance.
using System;
using System.Drawing;
using System.Drawing.Printing;
namespace ConsoleApp1
{
class Program
{
public static int GetPageCount(PrintDocument printDocument)
{
int count = 0;
printDocument.PrintController = new PreviewPrintController();
printDocument.PrintPage += (sender, e) => count++;
printDocument.Print();
return count;
}
static void Main(string[] args)
{
var testPrint = GetPageCount (#"c:\temp\test.msg");
Console.WriteLine(testPrint);
}
}
}
You’re trying to pass a string to a method that is expecting a PrintDocument object.
I’d also check out the MSDN documentation on this, available here: PrintDocument

C#, console, how to check if key is pressed, and change variables in real time accordingly

Edited 2017 07 30 13:49
The main difference between this and the other question is that:
How to detect 2 pressed key at the same time?
For example: a program that display "2" on the screen only if key A and B are pressed at the same time. When either A or B or both are released, it display "1"
The following program does not work, because ReadKey need to wait.
if (Console.KeyAvailable){} Also doesn't work, because it only allow one key to be read, not if multiple is pressed at the same time.
In short, I wish someone can tell me a function that, when used, immediately out put a Boolean value depend on if a certain key is pressed without letting the program to wait
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace ConsoleApp9
{
class Program
{
static void Main(string[] args)
{
int number = 2;
while (true)
{
Console.Clear();
if (Console.ReadKey(true).Key == ConsoleKey.B & Console.ReadKey(true).Key == ConsoleKey.A)
{
Console.Write(2);
}
else
{
Console.Write(1);
}
}
}
}
}
I am new to C# right now I wish to know if there is a way to check if key is pressed, and change variables in real time accordingly.
I have a program that out put an number after a key is pressed, however, its update rate is too slow and it can only check for one key at a time. (It can only recognize A or B if I am pressing AB at the same time.)
Is there a function that out put an Boolean value and does not block the code like Console.ReadKey()? (or something similar) For example "function(A)" will out put a "true" if A is pressed at the time this function is used. If not, it out put a "false" and program proceed to the next line.
In short can you tell me how to program a console, so that it will have a list of variables that reflect keys pressed in real time?
(Using while(true) loop, at anytime I am pressing the key A. Program write variable KeyA=true, at any time it is not pressed, KeyA=false)
Tried event, but can not get it to work. ("Does not exist" error during compilation)
This is the program I am using.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace ConsoleApp9
{
class Program
{
static void Main(string[] args)
{
int number = 2;
while (true)
{
if (Console.KeyAvailable)
{
var key = Console.ReadKey();
Console.Write((int)key.KeyChar);
}
}
}
}
}
See this code:
class Program
{
[System.Runtime.InteropServices.DllImport("User32.dll")]
public static extern short GetAsyncKeyState(int vKey);
static void Main(string[] args)
{
while (GetAsyncKeyState('Q') == 0)
{
short result = GetAsyncKeyState('A');
if (result < 0 && (result & 0x01) == 0x01)
Console.WriteLine("A pressed and up");
}
}
}
Press Q to quit or A to see a message that is was pressed. You can also use the GetKeyboardState API to retrieve information on all keys at once. Be sure to read the documentation to have a proper understanding of return values and usage.

handle native external process windows events from c#

I'm starting a process (namely gnuplot.exe) from within a C# application.
The process can open some window and for that process i'd like to intercept the events of:
opened window
closed window
focused window
The basic idea is to handle if the user closes some windows or changes the active window and so on, referring only to the started process. In other word, i don't want to handle others focus changes or closed windows events which are not thrown by a gnuplot window.
Can you help me? Is it possible to avoid polling? Which api should i refer to? Can you paste/link an mwe or some example code?
Thank you in advance
Update
As suggested by Eric Brown I tried this way, but still not works. Can you help me to detect where am I wrong?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System;
using System.Windows;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Windows.Automation;
namespace WinApiEvents
{
class Program
{
public static void Main()
{
Process gp = new Process();
gp.StartInfo.FileName = #"C:\Software\gp463-win32\gnuplot\bin\gnuplot.exe";
gp.StartInfo.UseShellExecute = false;
gp.StartInfo.RedirectStandardInput = true;
gp.StartInfo.CreateNoWindow = true;
gp.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
gp.Start();
AutomationElement targetElement =
AutomationElement.FromHandle(gp.Handle);
StructureChangedEventHandler structChangedHandler =
new StructureChangedEventHandler(OnGnuplotWindowStructureChanged);
Automation.AddStructureChangedEventHandler(
targetElement, TreeScope.Element, structChangedHandler);
AutomationEventHandler focusHandler =
new AutomationEventHandler(OnGnuplotWindowFocusGained);
Automation.AddAutomationEventHandler(
AutomationElement.AutomationFocusChangedEvent, targetElement, TreeScope.Element, focusHandler);
StringBuilder sb = new StringBuilder();
sb.AppendLine("set term wxt 1 enhanced");
sb.AppendLine("plot sin(x)");
gp.StandardInput.WriteLine(sb.ToString());
gp.StandardInput.Flush();
sb.Clear();
sb.AppendLine("set term wxt 2 enhanced");
sb.AppendLine("plot cos(x)");
gp.StandardInput.WriteLine(sb.ToString());
gp.StandardInput.Flush();
sb.Clear();
sb.AppendLine("set term wxt 3 enhanced");
sb.AppendLine("plot atan(x)");
gp.StandardInput.WriteLine(sb.ToString());
gp.StandardInput.Flush();
sb.Clear();
MessageBox.Show("Click to exit.");
}
private static void OnGnuplotWindowStructureChanged(object src, StructureChangedEventArgs e)
{
Console.WriteLine("structure changed window, id=" + e.EventId.ProgrammaticName);
}
private static void OnGnuplotWindowFocusGained(object src, AutomationEventArgs e)
{
Console.WriteLine("focused window, id=" + e.EventId.ProgrammaticName);
}
}
}
Thank you in advance
I would use the UI Automation framework for this.
I assume you have (or can get) the gnuplot window handle. Once you have that, you can get the UI Automation element for that window, and set up FocusChanged event handlers, and StructureChanged handlers to detect subwindow opening & closing. The WindowClosed event will tell you if the gnuplot window itself closes. (You can use this on subwindows as well, but you'll still need to listen for StructureChanged events to detect subwindow open events.)

Windows Forms\Console - Make Your KeyBord Type Words. Or Your Mouse to be clicked

Well,
I am not sure if someone already asked this qusiton before. I was trying to look arround but noting came up. (if there is, please show me and close this. I am very sorry!)
For a few days now I am looking for a way that when I click on a button in my windows form in C# it will copy paste something to somewhere else.
The best way to expline this:
Lets say I got a Ms Word open, and I want that when I will click on a button in my windows form, after 5 seconds, it will write something in my word office. Of course I will open the Ms Word by my self.
Another thing: is how to make your mouse click on hes key?
edit:
When i use this code --
int forhow = int.Parse(textBox1.Text);
for(int i = 0;i <forhow; i++)
{
i++;
SendKeys.Send("ספאמר על ידי פריזו - ספאמר על גירסא ראשונה");
//ספאמר על ידי פThread.Sleep(1200);
//Thread.Sleep(5000);
SendKeys.Send("{ENTER}");
}
well, its should do it only 1 time. is i write 1 in the text box. but, it is doing it about 50 times. and the stop. any one knows why? + . if you lick on the button, the program stops to work until she compltite all the "Send:".
I couldn't find a way to force a mouse click, but you cam mimic the keyboard using the SendKeys class. All code that is not in between "//{" and "//}" was generated by visual studio.
Hope this helps!
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
//{
using System.Diagnostics;
//}
namespace ClickToWord
{
public partial class Form1 : Form
{
//{
Process imsWord = new Process();
Timer tempTime = new Timer();
int counter = 0;
//}
public Form1()
{
InitializeComponent();
//{
imsWord.StartInfo.FileName = #"";
//Inside the "" put the path to the file/application. No need to escape it, because of the "#"
tempTime.Interval = 1000;
//The interval in miliseconds
tempTime.Tick += new EventHandler(tempTime_Tick);
//}
}
void tempTime_Tick(object sender, EventArgs e)
{
//{
char send = 'a';
send += (char)(counter % 26);
SendKeys.Send(send.ToString());
counter++;
//An example of looping through the alphabet. Send any string via SendKeys, and it will act as if the keyboard ent it.
//This mimics keyboard strokes, and requires the document to have focus. That is why it is not the ideal way to do this.
//To programmatically communicate with Word, use the Microsoft Word Object Model library.
//tempTime.Enabled = false;
//}
}
private void button1_Click(object sender, EventArgs e)
{
//{
imsWord.Start();
//Starts the proccess
tempTime.Enabled = true;
//Starts the timer
//}
}
}
}

How to delay program for a certain number of milliseconds, or until a key is pressed?

I need to delay my program's execution for a specified number of milliseconds, but also want the user to be able to escape the wait when a key is pressed. If no key is pressed the program should wait for the specified number of milliseconds.
I have been using Thread.Sleep to halt the program (which in the context of my program I think is ok as the UI is set to minimise during the execution of the main method).
I have thought about doing something like this:
while(GetAsyncKeyState(System.Windows.Forms.Keys.Escape) == 0 || waitTime > totalWait)
{
Thread.Sleep(100);
waitTime += 100;
}
As Thread.Sleep will wait until at least the time specified before waking the thread up, there will obviously be a large unwanted extra delay as it is scaled up in the while loop.
Is there some sort of method that will sleep for a specified amount of time but only while a condition holds true? Or is the above example above the "correct" way to do it but to use a more accurate Sleep method? If so what method can I use?
Thanks in advance for your help.
Edit ---- Possible Idea...
DateTime timeAtStart = DateTime.Now;
int maxWaitTime = 15000;
while (true)
{
if (GetAsyncKeyState(System.Windows.Forms.Keys.Escape) != 0)
{
break;
}
if ((DateTime.Now - timeAtStart).TotalMilliseconds >= maxWaitTime)
{
break;
}
}
This doesn't use any sort of timer but looks like it could work, any suggestions?
Edit 2: The above works for me and now allows me to break the wait when escape is pressed. I have noticed the delay is more accurate than using Thread.Sleep too!
Consider reversing the concepts... instead of delaying it for a certain time, think about starting execution in a certain time, or when a key is pressed.
Start a Windows Forms timer with a tick handler which will kick off whatever you want to happen, and also a key event handler which will start it and stop the timer.
First sample is using Timer, ManuelResetEvent and Global Keyboard hook:
I did not include keyboard hook code because it's too large. You can find it here.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;
namespace WindowsFormsApplication1
{
static class Program
{
private static System.Threading.Timer _timer;
private static ManualResetEvent _signal;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
_signal = new ManualResetEvent(false);
_timer = new System.Threading.Timer(Timer_Signaled, null, 15000, 0);
_signal.WaitOne();
_signal.Reset();
Application.Run(new Form1());
}
private static void Timer_Signaled(object state)
{
_signal.Set();
}
}
}
When you hook to keyboard and ESC is pressed, simply call: _signal.Set(). This first sample is just to give you an idea.
Second sample:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1
{
static class Program
{
[DllImport("user32.dll")]
static extern short GetAsyncKeyState(System.Windows.Forms.Keys vKey);
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
int maxWaitTime = 15000;
int tc = System.Environment.TickCount;
while (true)
{
System.Threading.Thread.Sleep(1000);
if (System.Environment.TickCount - tc > maxWaitTime)
{
break;
}
if (GetAsyncKeyState(Keys.Escape) > 0)
{
break;
}
}
Application.Run(new Form1());
}
}
}
EDITED:
First sample is more reliable as keyboard hook use callback to inform which key was pressed. Second sample works like 'Pull' and it can happen not every key press will be collected.
Looking at your code, I'm assuming you're using Windows Forms for the UI.
There are many ways to solve your issue, but given the framework the easiest that comes to my mind is:
Blocking your UI (i.e. : this.Enabled = false)
Setting up a timer (i.e.: timer.Tick += ContinueUITimer();)
Setting up a keyboard handler (i.e.: this.KeyDown += ContinueUIKeyboard)
With the ContinueUI functions like this:
void ContinueUIXxx(...)
{
timer.Tick -= ContinueUITimer;
this.KeyDown -= ContinueUIKeyboard;
this.Enabled = true;
... whatever else in the continuation;
}

Categories