用C#实现WINIO64位模拟键鼠操作

Home / Article MrLee 2016-8-31 6967

最近玩游戏有点入迷,心急升级经验,于是某天开始"挂尸体",一系列手动操作之后决定写一个外挂,模拟一系列键盘和鼠标操作,没做过游戏winform也用得少,开始以为只要简单调用winApi的键盘和鼠标就能够实现...结果
后来才发现游戏一般都禁用了winAPI,最后找了一个驱动级的模拟PS2端口的三方库(WinIO),因为是64位的电脑涉及到数字证书之类的比较麻烦,不过最后好歹都实现了需要的功能,里面写了一些截取屏幕指定坐标图片与采集的图片做对比,
以实现什么时候该点什么时候不该点的判断,一些关键的代码当做随笔记录下来.
 
将游戏窗体保持最前
[DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern int SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int Width, int Height, int flags);
        /// <summary> 
        /// 得到当前活动的窗口 
        /// </summary> 
        /// <returns></returns> 
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern System.IntPtr GetForegroundWindow();
        [DllImport("User32.dll", EntryPoint = "FindWindow")]
        private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
        private void button1_Click(object sender, EventArgs e)
        {
            IntPtr hwnd;
            hwnd = FindWindow(null, "XXXX");  //根据程序标题获取句柄
            SetWindowPos(hwnd, -1, 0, 0, 0, 0, 1 | 2);  //设置在最前
        }

64位win7操作 winIO
public class WinIO
    {
        public const int KBC_KEY_CMD = 0x64;//输入键盘按下消息的端口
        public const int KBC_KEY_DATA = 0x60;//输入键盘弹起消息的端口
        [DllImport("WinIo64.dll")]
        public static extern bool InitializeWinIo();
        [DllImport("WinIo64.dll")]
        public static extern bool GetPortVal(IntPtr wPortAddr, out int pdwPortVal,
                    byte bSize);
        [DllImport("WinIo64.dll")]
        public static extern bool SetPortVal(uint wPortAddr, IntPtr dwPortVal,
                    byte bSize);
        [DllImport("WinIo64.dll")]
        public static extern byte MapPhysToLin(byte pbPhysAddr, uint dwPhysSize,
                        IntPtr PhysicalMemoryHandle);
        [DllImport("WinIo64.dll")]
        public static extern bool UnmapPhysicalMemory(IntPtr PhysicalMemoryHandle,
                        byte pbLinAddr);
        [DllImport("WinIo64.dll")]
        public static extern bool GetPhysLong(IntPtr pbPhysAddr, byte pdwPhysVal);
        [DllImport("WinIo64.dll")]
        public static extern bool SetPhysLong(IntPtr pbPhysAddr, byte dwPhysVal);
        [DllImport("WinIo64.dll")]
        public static extern void ShutdownWinIo();
        [DllImport("user32.dll")]
        public static extern int MapVirtualKey(uint Ucode, uint uMapType);


        private WinIO()
        {
            IsInitialize = true;
        }
        public static void Initialize()
        {
            if (InitializeWinIo())
            {
                KBCWait4IBE();
                IsInitialize = true;
            }
        }
        public static void Shutdown()
        {
            if (IsInitialize)
                ShutdownWinIo();
            IsInitialize = false;
        }
        private static bool IsInitialize { get; set; }
        ///等待键盘缓冲区为空
        private static void KBCWait4IBE()
        {
            int dwVal = 0;
            do
            {
                bool flag = GetPortVal((IntPtr)0x64, out dwVal, 1);
            }
            while ((dwVal & 0x2) > 0);
        }
        /// 模拟键盘标按下
        public static void KeyDown(Keys vKeyCoad)
        {
            if (!IsInitialize) return;
            int btScancode = 0;
            btScancode = MapVirtualKey((uint)vKeyCoad, 0);
            KBCWait4IBE();
            SetPortVal(KBC_KEY_CMD, (IntPtr)0xD2, 1);
            KBCWait4IBE();
            SetPortVal(KBC_KEY_DATA, (IntPtr)0x60, 1);
            KBCWait4IBE();
            SetPortVal(KBC_KEY_CMD, (IntPtr)0xD2, 1);
            KBCWait4IBE();
            SetPortVal(KBC_KEY_DATA, (IntPtr)btScancode, 1);
        }
        /// 模拟键盘弹出
        public static void KeyUp(Keys vKeyCoad)
        {
            if (!IsInitialize) return;
            int btScancode = 0;
            btScancode = MapVirtualKey((uint)vKeyCoad, 0);
            KBCWait4IBE();
            SetPortVal(KBC_KEY_CMD, (IntPtr)0xD2, 1);
            KBCWait4IBE();
            SetPortVal(KBC_KEY_DATA, (IntPtr)0x60, 1);
            KBCWait4IBE();
            SetPortVal(KBC_KEY_CMD, (IntPtr)0xD2, 1);
            KBCWait4IBE();
            SetPortVal(KBC_KEY_DATA, (IntPtr)(btScancode | 0x80), 1);
        }
    }

 
调用:
1.初始实例: WinIO.Initialize();
2.模拟按键
WinIO.KeyDown(Keys.A); // 按下A Thread.Sleep(100); WinIO.KeyUp(Keys.A); // 松开A
3.窗体关闭之后注销: WinIO.Shutdown(); // 用完后注销
 
当然WINIO在64位下没有正式的数字证书,用得时候需要手动在测试模式下为sys文件导入证书. 命令 ( bcdedit /set testsigning on )
鼠标模拟
[DllImport("user32.dll")]
        private static extern int SetCursorPos(int x, int y);
        public enum MouseEventFlags
        {
            Move = 0x0001,
            LeftDown = 0x0002,
            LeftUp = 0x0004,
            RightDown = 0x0008,
            RightUp = 0x0010,
            MiddleDown = 0x0020,
            MiddleUp = 0x0040,
            Wheel = 0x0800,
            Absolute = 0x8000
        }
        [DllImport("User32")]
        public extern static void mouse_event(int dwFlags, int dx, int dy, int dwData, IntPtr dwExtraInfo);
        /// <summary>        
        /// 移动鼠标到指定的坐标点        
        /// </summary>        
        public void MoveMouseToPoint()
        {
            string settingValue = ConfigurationManager.AppSettings.Get("Point");
            string[] pList = settingValue.Split(',');
            Point centerP = new Point(int.Parse(pList[0]), int.Parse(pList[1]));
            if (checkBox1.Checked)
            {
                SetCursorPos(centerP.X, centerP.Y);
                mouse_event((int)(MouseEventFlags.LeftDown | MouseEventFlags.Absolute), 0, 0, 0, IntPtr.Zero);
                mouse_event((int)(MouseEventFlags.LeftUp | MouseEventFlags.Absolute), 0, 0, 0, IntPtr.Zero);
            }
        }
        /// <summary>       
        /// /// 设置鼠标的移动范围        
        /// </summary>        
        public void SetMouseRectangle(Rectangle rectangle)
        {
            System.Windows.Forms.Cursor.Clip = rectangle;
        }

 

本文链接:https://www.it72.com/9993.htm

推荐阅读
最新回复 (0)
返回