开发者

Input language Hooking

I am writing an aplication that need to get the system input language, while the application window is not focused.

After searching Google I have found that the way to do this is to hook WM_INPUTLANGCHANGE message.

But I could not find a syntax example of the hook.

I have found the following code and tried to adapt it for my needs, but I have failed:

Edit: I have replaced WM_KEYUP with WM_INPUTLANGCHANGE but it does not works.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace KeyHook
{
    class LenHook
    {

        private const int WM_INPUTLANGCHANGE = 0x0051;
        private static LowLevelKeyboardProc _proc = HookCallback;
        private static IntPtr _h开发者_如何学JAVAookID = IntPtr.Zero;


        [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)]
        public static extern bool UnhookWindowsHookEx(IntPtr hhk);

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

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern IntPtr GetModuleHandle(string lpModuleName);


        private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);


        public LenHook()
        {


            _hookID = SetHook(_proc);
            UnhookWindowsHookEx(_hookID);
            System.Windows.Forms.Application.Run();


        }
        //Install hook
        private static IntPtr SetHook(LowLevelKeyboardProc proc)
        {
            using (var curProcess = Process.GetCurrentProcess())
            {
                using (var curModule = curProcess.MainModule)
                {
                    return SetWindowsHookEx(WM_INPUTLANGCHANGE, proc, GetModuleHandle(curModule.ModuleName), 0);
                }
            }
        }

        //Do it when key press
        private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {

            MessageBox.Show(wParam.ToString());
            return CallNextHookEx(_hookID, nCode, wParam, lParam);
        }
     }
}


This code from a project of mine works for me, it looks like we may have used the same example:

private static IntPtr _hookId = IntPtr.Zero;
private readonly External.LowLevelKeyboardProc _proc;

public FrmMain()
{
    _proc = HookCallback;
    _hookId = SetHook(_proc);
    InitializeComponent();
}

private static IntPtr SetHook(External.LowLevelKeyboardProc proc)
{
    using(var curProcess = Process.GetCurrentProcess())
    {
        using(var curModule = curProcess.MainModule)
        {
            return External.SetWindowsHookEx(External.WH_KEYBOARD_LL, proc, External.GetModuleHandle(curModule.ModuleName), 0);
        }
    }
}

private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
    // You can change this to WM_KEYDOWN
    if (nCode >= 0 && wParam == (IntPtr)External.WM_KEYUP)
    {
         // Code you want to run when a button is pressed.
    }
    return External.CallNextHookEx(_hookId, nCode, wParam, lParam);
}

Also, this is my External class.

public static class External
{
    public delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);

    public const int WH_KEYBOARD_LL = 13;
    public const int WM_KEYDOWN = 0x0100;
    public const int WM_KEYUP = 0x0101;
    public const uint WM_GETTEXT = 0x0D;
    public const uint WM_GETTEXTLENGTH = 0x0E;
    public const uint EM_GETSEL = 0xB0;

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern IntPtr GetForegroundWindow();

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern uint GetCurrentThreadId();

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern IntPtr GetFocus();

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, StringBuilder lParam);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern int SendMessage(IntPtr hWnd, uint Msg, out int wParam, out int lParam);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool UnhookWindowsHookEx(IntPtr hhk);

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

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern IntPtr GetModuleHandle(string lpModuleName);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool GetCaretPos(out Point lPoint);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
}

I have read that you'll have problems if you try to do these hooks from a console application, although your call to Application.Run() should fix that.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜