控制在HookCallback中捕获了两次

时间:2016-08-10 19:02:53

标签: c# pinvoke

尝试让L-Control使用keybd_event使用self变量执行操作失败,当您释放左控制两个LControlKey并将LMenu写入控制台时,LShiftKey会发生什么?< / p>

我的代码:

using System;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
class Programz
{
    private const int WH_KEYBOARD_LL = 13;
    private const int WM_KEYDOWN = 0x0100;
    private const int WM_KEYUP = 0x0101;

    const uint KEYEVENTF_EXTENDEDKEY = 0x0001;
    const uint KEYEVENTF_KEYUP = 0x0002;
    private static bool self = false;
    private static LowLevelKeyboardProc _proc = HookCallback;
    private static IntPtr _hookID = IntPtr.Zero;
    public static void Main()
    {
        _hookID = SetHook(_proc);
        Application.Run();
        UnhookWindowsHookEx(_hookID);
    }
    public static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0 && wParam == (IntPtr)WM_KEYUP)
        {
            int vkCode = Marshal.ReadInt32(lParam);
            var Key = (Keys)vkCode;
            Console.WriteLine(Key);
            if (!self && Key == Keys.LControlKey)
            {
                self = true;
                keybd_event((int)Keys.LControlKey, (byte)MapVirtualKey((int)Keys.LControlKey, 0),
                    KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
                self = false;
                keybd_event((int)Keys.LMenu, (byte)MapVirtualKey((int)Keys.LMenu, 0),
                    0 | KEYEVENTF_EXTENDEDKEY, 0); //Send L-Alt down
                Thread.Sleep(10);
                keybd_event((int)Keys.LShiftKey, (byte)MapVirtualKey((int)Keys.LShiftKey, 0),
                    0 | KEYEVENTF_EXTENDEDKEY, 0);//Send L-Shift down
                Thread.Sleep(10);
                //Send L-Alt & L-Shift up
                keybd_event((int)Keys.LShiftKey, (byte)MapVirtualKey((int)Keys.LShiftKey, 0),
                    KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
                keybd_event((int)Keys.LMenu, (byte)MapVirtualKey((int)Keys.LMenu, 0),
                    KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
            }

        }
        return CallNextHookEx(_hookID, nCode, wParam, lParam);
    }
    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);
        }
    }
    [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)]
    public static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int extraInfo);

    [DllImport("user32.dll")]
    public static extern short MapVirtualKey(int wCode, int wMapType);
    private delegate IntPtr LowLevelKeyboardProc(
        int nCode, IntPtr wParam, IntPtr lParam);

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

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

感谢。

1 个答案:

答案 0 :(得分:-1)

Input Simulator没有这样的问题,就像魅力一样。

修改

我弄清楚它为什么在输入模拟器中工作,这是因为扩展键:

LShift和LControl不是扩展密钥,因此它们不需要KEYEVENTF_EXTENDEDKEY标志,这就是为什么它不能提前工作。