public Form1()
        {
            InitializeComponent();
        }
        
        #region Other
        public delegate int HookProc(int nCode, int wParam, IntPtr lParam);//委托
        static int hHook = 0;//获取钩子静态变量,初始化0
        public const int WH_KEYBOARD_LL = 13;//底层钩子
        //LowLevel键盘截获,如果是WH_KEYBOARD=2,并不能对系统键盘截取,Acrobat Reader会在你截取之前获得键盘。 
        HookProc KeyBoardHookProcedure;
        //键盘结构 原型
        [StructLayout(LayoutKind.Sequential)]
        public class KeyboardHookStruct
        {
            public int vkCode; //定一个虚拟键码。该代码必须有一个价值的范围1至254 。 
            public int scanCode; // 指定的硬件扫描码的关键。 
            public int flags;  // 键标志
            public int time; // 指定的时间戳记的这个讯息。
            public int dwExtraInfo; // 指定额外信息相关的信息。
        }        SinnerCode.SinnerCode Sn = new SinnerCode.SinnerCode();
        
        private string WindowsFromTitle = null;//获取拳皇窗口标题        #endregion        #region API
        //安装钩子 最好设置非托管约定
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);        //卸载钩子 最好设置非托管约定
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern bool UnhookWindowsHookEx(int idHook);        //调用下一个钩子
        [DllImport("user32.dll")]
        public static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);        //用作与安装时THREADID
        [DllImport("kernel32.dll")]
        public static extern int GetCurrentThreadId();        //进程模版
        [DllImport("kernel32.dll")]
        public static extern IntPtr GetModuleHandle(string name);        //寻找目标进程窗口
        [DllImport("USER32.DLL")]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);        //设置进程窗口到最前
        [DllImport("USER32.DLL")]
        public static extern bool SetForegroundWindow(IntPtr hWnd);
        #endregion        #region 自定义事件
        public void Hook_Start()
        {            // 安装键盘钩子 
            if (hHook == 0)
            {
                KeyBoardHookProcedure = new HookProc(KeyBoardHookProc);
                hHook = SetWindowsHookEx(WH_KEYBOARD_LL,
              KeyBoardHookProcedure,
              GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0);
                //Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0])是不行的,获取到的是0,会失败,这就是为什么需要定义GetModuleHandle的原因,注意的是IntPtr的特定句柄类型。
                //如果设置钩子失败. 
                if (hHook == 0)
                {
                    Hook_Clear();
                    throw new Exception("设置Hook失败!");
                }
            }
        }        //卸载键盘钩子 
        public void Hook_Clear()
        {
            bool retKeyboard = true;
            if (hHook != 0)
            {
                retKeyboard = UnhookWindowsHookEx(hHook);
                hHook = 0;
            }
            //如果去掉钩子失败. 
            if (!retKeyboard) throw new Exception("卸载钩子失败!");
        }        //这里可以添加自己想要的信息处理 
        public static int KeyBoardHookProc(int nCode, int wParam, IntPtr lParam)
        {
            if (nCode >= 0)
            {
                //问题①
                WinIoSys Sw_Key = new WinIoSys();//这局代码应该做全局变量,但做了之后无法调用..?因为Sw_Key.InitSuperKeys()用了之后要关闭,暂时不知道如何解决.
                Sw_Key.InitSuperKeys();
                KeyboardHookStruct kbh = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
                if (kbh.vkCode == (int)Keys.S && (int)Control.ModifierKeys == (int)Keys.Control) // 截获Ctrl+S 
                {
                    return 1;                }
                if (kbh.vkCode == (int)Keys.Y
                && (int)Control.ModifierKeys == (int)Keys.Control + (int)Keys.Alt) //截获Ctrl+Alt+Y 
                {                    //MessageBox.Show("不能全部保存!"); 
                    return 1;
                }
                //以下是测试部分
                if (kbh.vkCode == (int)Keys.L)
                {
                    Sw_Key.KeyDown(WinIoSys.Key.VK_S);
                    Thread.Sleep(100);
                    Sw_Key.KeyDown(WinIoSys.Key.VK_D);
                    Thread.Sleep(100);
                    Sw_Key.KeyUp(WinIoSys.Key.VK_S);
                    Thread.Sleep(100);
                    Sw_Key.KeyUp(WinIoSys.Key.VK_D);
                    Thread.Sleep(10);
                    Sw_Key.KeyPress(WinIoSys.Key.VK_J, 200);
                    return 0;
                    
                }            }
            return CallNextHookEx(hHook, nCode, wParam, lParam);
            //问题②
            //程序运行后sdj三个键会输入两次,把button1代码注释,留下Hook_Start()可进任意窗口行测试.
            //return CallNextHookEx(hHook, nCode, wParam, lParam);这句改为:
            //return 1,会只按下L,而return0的话会执行lsdjsdj
            
        }
        #endregion        private void button1_Click(object sender, EventArgs e)
        {
            Sn.GetProcessTitle();
            for (int i = 0; i < Sn.IsProcess.Length; i++) 
            {
  大侠们。。来吧。最后34分了解决问题2就可以了。。

解决方案 »

  1.   

    public static int asd = 1;                if (asd % 2 == 1)//加了这个判断之后,输出结果就是一次了,但是只能在记事本输出,在其他窗口就没用了。。
                    {
                        asd += 1;
                        if (kbh.vkCode == (int)Keys.L)
                        {
                            Sw_Key.KeyDown(WinIoSys.Key.VK_S);
                            Thread.Sleep(100);
                            Sw_Key.KeyDown(WinIoSys.Key.VK_D);
                            Thread.Sleep(100);
                            Sw_Key.KeyUp(WinIoSys.Key.VK_S);
                            Thread.Sleep(100);
                            Sw_Key.KeyUp(WinIoSys.Key.VK_D);
                            Thread.Sleep(10);
                            Sw_Key.KeyPress(WinIoSys.Key.VK_J, 200);
                            return 1;
                        }
                    }
                    else 
                    {
                        asd += 1;
                    }
    我改成了这样在记事本输出是不会出现两次了,但是在其他窗口,比如KOF拳皇。。就不会按下sdj这3个键了只有在记事本上能输出sdj。来人吧这问题我已经问了两次了
      

  2.   

    keydown和keyup,找到它们的确切定义,然后分别判断
      

  3.   

    “KOF拳皇。。就不会按下sdj这3个键了只有在记事本上能输出sdj”
    很多程序,特别是游戏,为了准求对键盘鼠标输入的快速反应,使用了IO的DX技术(就是说KOF拳皇直接到键盘的中断端口去读取输入,参见相关资料),而不是一般的程序那样(例如记事本)从操作系统的消息队列里获取。可能这个是输出不了的原因。
      

  4.   


    问题是在于我用的判断方法是不对的。屏蔽的上一个钩子应该就是按下sdj的,而后面的那个是跟复制粘贴一样。。感觉是这样。。