Sending hotkeys to program in background - c#

I want to make in my application, than when this application is in background, when I will click F10, the function with loop will be start.
This is my code:
namespace test
{
public partial class Form1 : Form
{
[DllImport("user32.dll")]
public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc);
[DllImport("user32.dll")]
public static extern bool UnregisterHotKey(IntPtr hWnd, int id);
public Form1() //(lub Form1_Load(object sender, System.EventArgs e))
{
RegisterHotKey(this.Handle,9000, 2, (int) Keys.F10);
InitializeComponent();
}
private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
UnregisterHotKey(this.Handle,9000);
UnregisterHotKey(this.Handle,9001);
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
switch (m.Msg)
{
case 0x312:
switch (m.WParam.ToInt32())
{
case 9000:
//code
break;
case 9001:
//code
break;
}
break;
}
}
}
}
But don't work :(
Can you help me please?

when I will click F10
Wrong key, you have to type Ctrl+F10. You passed 2 as the 3rd argument to RegisterHotKey(), that's MOD_CONTROL. Using const or enum declarations instead of raw literals help you fall in the pit of success.

Related

Not able to receive window message in c# .net

I want to send message to other process already running. What wrong...? why I am not able to receive messages
My sender code is as below
public partial class RegisterWindowMessage : Form
{
[DllImport("User32.dll", EntryPoint = "SendMessage")]
//private static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
private static extern int SendMessage(IntPtr hWnd, int Msg, string s, int i);
const int WM_SETTEXT = 0X000C;
public RegisterWindowMessage()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Process[] procs = Process.GetProcesses();
foreach (Process p in procs)
{
if (p.ProcessName.Equals("TaskScheduling"))
{
IntPtr hWnd = p.MainWindowHandle;
Thread.Sleep(1000);
SendMessage(hWnd, WM_SETTEXT, "This is the new Text!!!", 0);
MessageBox.Show("Inside");
}
}
}
private void button2_Click(object sender, EventArgs e)
{
}
}
My receiver code is
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
}
private void frmReceiver_KeyDown(object sender, KeyEventArgs e)
{
// this.lsvMsgList.Items.Add(e.KeyValue.ToString());
}
protected override void WndProc(ref Message m)
{
MessageBox.Show(m.Msg.ToString());
MessageBox.Show(m.LParam.ToString());
MessageBox.Show(m.WParam.ToString());
if (m.LParam.ToInt32() == 1)
{
}
else
{
base.WndProc(ref m);
}
}
}
I want to know why i am not able to receive message. Let me know where I am wrong

Console check for pressed keys like in monogame

In my console application, I would like to be able to detect for key presses somewhat like in mono, where you can get a list of the currently pressed keys and check if a key is on the list, or detect if a key is being pressed. My problem with using
if( Console.KeyAvailable ) k = Console.ReadKey( true ).Key;
is the fact that there will be a delay after I press the first key. You can see an example of this if you open notepad and hold down "A". A will be pressed, then a delay, and then A will be spammed.
How can I get keyboard input without the delay in between presses? I'm not afraid to use low level functions such as hooking into kernel32.dll
So I wrote some code, based off what I've read so far.
Step 1: Copy the following code into your console application. It must be STAThread or it will throw an error. Put in the commands you want to use in the switch statement. All other keys will be blocked by ReadKey(true).
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.IO;
using System;
using System.Windows.Forms;
using System.Windows.Input;
namespace ConsoleApplication10
{
class Program
{
[STAThread]
static void Main(string[] args)
{
KeyListener.RegisterHotKey(Keys.A);
KeyListener.HotKeyPressed += new EventHandler<HotKeyEventArgs>(KeyListener_HotKeyPressed);
while (true)
{
Console.ReadKey(true);
}
}
static void KeyListener_HotKeyPressed(object sender, HotKeyEventArgs e)
{
switch (e.Key)
{
case Keys.A:
{
Console.WriteLine("Do stuff");
return;
}
default:
return;
}
}
}
}
Step 2: Add a reference to System.Windows.Forms. You need this to have a hidden Form that is necessary for the message loop for the keyboard hook.
Step 3: Add the following static class. It does all the heavy lifting of the keyboard hooks for you, so you don't have to do it.
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;
namespace ConsoleApplication10
{
public static class KeyListener
{
public static event EventHandler<HotKeyEventArgs> HotKeyPressed;
public static int RegisterHotKey(Keys key, KeyModifiers modifiers)
{
_windowReadyEvent.WaitOne();
int id = System.Threading.Interlocked.Increment(ref _id);
_wnd.Invoke(new RegisterHotKeyDelegate(RegisterHotKeyInternal), _hwnd, id, (uint)modifiers, (uint)key);
return id;
}
public static int RegisterHotKey(Keys key)
{
_windowReadyEvent.WaitOne();
int id = System.Threading.Interlocked.Increment(ref _id);
_wnd.Invoke(new RegisterHotKeyDelegate(RegisterHotKeyInternal), _hwnd, id, (uint)KeyModifiers.None, (uint)key);
return id;
}
public static void UnregisterHotKey(int id)
{
_wnd.Invoke(new UnRegisterHotKeyDelegate(UnRegisterHotKeyInternal), _hwnd, id);
}
delegate void RegisterHotKeyDelegate(IntPtr hwnd, int id, uint modifiers, uint key);
delegate void UnRegisterHotKeyDelegate(IntPtr hwnd, int id);
private static void RegisterHotKeyInternal(IntPtr hwnd, int id, uint modifiers, uint key)
{
RegisterHotKey(hwnd, id, modifiers, key);
}
private static void UnRegisterHotKeyInternal(IntPtr hwnd, int id)
{
UnregisterHotKey(_hwnd, id);
}
private static void OnHotKeyPressed(HotKeyEventArgs e)
{
if (KeyListener.HotKeyPressed != null)
{
KeyListener.HotKeyPressed(null, e);
}
}
private static volatile MessageWindow _wnd;
private static volatile IntPtr _hwnd;
private static ManualResetEvent _windowReadyEvent = new ManualResetEvent(false);
static KeyListener()
{
Thread messageLoop = new Thread(delegate ()
{
Application.Run(new MessageWindow());
});
messageLoop.Name = "MessageLoopThread";
messageLoop.IsBackground = true;
messageLoop.Start();
}
private class MessageWindow : Form
{
public MessageWindow()
{
_wnd = this;
_hwnd = this.Handle;
_windowReadyEvent.Set();
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_HOTKEY)
{
HotKeyEventArgs e = new HotKeyEventArgs(m.LParam);
KeyListener.OnHotKeyPressed(e);
}
base.WndProc(ref m);
}
protected override void SetVisibleCore(bool value)
{
// Ensure the window never becomes visible
base.SetVisibleCore(false);
}
private const int WM_HOTKEY = 0x312;
}
[DllImport("user32", SetLastError = true)]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
[DllImport("user32", SetLastError = true)]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
private static int _id = 0;
}
public class HotKeyEventArgs : EventArgs
{
public readonly Keys Key;
public readonly KeyModifiers Modifiers;
public HotKeyEventArgs(Keys key, KeyModifiers modifiers)
{
this.Key = key;
this.Modifiers = modifiers;
}
public HotKeyEventArgs(IntPtr hotKeyParam)
{
uint param = (uint)hotKeyParam.ToInt64();
Key = (Keys)((param & 0xffff0000) >> 16);
Modifiers = (KeyModifiers)(param & 0x0000ffff);
}
}
[Flags]
public enum KeyModifiers
{
None = 0,
Alt = 1,
Control = 2,
Shift = 4,
Windows = 8,
NoRepeat = 0x4000
}
}
Step 4:
Now, there's still a delay. It's way more elegant, but you still have the operating system fighting you. So what to do?
You have two options.
a) You implement a timing option and you simply repeat the action for as long as a key is down on the timer tick event. You can either copy the code or merge it with the hotkey approach that I've given you.
See here for details: Removing the delay after KeyDown event?
private bool _moveUp;
private bool _moveDown;
private bool _moveLeft;
private bool _moveRight;
// You can add the Timer in the Winforms Designer instead if you like;
// The Interval property can be configured there at the same time, along
// with the Tick event handler, simplifying the non-Designer code here.
private System.Windows.Forms.Timer _movementTimer = new Timer { Interval = 100 };
public MainForm()
{
InitializeComponent();
_movementTimer.Tick += movementTimer_Tick;
}
private void movementTimer_Tick(object sender, EventArgs e)
{
_DoMovement();
}
private void _DoMovement()
{
if (_moveLeft) Player.MoveLeft();
if (_moveRight) Player.MoveRight();
if (_moveUp) Player.MoveUp();
if (_moveDown) Player.MoveDown();
}
// You could of course override the OnKeyDown() method instead,
// assuming the handler is in the Form subclass generating the
// the event.
public void MainForm_KeyDown(object sender, KeyEventArgs e)
{
if (e.IsRepeat)
{
// Ignore key repeats...let the timer handle that
return;
}
switch (e.KeyCode)
{
case Keys.Up:
_moveUp = true;
break;
case Keys.Down:
_moveDown = true;
break;
case Keys.Left:
_moveLeft = true;
break;
case Keys.Right:
_moveRight = true;
break;
}
_DoMovement();
_movementTimer.Start();
}
public void MainForm_KeyUp(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Up:
_moveUp = false;
break;
case Keys.Down:
_moveDown = false;
break;
case Keys.Left:
_moveLeft = false;
break;
case Keys.Right:
_moveRight = false;
break;
}
if (!(_moveUp || _moveDown || _moveLeft || _moveRight))
{
_movementTimer.Stop();
}
}
b) In your Main method, you get the delay setting, set the delay programmatically to the lowest setting, and on Application Exit, you set it back to its original setting.
See here for where to find it in the registry: https://superuser.com/questions/388160/keyboard-repeat-rate-repeat-delay-values-in-win7
And how to read/write to the registry: https://msdn.microsoft.com/en-us/library/microsoft.win32.registry_methods(v=vs.110).aspx
Note: With this approach, there's still a small delay. It's small, but it's there. Good luck.

C# Setting up a single key hotkey

I'm currently trying to set a single key as global hook. Howerver, I was perhaps wondering if it's possible to manipulate this code, so that a single button is set as a global hot key?
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[DllImport("user32.dll")]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);
[DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
const int B = 0x42;
const int MOD_SHIFT = 0x0004;
const int WM_HOTKEY = 0x0312;
private void Form1_Load(object sender, EventArgs e)
{
RegisterHotKey(this.Handle, 1, B + MOD_SHIFT, (int)Keys.X);
RegisterHotKey(this.Handle, 2, B + MOD_SHIFT, (int)Keys.Y);
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
UnregisterHotKey(this.Handle, 1);
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_HOTKEY && (int)m.WParam == 1)
MessageBox.Show("Hotkey X pressed.");
if (m.Msg == WM_HOTKEY && (int)m.WParam == 2)
MessageBox.Show("Hotkey Y pressed.");
base.WndProc(ref m);
}
}
}

How to detect a keybd_event without focus

I'm working on a program, who need to detect when the user press the keyboard or use his mouse, even if the program is minimized or not focused.
I think I have to use the windows API, keybd_event (user32), but I don't know how to use the "listener" of this event. I have something like that:
[DllImport("user32.dll")]
static extern void keybd_event(byte bVk, byte bScan, uint dwFlags,UIntPtr dwExtraInfo);
void PressKey(byte keyCode)
{
//My code here
}
I did some research, but it's the first time I have to use DllImport, so I don't know how to continue ...
Thanks
(Ps:Sorry about my bad English, this is not my native language :) )
(PPs: I've read all of your answers, but it takes a while to read every link, so I'll work on it tonight, but I think I will find the answer. Anyway, thanks for the links everybody ;) )
Edit: So I just finished my code and it's work :) It looks something like:
[DllImport("user32.dll")]
public static extern Boolean GetLastInputInfo(ref tagLASTINPUTINFO plii);
public struct tagLASTINPUTINFO
{
public uint cbSize;
public Int32 dwTime;
}
private void timerTemps_Inactif_Tick(object sender, EventArgs e)
{
tagLASTINPUTINFO LastInput = new tagLASTINPUTINFO();
Int32 IdleTime;
LastInput.cbSize = (uint)Marshal.SizeOf(LastInput);
LastInput.dwTime = 0;
if (GetLastInputInfo(ref LastInput))
{
IdleTime = System.Environment.TickCount - LastInput.dwTime;
if (IdleTime > 10000)
{
//My code here
}
}
}
Thanks for the help guys ;)
You will need to hook into Windows OS with SetWindowsHookEx function. You should read the article Keyloggers: How they work and how to detect them posted by SecureList to get a understanding ofthe process.
I have always got a good performance by using RegisterHotKey/UnregisterHotKey functions. Sample code:
[DllImport("User32")]
public static extern bool RegisterHotKey(
IntPtr hWnd,
int id,
int fsModifiers,
int vk
);
[DllImport("User32")]
public static extern bool UnregisterHotKey(
IntPtr hWnd,
int id
);
public const int MOD_SHIFT = 0x4;
public const int MOD_CONTROL = 0x2;
public const int MOD_ALT = 0x1;
public const int WM_HOTKEY = 0x312;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_HOTKEY && m.WParam == (IntPtr)0)
{
IntPtr lParamCTRLA = (IntPtr)4259842;
IntPtr lParamB = (IntPtr)4325376;
if (m.LParam == lParamCTRLA)
{
MessageBox.Show("CTRL+A was pressed");
}
else if (m.LParam == lParamB)
{
MessageBox.Show("B was pressed");
}
}
base.WndProc(ref m);
}
private void Form1_Load(object sender, EventArgs e)
{
this.FormClosing += new FormClosingEventHandler(Form1_FormClosing);
RegisterHotKey(this.Handle, 0, MOD_CONTROL, (int)Keys.A);
RegisterHotKey(this.Handle, 0, 0, (int)Keys.B);
}
private void Form1_FormClosing(Object sender, FormClosingEventArgs e)
{
UnregisterHotKey(this.Handle, 0);
}
You can "register" as many keys (or combination of keys) as you want by emulating the shown structure. All the registered keys will get inside the condition if (m.Msg == WM_HOTKEY && m.WParam == (IntPtr)0); if they are pressed at all (independently upon the program currently being selected). The easiest way to know the specific key/combination being pressed is relying on m.LParam (I got the two values I am including after a quick test with the given keys). You can do a quick research to find out a list of LParam or further constant modifiers (wheel of the mouse, for example).
The final code:
[DllImport("user32.dll")]
public static extern Boolean GetLastInputInfo(ref tagLASTINPUTINFO plii);
public struct tagLASTINPUTINFO
{
public uint cbSize;
public Int32 dwTime;
}
private void timerTemps_Inactif_Tick(object sender, EventArgs e)
{
tagLASTINPUTINFO LastInput = new tagLASTINPUTINFO();
Int32 IdleTime;
LastInput.cbSize = (uint)Marshal.SizeOf(LastInput);
LastInput.dwTime = 0;
if (GetLastInputInfo(ref LastInput))
{
IdleTime = System.Environment.TickCount - LastInput.dwTime;
if (IdleTime > 10000)
{
//My code here
}
}
}

Use of NativeWindow for ComboBox causes exception in Dispose-method

In C# Windows.Forms I want to intercept the paste-windowmessage for a combobox. As this doesn't work by overriding the WndProc-method of the combobox, because I would need to override the WndProc of the textbox inside the combobox, I decided to create a custom class of type NativeWindow which overrides the WndProc. I assign the handle and release it, when the combobox-handle gets destroyed. But when Dispose for the combobox is called the problem is that I get an InvalidOperationException saying that an invalid cross-thread operation occured and that the combobox was accessed from a thread other than the thread it was created on. Any ideas what is going wrong here?
In the following you'll see, how my classes look like:
public class MyCustomComboBox : ComboBox
{
private WinHook hook = null;
public MyCustomComboBox()
: base()
{
this.hook = new WinHook(this);
}
private class WinHook : NativeWindow
{
public WinHook(MyCustomComboBox parent)
{
parent.HandleCreated += new EventHandler(this.Parent_HandleCreated);
parent.HandleDestroyed += new EventHandler(this.Parent_HandleDestroyed);
}
protected override void WndProc(ref Message m)
{
// do something
base.WndProc(ref m);
}
private void Parent_HandleCreated(object sender, EventArgs e)
{
MyCustomComboBox cbx = (MyCustomComboBox)sender;
this.AssignHandle(cbx.Handle);
}
private void Parent_HandleDestroyed(object sender, EventArgs e)
{
this.ReleaseHandle();
}
}
}
Per Hans' suggestion, I modified the code to use CB_GETCOMBOBOXINFO from one of his own examples.
public class PastelessComboBox : ComboBox {
private class TextWindow : NativeWindow {
[StructLayout(LayoutKind.Sequential)]
private struct RECT {
public int Left;
public int Top;
public int Right;
public int Bottom;
}
private struct COMBOBOXINFO {
public Int32 cbSize;
public RECT rcItem;
public RECT rcButton;
public int buttonState;
public IntPtr hwndCombo;
public IntPtr hwndEdit;
public IntPtr hwndList;
}
[DllImport("user32.dll", EntryPoint = "SendMessageW", CharSet = CharSet.Unicode)]
private static extern IntPtr SendMessageCb(IntPtr hWnd, int msg, IntPtr wp, out COMBOBOXINFO lp);
public TextWindow(ComboBox cb) {
COMBOBOXINFO info = new COMBOBOXINFO();
info.cbSize = Marshal.SizeOf(info);
SendMessageCb(cb.Handle, 0x164, IntPtr.Zero, out info);
this.AssignHandle(info.hwndEdit);
}
protected override void WndProc(ref Message m) {
if (m.Msg == (0x0302)) {
MessageBox.Show("No pasting allowed!");
return;
}
base.WndProc(ref m);
}
}
private TextWindow textWindow;
protected override void OnHandleCreated(EventArgs e) {
textWindow = new TextWindow(this);
base.OnHandleCreated(e);
}
protected override void OnHandleDestroyed(EventArgs e) {
textWindow.ReleaseHandle();
base.OnHandleDestroyed(e);
}
}

Categories

Resources