C#检查是否按下了多个键(全局键盘挂钩)

时间:2016-01-21 18:54:24

标签: c# winforms winapi keyboard-hook

我正在制作一个在后台运行的C#表单应用程序并检查你是否按下CTRL + A + S.所以我在互联网上检查论坛,我已经设置了应用程序在后台运行,现在我'我正在尝试设置键盘钩子。我在互联网上找到了一个全局键盘钩子代码。

以下是此代码:

    // GLOBAL HOOK
    [DllImport("user32.dll")]
    static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc callback, IntPtr hInstance, uint threadId);

    [DllImport("user32.dll")]
    static extern bool UnhookWindowsHookEx(IntPtr hInstance);

    [DllImport("user32.dll")]
    static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, int wParam, IntPtr lParam);

    [DllImport("kernel32.dll")]
    static extern IntPtr LoadLibrary(string lpFileName);

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

    const int WH_KEYBOARD_LL = 13; // Number of global LowLevel- hook on the keyboard
    const int WM_KEYDOWN = 0x100; // Messages pressing

    private LowLevelKeyboardProc _proc = hookProc;

    private static IntPtr hhook = IntPtr.Zero;

    public void SetHook()
    {
        IntPtr hInstance = LoadLibrary("User32");
        hhook = SetWindowsHookEx(WH_KEYBOARD_LL, _proc, hInstance, 0);
    }

    public static void UnHook()
    {
        UnhookWindowsHookEx(hhook);
    }

    public static IntPtr hookProc(int code, IntPtr wParam, IntPtr lParam)
    {
        if (code >= 0 && wParam == (IntPtr)WM_KEYDOWN)
        {
            int vkCode = Marshal.ReadInt32(lParam);

            if (vkCode.ToString() == "162") //162 is ASCI CTRL
            {
                MessageBox.Show("You pressed a CTRL");                    
            }
            return (IntPtr)1;
        }
        else
            return CallNextHookEx(hhook, code, (int)wParam, lParam);
    }

    private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
    {
        // Remove the hook
        UnHook();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        // Set the hook
        SetHook();
    }

}

我的问题是这个挂钩设置为1键,我无法弄清楚如何检查是否按下3个键(CTRL + A + S)。

我已经尝试了这个但是没有用。

if (vkCode.ToString() == "162" && vkCode.ToString() == "65" && vkCode.ToString() == "83") //162 is CTRL, 65 is A, 83 is S, ASCII CODE
            {
                MessageBox.Show("You pressed a CTRL + A + S");                    
            }

所以我的问题是我需要做的是程序或这个钩子允许我检查3个按下的键(CTRL + A + S)。

1 个答案:

答案 0 :(得分:3)

我相信您必须分别检测CTRL,A和S,使用标记来跟踪CTRL和A是否是最后一次按键,如下所示:

static bool ctrlPressed = false;
static bool ctrlAPressed = false;

public static IntPtr hookProc(int code, IntPtr wParam, IntPtr lParam)
{
    if (code >= 0 && wParam == (IntPtr)WM_KEYDOWN)
    {
        int vkCode = Marshal.ReadInt32(lParam);

        if (vkCode == 162 || vkCode == 163) //162 is Left Ctrl, 163 is Right Ctrl
        {
            ctrlPressed = true;
        }
        else if (vkCode == 65 && ctrlPressed == true) // "A"
        {
            ctrlPressed = false;
            ctrlAPressed = true;
        }
        else if (vkCode == 83 && ctrlAPressed == true) // "S"
        {
            ctrlPressed = false;
            ctrlAPressed = false;
            MessageBox.Show("Bingo!");
        }
        else
        {
            ctrlPressed = false;
            ctrlAPressed = false;
        }

        // return (IntPtr)1; // note: this will interfere with keyboard processing for other apps
    }
//  else // don't interfere , always return callnexthookex
        return CallNextHookEx(hhook, code, (int)wParam, lParam);
}

如果您希望确保在逻辑相似的同时按下所有按钮,则只需添加检查按键是否按下或按下。您可能还会使用某种列表或队列或其他按键来提供一种更聪明的方法。