Tuesday, December 6, 2011

How to: write a key mapper or Key transformation utility in 10 minutes

Question, need a utility to map or transform the key stoke, say when you press F6, replace the contents with a Mailing address, and Press F7 for the zip code of your city.

  Answer, In C#, it’s easy and not easy. you have to wrap several Native APIs to hook the mapping point into the system, Easy one is it has one Great methods called Sendkeys.Send.

So eventually, we need one file to keep the mapping logic , here I just pickup the .config file, then the code. Code is here,you may just copy and save it as .cs file, then compile it.

using System;
using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Text;
using System.Collections.Specialized;

public class KeyMapper
{
    private const int WH_KEYBOARD_LL = 13;
    private const int WM_KEYDOWN = 0x0100;

    private static LowLevelKeyboardProc _proc = HookCallback;
    private static IntPtr _hookID = IntPtr.Zero;
    private static NameValueCollection mappings;
    public static void Main()
    {
        //Check to see no duplicate running
        if(Process.GetProcessesByName("af").Length>1)
        {
            return;
        }
        //keep it small
        Console.SetWindowSize(1,2);

        mappings = System.Configuration.ConfigurationManager.AppSettings;

        _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);
            String key = ((Keys)vkCode).ToString();

            if (mappings[key] != null)
            SendKeys.Send(mappings[key]);
            
        }
        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);
}

Config  file, like mine,
image

Then we you started the console application.
wherever you enter F6, it will put a sample address there.
image

If you can’t compile the code , leave a comment , I will email you the compiled bits.

 
Locations of visitors to this page