Thursday, February 5, 2009

C# Key Listener

CodeGuru has this post:

Hi All

Looking for a little help..

I would like to create a process that runs on both a Windows XP and Vista Machines that loads on startup, what this process will do is, on the "F12" keypress it brings up a simple form that a user fills in some details then clicks on send, then it goes back to sleep and waits on the "F12" key being pressed.

Never created a process before so any help is appreciated.

Cheers

Djbell


This post will describe how to do this in C#. We will approach this by creating an executable that could be loaded at startup. It will listen for the F12 keyboard event and present a message box.


Create a new C# Console project in Visual Studio, call it 'ListenForHotkey.'

We will use a windows hook to notify our application when a key is pressed. So in the Program.cs file you should define four win32 API's. SetWindowsHookEx, UnhookWindowsHookEx, GetModuleName, CallNextHookEx. We'll also define a delegate for the callback, and some constants.

Here is the Program.cs with these definitions.
using System;
using System.Runtime.InteropServices; //Used for dll import
using System.Diagnostics; //'Process'

namespace ListenForHotkey
{
static class Program
{
[STAThread]
static void Main()
{
}
// Define win32 api calls.
[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("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
IntPtr wParam, IntPtr lParam);

//Define delegate for the callback.
private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);

//Define constants
private const int WH_KEYBOARD_LL = 13;

}
}


In the code above we've defined a delegate called LowLevelKeyboardProc that is the signature of the callback. Let's add our callback.

// Callback, executed when hook is triggered. In our case on keydown.            
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
System.Console.WriteLine("key pressed");

//Call next hook in chain.
return CallNextHookEx(m_hookId, nCode, wParam, lParam);

}



Our callback simply prints that a key was pressed then calls the next hook if applicable. This is important else another application that register a hook may not be called.

Lastly we should register our hook, and run the app. This is done in the main method.

[STAThread]
static void Main()
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{

m_hookId = SetWindowsHookEx(WH_KEYBOARD_LL, HookCallback, GetModuleHandle(curModule.ModuleName), 0);
}
System.Windows.Forms.Application.Run();
UnhookWindowsHookEx(m_hookId);
}


In main we register the callback then call Application.Run() which puts the app in an infinite loop by waiting for any system messages. When the program is ready to exit we unregister our hook.

That's it.

Hope it helps.

2 comments:

jazmy said...

Hey your code needs lot of guide !!.

- where the F12 key in code.
- where we should write the second block of code (HookCallback(int nCode, IntPtr wParam, IntPtr lParam) ).
- i got error m_hookid doesnot exist.

generic cialis said...

I, of course, a newcomer to this blog, but the author does not agree