C# 开发 DNF手搓按键。keybd_event 模拟键盘操作(重点是方向键模拟)

一、开发目标:使用keybd_event和键盘HOOK实现一个按键模拟DNF中的技能指令。操作角色是红眼。

二、项目进度:初步实现技能指令释放,没有对键盘连按做处理,会有N多重复命令,导致角色会抽搐。没有做自定义按键,所有指令都是写到程序中的,不够灵活。

三、开发环境:Win11 ,VS 2022, .net6

四、详细介绍:

  1. 创建键盘钩子,拦截键盘操作

 public class Hook
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        public Hook() { }
        /// <summary>
        /// 单例模式
        /// </summary>
        public static readonly Hook _HookClient = new Hook();

        #region 钩子
        //委托 
        public delegate int HookProc(int nCode, int wParam, IntPtr lParam);
        HookProc KeyBoardHookProcedure;

        public delegate void HookHandle(Keys key, int DownOrUp);
        public event HookHandle EventHandle;

        //钩子状态
        public static int hHook = 0;
        //键盘Hook结构函数 
        [StructLayout(LayoutKind.Sequential)]
        public class KeyBoardHookStruct
        {
            public int vkCode;
            public int scanCode;
            public int flags;
            public int time;
            public int dwExtraInfo;
        }
        #region DllImport
        //设置钩子 
        [DllImport("user32.dll")]
        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);

        //获取模块处理
        [DllImport("kernel32.dll")]
        public static extern IntPtr GetModuleHandle(string name);

        /// <summary>
        /// 获取按键状态
        /// </summary>
        /// <param name="nVirtKey"></param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        public static extern short GetKeyState(int nVirtKey);

        const int WM_KEYUP = 0x101;//抬起
        const int WM_KEYDOWN = 0x100;//按下
        const int WM_SYSKEYDOWN = 0x0104;//系统键按下
        const int WM_SYSKEYUP = 0x0105;//系统键抬起
        const int WM_COPYDATA = 0x004A;//消息中的msg;
        const int WH_KEYBOARD_LL = 13;//键盘获取级别(高),可获取系统按键(Ctrl、Shift等)
        const int WH_KEYBOARD = 2;//键盘获取级别(低),不能可获取系统按键(Ctrl、Shift等)

        #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);
                hHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyBoardHookProcedure, GetModuleHandle("user32"), 0);
                //如果设置钩子失败. 
                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)
            {
                //Debug.WriteLine("钩子注销失败!该钩子可能已经失效");
            }
        }

        //这里可以添加自己想要的信息处理 
        public int KeyBoardHookProc(int nCode, int wParam, IntPtr lParam)
        {

            int sendW = wParam;

            if (nCode >= 0)
            {  

                KeyBoardHookStruct kbh = (KeyBoardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyBoardHookStruct));
 
                //获取按键的键值
                Keys key = (Keys)kbh.vkCode;
                 
                //处理键盘命令
                EventHandle?.Invoke(key, wParam);  
                
            }
            int ww = CallNextHookEx(hHook, nCode, wParam, lParam);
            return ww;
        }


        #endregion

        #endregion


    }
  1. 创建一个窗口添加一个CheckBox用于启动和关闭模拟功能

  1. 双击checkbox 控件编写checkBox1_CheckedChanged事件

 private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            if (this.checkBox1.Checked)
            {
                Hook._HookClient.Hook_Start();  //加载钩子 
                Hook._HookClient.EventHandle += _HookClient_EventHandle;
                Hook._HookClient.EventHandle11 += _HookClient_EventHandle11;
            }
            else
            {
                Hook._HookClient.EventHandle -= _HookClient_EventHandle;
                Hook._HookClient.EventHandle11 -= _HookClient_EventHandle11;
                Hook._HookClient.Hook_Clear();
            }
        }
  1. 使用User32标记创建Win32API调用方法

 
        //模拟键盘API  键值用byte最准确
        [DllImport("user32.dll", EntryPoint = "keybd_event", SetLastError = true)]
        public static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo);
        byte VK_LEFT = 0x64;//向左键(数字键盘4)
        byte VK_UP = 0x68;   //向上键(数字键盘8)
        byte VK_RIGHT = 0x66;    //向右键(数字键盘6)
        byte VK_DOWN = 0x65; //向下键(数字键盘5)
        byte VK_SPACE = 0x20;   //空格键
        byte VK_Z = 0x2c;       //Z

        byte CO_LEFT = 0x4b;//向左键(数字键盘4)
        byte CO_UP = 0X48;   //向上键(数字键盘8)
        byte CO_RIGHT = 0x4d;    //向右键(数字键盘6)
        byte CO_DOWN = 0x4c; //向下键(数字键盘5)
        byte CO_SPACE = 0x39;   //空格键 
        byte CO_Z = 0x2c;       //Z
        /// <summary>
        /// 按下
        /// </summary>
        const byte KEYEVENTF_KEYDOWN = 0;
        /// <summary>
        /// 抬起
        /// </summary>
        const byte KEYEVENTF_KEYUP = 2;
  1. 编写按键处理方法_HookClient_EventHandle

         //创建一个随机数,用来随机按键按下的时长,更真实的模拟手动操作。
        Random rd = new Random();
        private void _HookClient_EventHandle(Keys key, int DownOrUp)
        {

            switch (key)
            {
                 
                case Keys.A:
                    //下上上z
                    血气之刃();
                    break;
                case Keys.B:
                    break;
                case Keys.C:
                    break;
                case Keys.D:
                    怒气爆发();
                    //噬魂之手();
                    break;
                case Keys.E:
                    致命血陨();
                    break;
                case Keys.F:
                    血气爆发();
                    break;
                case Keys.G:
                    暴怒狂斩();
                    break;
                case Keys.H:
                    疯魔血魂斩();
                    break;
                case Keys.I:
                    break;
                case Keys.J:
                    血魔弑天();
                    break;
                case Keys.K:
                    break;
                case Keys.L:
                    break;
                case Keys.M:
                    break;
                case Keys.N:
                    break;
                case Keys.O:
                    break;
                case Keys.P:
                    break;
                case Keys.Q:
                    //下上下下z
                    噬魂封魔斩();
                    break;
                case Keys.R:
                    浴血之怒();
                    break;
                case Keys.S:
                    崩山击();
                    break;
                case Keys.T:
                    崩山裂地斩();
                    break;
                case Keys.U:
                    break;
                case Keys.V:
                    灭世();
                    break;
                case Keys.W:
                    鲜血暴掠();
                    break;
                case Keys.X:
                    break;
                case Keys.Y:
                    一觉();
                    break;
                case Keys.Z:
                    break; 
                case Keys.Add:
                    回血();
                    break; 
                default:
                    break;
            }
        }

        private void 暴怒狂斩()
        {
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //下
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //下
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //下
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //Z
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYUP, 0);
        }

        private void 回血()
        {  //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //空格
            keybd_event(VK_SPACE, CO_SPACE, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_SPACE, CO_SPACE, KEYEVENTF_KEYUP, 0);
        }

        private void 疯魔血魂斩()
        {
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //下
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //Z
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYUP, 0);
        }

        private void 一觉()
        {
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //下
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //下
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //Z
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYUP, 0);
        }

        private void 灭世()
        {  //下
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //下
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));

            //Z
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYUP, 0);
        }

        private void 崩山裂地斩()
        {
            //下
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));

            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //下
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));

            //Z
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYUP, 0);
        }

        private void 浴血之怒()
        {

            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));

            //Z
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYUP, 0);
        }

        private void 致命血陨()
        {

            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //下
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //下
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));

            //Z
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYUP, 0);
        }

        private void 鲜血暴掠()
        {
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //下
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));

            //Z
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYUP, 0);
        }

        private void 血魔弑天()
        {
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //下
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //下
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));

            //Z
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYUP, 0);
        }

        private void 封魔血魂斩()
        {
            //下
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //下
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //下
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));

            //Z
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYUP, 0);
        }

        private void 血气爆发()
        {
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //下
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));

            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));

            //Z
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYUP, 0);
        }

        private void 怒气爆发()
        {
            //下
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //下
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //下
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //Z
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYUP, 0);
        }

        private void 噬魂之手()
        {
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //下
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //Z
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYUP, 0);
        }

        private void 崩山击()
        {   //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //下
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //Z
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYUP, 0);
        }

        private void 噬魂封魔斩()
        {    //下
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //下
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //下
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //Z
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(100, 200));
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYUP, 0);
        }

        private void 血气之刃()
        {
            //下
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_DOWN, CO_DOWN, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));

            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //上
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYUP, 0);
            Thread.Sleep(rd.Next(40, 60));
            //Z
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYDOWN, 0);
            Thread.Sleep(rd.Next(50, 60));
            keybd_event(CO_Z, CO_Z, KEYEVENTF_KEYUP, 0);
        }
  1. 修改游戏中操作指令,所有操作都改成上下+Z 或者空格。方便把握好左右。

  1. 整体代码完成,由于一开始不知道怎么使用方向键,所以把方向键改成了数字键盘。

  1. 重点:由于部分地图必须使用方向键才能操作,又对方向键的使用进行了研究

    //增加辅助键盘按下值 
    const byte KEYEVENTF_KEYDOWNFangXiang = 1;
    
    //方向键的指令改成下面这样 
    keybd_event(VK_UP, CO_UP, KEYEVENTF_KEYDOWNFangXiang, 0);
    Thread.Sleep(rd.Next(50, 60));
    keybd_event(VK_UP, CO_UP, (KEYEVENTF_KEYDOWNFangXiang | KEYEVENTF_KEYUP), 0);
    Thread.Sleep(rd.Next(40, 60));

总结:整体代码比较简单,就是方向键研究了一下。同时因为没有适应指令释放技能的速度,最终只是实现了想要的功能进行了测试,最终被我放弃了。特此发出来分享一下。

预告:最近在研究.NET MAUI 想做一个手机操作软件,配合向日葵远程,或者其他远程。实现手机玩游戏。对于我来时比较难得是APP的界面制作,由于没有接触过android开发,步履蹒跚,有对.net MAUI 比较熟,或者对 xaml熟悉的兄弟留个言探讨一下。。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值