我正在编写一个应用程序,需要获得系统输入语言,而应用程序窗口没有焦点。
在搜索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);
        }
     }
}

最佳答案

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

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

还有,这是我的课。
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);
}

我已经读过,如果您试图从控制台应用程序中执行这些钩子操作,您将遇到问题,尽管您对External的调用应该可以解决这个问题。

关于c# - 输入语言 Hook ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6155317/

10-11 15:31