|
|
Comments and Discussions
|
|
 |
|

|
The sample works fine but in more sophisticated mdi interface you get a CallbackOnCollectedDelegate Exception.
To avoid this porblem just change code.
Replace
public void hook() {
IntPtr hInstance = LoadLibrary("User32");
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, hInstance, 0);
}
by
public void hook() {
IntPtr hInstance = LoadLibrary("User32");
// Avoid CallbackOnCollectedDelegate Exception
// when calling delegates from unmanaged code
hkbProc = new keyboardHookProc(hookProc);
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, hkbProc, hInstance, 0);
}
Jean-Michel Grange
|
|
|
|

|
it work.but you have to declare hkbProc before hook()'s function.
like this:
private keyboardHookProc _hookCallback;
public void hook()
{
_hookCallback = new keyboardHookProc(hookProc);
_handleToHook = SetWindowsHookEx(
_hookType,
_hookCallback,
Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]),
0);
}
و این منم زنی تنها در آستانه فصلی سرد...
|
|
|
|

|
I know it's old, but thank you for this modification!
This code is only useful in "sophisticated" application with a lot of forms,
so this revision was needed.
|
|
|
|

|
This is the simplest and neatest hook code I have seen. Can you make one like that to hook keyboards too?
|
|
|
|

|
Thanks StormySpike...
Helped me to learn a lot..
|
|
|
|

|
can also do Ctrl + alt + i? :(
|
|
|
|

|
Control.Modifiers always is None in this case
|
|
|
|

|
How do you add characters to the hook like danish æ, ø and å. Or other european special characters?
|
|
|
|

|
Is it possible to do with all keys? Also KeyPress event would be nice
|
|
|
|

|
foreach (System.Windows.Forms.Keys item in Enum.GetValues(typeof(System.Windows.Forms.Keys)))
{
gkh.HookedKeys.Add(item);
}
|
|
|
|

|
error garbage collected delegate but solution in ocmments
|
|
|
|

|
it crash when we type very fast
|
|
|
|

|
Is there a way to capture a key combination like CTRL+ALT+A, where those three keys are pressed simultaneously?
|
|
|
|

|
Have a look at your marshalling! (Attributes) Your code can lead to some (seldom but nasty) errors.
So sorry for the bad vote but your code seems to be reused by a lot of people, i will revote if you improve your code.
A good site is: http://www.pinvoke.net[^]
Maybe you are also interested in the way I get the Instance handle for the process containing the callback.
Have a look at the code I use for a keyboard hook:
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Common
{
#region CLASS GlobalKeyboardHook
public class GlobalKeyboardHook
{
#region TYPES
#region CLASS KeyboardHookStruct
[StructLayout(LayoutKind.Sequential)]
class KeyboardHookStruct
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
#endregion
#region DELEGATE HookProc
protected delegate int HookProc(int nCode, int wParam, IntPtr lParam);
#endregion
#endregion
#region CONSTANTS
const int WH_KEYBOARD_LL = 13;
const int WH_KEYBOARD = 2;
const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;
const int WM_SYSKEYDOWN = 0x104;
const int WM_SYSKEYUP = 0x105;
const byte VK_SHIFT = 0x10;
const byte VK_CAPITAL = 0x14;
const byte VK_NUMLOCK = 0x90;
const byte VK_LSHIFT = 0xA0;
const byte VK_RSHIFT = 0xA1;
const byte VK_LCONTROL = 0xA2;
const byte VK_RCONTROL = 0x3;
const byte VK_LALT = 0xA4;
const byte VK_RALT = 0xA5;
#endregion
#region VARIABLES
bool m_bHookActive;
int m_iHandleToHook;
protected HookProc m_hookproc;
#endregion
#region EVENTS
public event KeyEventHandler KeyDown;
public event KeyEventHandler KeyUp;
public event KeyPressEventHandler KeyPress;
#endregion
#region CONSTRUCTION & DESTRUCTION
~GlobalKeyboardHook()
{
Unhook();
}
#endregion
#region PROPERTIES
public bool HookActive
{
get { return m_bHookActive; }
}
#endregion
#region METHODS
public bool Hook()
{
if(!m_bHookActive)
{
m_hookproc = new HookProc(HookCallbackProcedure);
IntPtr hInstance = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
m_iHandleToHook = SetWindowsHookEx(
WH_KEYBOARD_LL,
m_hookproc,
hInstance,
0);
if(m_iHandleToHook != 0)
{
m_bHookActive = true;
}
}
return m_bHookActive;
}
public void Unhook()
{
if(m_bHookActive)
{
UnhookWindowsHookEx(m_iHandleToHook);
m_bHookActive = false;
}
}
protected virtual void OnKeyDown(KeyEventArgs kea)
{
if(KeyDown != null)
KeyDown(this, kea);
}
protected virtual void OnKeyUp(KeyEventArgs kea)
{
if(KeyUp != null)
KeyUp(this, kea);
}
protected virtual void OnKeyPress(KeyPressEventArgs kpea)
{
if(KeyPress != null)
KeyPress(this, kpea);
}
#endregion
#region EVENTHANDLER
int HookCallbackProcedure(int nCode, int wParam, IntPtr lParam)
{
bool bHandled = false;
if(nCode > -1 && (KeyDown != null || KeyUp != null || KeyPress != null))
{
KeyboardHookStruct khs = (KeyboardHookStruct) Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
bool bControl = ((GetKeyState(VK_LCONTROL) & 0x80) != 0) || ((GetKeyState(VK_RCONTROL) & 0x80) != 0);
bool bShift = ((GetKeyState(VK_LSHIFT) & 0x80) != 0) || ((GetKeyState(VK_RSHIFT) & 0x80) != 0);
bool bAlt = ((GetKeyState(VK_LALT) & 0x80) != 0) || ((GetKeyState(VK_RALT) & 0x80) != 0);
bool bCapslock = (GetKeyState(VK_CAPITAL) != 0);
KeyEventArgs kea = new KeyEventArgs((Keys) (khs.vkCode |
(bControl ? (int) Keys.Control : 0) |
(bShift ? (int) Keys.Shift : 0) |
(bAlt ? (int) Keys.Alt : 0)));
if(wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)
{
OnKeyDown(kea);
bHandled = kea.Handled;
}
else if(wParam == WM_KEYUP || wParam == WM_SYSKEYUP)
{
OnKeyUp(kea);
bHandled = kea.Handled;
}
if(wParam == WM_KEYDOWN && !bHandled && !kea.SuppressKeyPress)
{
byte[] abyKeyState = new byte[256];
byte[] abyInBuffer = new byte[2];
GetKeyboardState(abyKeyState);
if(ToAscii(khs.vkCode, khs.scanCode, abyKeyState, abyInBuffer, khs.flags) == 1)
{
char chKey = (char) abyInBuffer[0];
if((bCapslock ^ bShift) && Char.IsLetter(chKey))
chKey = Char.ToUpper(chKey);
KeyPressEventArgs kpea = new KeyPressEventArgs(chKey);
OnKeyPress(kpea);
bHandled = kea.Handled;
}
}
}
if(bHandled)
return 1;
else
return CallNextHookEx(m_iHandleToHook, nCode, wParam, lParam);
}
#endregion
#region EXTERN
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, int dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
static extern int UnhookWindowsHookEx(int idHook);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);
[DllImport("user32.dll")]
static extern int GetKeyboardState(byte[] pbKeyState);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
static extern short GetKeyState(int vKey);
[DllImport("user32.dll")]
static extern int ToAscii(int uVirtKey, int uScanCode, byte[] lpbKeyState, byte[] lpwTransKey, int fuState);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
#endregion }
#endregion }
btw: This is .NET not Java - the convention is: type names start with capital letters...
|
|
|
|

|
Hi Johannes,
Thanks for posting your code. I tried it and works perfectly for XP. However, when migrated to Windows 7, it works initially for several key strokes, but then it does not work as expected... I used the code to hook the keys for my application to control PowerPoint slide up and down by SendKeys method. Initially ok, but after ~10 key strokes, the PowerPoint does not respond to the keys. Does the code compliant with Windows 7? or any hint to change? thanks.
Best regards,
Vincent
|
|
|
|

|
I've made a program using this hook and on about the 40th second I get an exception:
A callback was made on a garbage collected delegate of type 'SuperLogger!Utilities.globalKeyboardHook+keyboardHookProc::Invoke'. This may cause application crashes, corruption and data loss. When passing delegates to unmanaged code, they must be kept alive by the managed application until it is guaranteed that they will never be called.
That's quite weird. Any ideas?
|
|
|
|

|
i have this error too.is there any solution????
و این منم زنی تنها در آستانه فصلی سرد...
|
|
|
|

|
Hi,
First of all, thanks for sharing this code!
Second: I got a problem using this code, I'm hooking some "normal" keys (like A, S, Q...) and the alt key. After a while (30-240 minutes), my application crashes. I surrounded all of my code with try-catches and debug output in the catch clause, so i'm almost sure its not my code that causes the crash (bold statement, I know ... not to be taken too seriously).
The only piece of information I found so far: The crash seems to occur shortly after using the arrow keys (which I did not hook).
My system: Win XP SP3, 32 Bit, german language
UPDATE: After testing some more, its not bound to the arrow keys ... it happens with all keys. I had some more crashes today that occured while I was typing.
modified on Wednesday, April 7, 2010 11:16 AM
|
|
|
|

|
I need to use the F1 in my application, and ive tried e.handled, but everytime ive hit F1, it brings up help.
|
|
|
|

|
When I hook keys, and then press them, the app locks up for a second or two, then resumes. why does it do this?
|
|
|
|

|
Hi, i'm trying to make my program pick up any key and write it in a text file when i press F6, then, i want the text file to be read and all the text from it put into a TextBox on the form by pressing F7. I've looked at numerous posts such as the one with the _hookAll thing, but when i type ANYTHING on a text field with this function, nothing happens. the text doesnt even appear.
I'm making a spammer (for experimental reasons) and everything works. I want the user to be able to set a new message without going back to the Form (by pressing F6 to activate, F7 to set).
I might not even have to use streamwriter/reader to do this, it just seems an easier option for me.
So can someone tell me why and how to stop the program disabling my keyboard?
Thanks!
|
|
|
|

|
Hm, make sure that your KeyUp/KeyDown handlers return properly and that you are not setting e.Handled to true.
|
|
|
|

|
WOW! This is PERFECT!!! Short, representative, well organized and after I changed some things I have read from the posts it's WORKING! Exactly what I needed, thanks!
modified on Friday, January 1, 2010 10:00 AM
|
|
|
|

|
Hi, I got the following error:
System.NullReferenceException: Object reference not set to an instance of an object.
at Utilities.globalKeyboardHook.CallNextHookEx(IntPtr idHook, Int32 nCode, Int32 wParam, keyboardHookStruct& lParam)
at Utilities.globalKeyboardHook.hookProc(Int32 code, Int32 wParam, keyboardHookStruct& lParam) in c:\Documents and Settings\Marius Utheim\Mine dokumenter\SharpDevelop Projects\Useful stuff\globalKeyboardHook.cs:line 109
at System.Windows.Forms.UnsafeNativeMethods.PeekMessage(MSG& msg, HandleRef hwnd, Int32 msgMin, Int32 msgMax, Int32 remove)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
It seems to happen if I press two keys at the same time, or almost simultaneously. Do you know how to fix it?
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.
|
A simple description and sample of creating a global low level keyboard hook in C#
| Type | Article |
| Licence | CPOL |
| First Posted | 30 May 2007 |
| Views | 278,688 |
| Downloads | 18,816 |
| Bookmarked | 124 times |
|
|