I made a Form and added a few buttons.
But instead want to press ctrl+NumpadKey1 to do exactly what the buttons would do.
Thus I need to access the program while it's in the background.
Does anyone have any ideas?
I already got the code for when the form is in the front.
Try using global hooks. This article explain how to do this. In short you have to set up hook:
[DllImport(“user32.dll”, CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
On the end you have to unhook:
[DllImport(“user32.dll”, CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
And this is how you can create handler:
private static LowLevelKeyboardProc _proc = HookCallback;
private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) {
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN) {
int vkCode = Marshal.ReadInt32(lParam);
Console.WriteLine((Keys)vkCode);
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
Related
I made a very simple Hook codes (I'm a beginner).
I opened Notepad and tested.
If I press ANY key it make a beep and printed itself.
Except "x" key, it is a terminator key.
Question :
I do not want to see "x" key printed. I just quit the program. What do I have to do ?
namespace HookingStudy
{
class HookingClass
{
private const int WM_KEYDOWN = 0x0100;
private static LowLevelKeyboardProc _proc = hookCallBack;
private static IntPtr _hookID = IntPtr.Zero;
public static void Main()
{
Beep(1111, 222);
_hookID = SetHook(_proc);
Application.Run();
}
private static IntPtr hookCallBack(int nCode, IntPtr wParam, IntPtr lParam)
{
if( nCode >= 0 && wParam == (IntPtr) WM_KEYDOWN )
{
int vkCode = Marshal.ReadInt32(lParam);
if( vkCode.ToString() == "88" ) // 88 ("x" key)
{
Beep(7777, 222);
UnhookWindowsHookEx(_hookID);
Process.GetCurrentProcess().Kill();
}
Beep(2222, 55);
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
private static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using( Process curProcess = Process.GetCurrentProcess() )
using( ProcessModule curModule = curProcess.MainModule )
{
return SetWindowsHookEx(13, proc, GetModuleHandle(curModule.ModuleName), 0);
}
}
private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("KERNEL32.DLL")]
extern public static void Beep(int freq, int dur);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
}
}
I do not want to see the terminator x printed at Notepad
Then do not call next hook in chain:
return CallNextHookEx(_hookID, nCode, wParam, lParam);
The idea of hooking it to install own handler prior existing handlers (afair from winapi). By intercepting (like you are doing it already) you are not only listening, but still invoking previous handlers with that call.
Try something like (untested):
if( vkCode == 88)
{
...
return 0;
}
I'm trying to write a hook into MS Excel using VSTO's, and I'm really close to what I need, but I have a minor issue.
I've used the low-level WINAPI calls to get the Keyboard events and check for the key-strokes (which works well).
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, KeyCaptureDelegate lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr KeyCaptureCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0)
{
int pointerCode = Marshal.ReadInt32(lParam);
bool result = false;
if (wParam == (IntPtr)WM_KEYDOWN)
{
if (KeyDown != null)
{
result = KeyDown(pointerCode);
}
}
//if (result)
//return IntPtr.Zero;
}
return CallNextHookEx(_keyCaptureHook, nCode, wParam, lParam);
}
Everything is hooked up and working well (using SetWindowsHookEx) and my code gets called via KeyDown without any issues. The only problem is that I'm trying to override a default command in Excel, i.e. Ctrl+Shift+1. This causes the default functionality to occur.
In my code, result returns whether or not the behavior should be overwritten (i.e. use my new behavior, rather than default). I had hoped, perhaps, that returning IntPtr.Zero would break and remove the keys from the pump, but that seemed to not do anything.
Is there a way to block the other (default) behavior? I would imagine that by canceling/handling the event (like we can in WinForms/WPF), there should be some way to prevent the key stroke from migrating further into Excel. Any thoughts?
So, I needed to make a few minor changes:
private delegate IntPtr KeyCaptureDelegate(int nCode, IntPtr wParam, IntPtr lParam);
became:
private delegate int KeyCaptureDelegate(int nCode, IntPtr wParam, IntPtr lParam);
and
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
became:
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
Which allowed me to rewrite it as:
private static int KeyCaptureCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0)
{
int pointerCode = Marshal.ReadInt32(lParam);
bool result = false;
if (wParam == (IntPtr)WM_KEYDOWN)
{
if (KeyDown != null)
{
result = KeyDown(pointerCode);
}
}
if (result)
{
return 1;
}
}
return CallNextHookEx(_keyCaptureHook, nCode, wParam, lParam);
}
I am using Keyboard Low Level hooks in a desktop application to monitor user activity. Code i am using for hooks is give below.
In this code (upto my knowledge) when I have to start monitoring user activity I call SetHook() this will install hook and I can monitor keys pressed on keyboard. When I want to stop capturing keys i just call UnHook() method.
Problem is when my application starts (SetHook() method is not called yet) my application install hooks automatically and it slows down system. System hangs for for 2-3 seconds every 1 mint.
To diagnose the problem I commented out all the below mentioned code and installed application. Now system works absolutely fine.
I am not sure why is this happening?
Why my application start capturing keys even I did not called SetHook() method yet?
Is there is any other way to capture global keys without using hooks?
Code for Hooks:
public static class WinKeyCapture5 {
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private static LowLevelKeyboardProc _proc = HookCallback;
public static DateTime LastKeyPressTime;
public static void SetHook()
{
SetHook(_proc);
}
public static void UnHook()
{
UnhookWindowsHookEx(_hookID);
}
private static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
}
}
private static IntPtr _hookID = IntPtr.Zero;
private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
//if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
//{
int vkCode = Marshal.ReadInt32(lParam);
//if (vkCode == 44)
//ScreenCapture.Load();
LastKeyPressTime = System.DateTime.Now;
//}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
}
I made a simple hook keyboard in C#, so i have this following code :
private static IntPtr hKeyboardHook = IntPtr.Zero;
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x100;
private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
private static extern int UnhookWindowsHookEx(IntPtr idHook);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32")]
private static extern int ToAscii(int uVirtKey, int uScanCode, byte[] lpbKeyState, byte[] lpwTransKey, int fuState);
[DllImport("user32")]
private static extern int GetKeyboardState(byte[] pbKeyState);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern short GetKeyState(int vKey);
private delegate int HookProc(int nCode, int wParam, IntPtr lParam);
[DllImport("kernel32.dll")]
public static extern IntPtr GetModuleHandle(string lpModuleName);
private static LowLevelKeyboardProc _proc = HookCallback;
public void initialization()
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, _proc, GetModuleHandle(curModule.ModuleName), 0);
}
}
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
if (vkCode >= 32 && vkCode < 160)
Console.Write((Keys)vkCode);
if (vkCode == 13)
Console.WriteLine("\n");
}
return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
}
It works fine with no problem !! my program grip all key pressed in other program and write it on the console.
But i want to have the name of the program where the key is pressed, and i don't know how i can do that.
Anyone can help me ?
You are using a low-level hook (WH_KEYBOARD_LL). Low-level hooks are dispatched before the window manager decides which program will receive the message. Therefore, there is no "name of the program where the key is pressed" because the window manager hasn't yet decided which program the keypress will be delivered to. (You can try to guess by calling GetForegroundWindow.)
(Just curious: What is the ultimate problem you're trying to solve by using a keyboard hook? Maybe there's a better way. I hope you're not writing a keylogger.)
I will be grateful to anybody who could help!
I'm using the InterceptKeys class below to change some of the keys. For example when I type the open bracket key "[", I want to change this to "ë" (whenever I type in my computer, not a particular program).
I use a SendKey.Send("ë"); whenever the "[" is typed, but the problem is that after "ë" alsot the "[" is typed.
Is it possible to replace the "[" with "ë" or any key, or cancel the "[" and just send "ë"?
class InterceptKeys
{
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private static LowLevelKeyboardProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
public static void Main()
{
_hookID = SetHook(_proc);
Application.Run();
UnhookWindowsHookEx(_hookID);
}
private static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
GetModuleHandle(curModule.ModuleName), 0);
}
}
private delegate IntPtr LowLevelKeyboardProc(
int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(
int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
//Console.WriteLine((Keys)vkCode);
if (vkCode == (int)Keys.OemOpenBrackets))
{
SendKeys.Send("ë");
}
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
}
Return 1 if you handled the key instead of calling CallNextHookEx.
IE, HookCallback() should look like this
private static IntPtr HookCallback(
int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
//Console.WriteLine((Keys)vkCode);
if (vkCode == (int)Keys.OemOpenBrackets))
{
SendKeys.Send("ë");
return 1;
}
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}