输入语言挂钩

时间:2011-05-27 16:44:44

标签: c# .net windows hook

我正在编写一个需要获取系统输入语言的应用程序,而应用程序窗口没有聚焦

搜索Google后,我发现执行此操作的方法是挂钩WM_INPUTLANGCHANGE消息。

但我找不到钩子的语法示例。

我找到了以下代码并试图根据我的需要调整它,但我失败了:

修改 我用WM_INPUTLANGCHANGE替换了WM_KEYUP,但它不起作用。

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 _hookID = 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);
        }
     }
}

1 个答案:

答案 0 :(得分:0)

我的一个项目的代码对我来说,看起来我们可能使用了相同的例子:

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);
}

此外,这是我的External课程。

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);
}

我已经读过,如果您尝试从控制台应用程序执行这些挂钩,则会遇到问题,尽管您对Application.Run()的调用应解决此问题。