一个C#写的模拟键盘输入的例子

如题,模拟键盘输入有很多方法,比如sendkey,keybd_event以及postmessage等,但大多游戏都对这些方法进行了屏蔽,特别是用DIRECTX写的游戏直接绕过操作系统直接读取键盘输入,因此上述三种方法都不好用,在网上查到使用WINIO方法可直接模拟键盘输入,因此自己试了一下,网上介绍的方法很少有c#写的,而且写出来的也无法直接使用,我把网上介绍的C#方法同其他语言写的进行了比较,终于找到了问题所在.调试终于通过了.

winio可以到这里去下载:http://www.internals.com/
下载解压后把“Binaries”文件夹下的文件拷贝入程序目录下。
//程序界面很简单,就是含一个"button"窗体程序。
程序思路如下:
1.找到桌面上的需要模拟键盘输入的窗口,本程序中的是“铁钩船长”这一款游戏,窗口名称为: "MAME: Hook (World) [hook]"
2.使被找到窗口成为输入焦点
3.模拟键盘输入


代码如下: 
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Threading;


namespace WindowsFormsApplication1
{
    public  partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        [DllImport("user32.dll", EntryPoint = "SwitchToThisWindow")]
        public static extern void SwitchToThisWindow(
        IntPtr hWnd, bool fAltTab
        );
        [DllImport("user32.dll", EntryPoint = "FindWindow")]
        public static extern int FindWindow(
            string lpClassName,
            string lpWindowName
        );


        ///
        public const int KBC_KEY_CMD = 0x64;
        public const int KBC_KEY_DATA = 0x60;
        [DllImport("winio32.dll")]
        public static extern bool InitializeWinIo();
        [DllImport("winio32.dll")]
        public static extern bool GetPortVal(IntPtr wPortAddr, out int pdwPortVal, byte bSize);
        [DllImport("winio32.dll")]
        public static extern bool SetPortVal(uint wPortAddr, IntPtr dwPortVal, byte bSize);
        [DllImport("winio32.dll")]
        public static extern byte MapPhysToLin(byte pbPhysAddr, uint dwPhysSize, IntPtr PhysicalMemoryHandle);
        [DllImport("winio32.dll")]
        public static extern bool UnmapPhysicalMemory(IntPtr PhysicalMemoryHandle, byte pbLinAddr);
        [DllImport("winio32.dll")]
        public static extern bool GetPhysLong(IntPtr pbPhysAddr, byte pdwPhysVal);
        [DllImport("winio32.dll")]
        public static extern bool SetPhysLong(IntPtr pbPhysAddr, byte dwPhysVal);
        [DllImport("winio32.dll")]
        public static extern void ShutdownWinIo();
        [DllImport("user32.dll")]
        public static extern int MapVirtualKey(uint Ucode, uint uMapType);




        public void sendwinio()
        {
            if (InitializeWinIo())
            {
                KBCWait4IBE();
            }


            else
            {
                MessageBox.Show("failure");
            }


        }


        private void KBCWait4IBE()
        {
            int dwVal = 0;
            do
            {
                bool flag = GetPortVal((IntPtr)0x64, out dwVal, 1);
                Thread.Sleep(5);             //这个不加似乎不行
            }
            while ((dwVal & 0x2) > 0);


            ///
          
        }     

        private void button1_Click(object sender, EventArgs e)
        {            
            int hWnd = FindWindow(null, "MAME: Hook (World) [hook]");  //找到窗口
            SwitchToThisWindow((IntPtr)hWnd, false);                   //得到输入焦点
            //
            
            int btScancode = 0;
    //模拟键盘按下,此处一定要注意,写入一次按下或弹起消息的步骤!
            btScancode = MapVirtualKey((byte)0X4a, 0);           //按键“j”的虚拟键位代码
            KBCWait4IBE();
            SetPortVal(KBC_KEY_CMD, (IntPtr)0xD2, 1);
            KBCWait4IBE();
            SetPortVal(KBC_KEY_DATA, (IntPtr)0xe2, 1);
            KBCWait4IBE();
            SetPortVal(KBC_KEY_CMD, (IntPtr)0xD2, 1);
            KBCWait4IBE();
            SetPortVal(KBC_KEY_DATA, (IntPtr)btScancode, 1);
            Thread.Sleep(5); 
            //模拟弹起,步骤很重要
            KBCWait4IBE();
            if (SetPortVal(0x64, (IntPtr)0xD2, 1) == false)
                MessageBox.Show("弹起时");
            KBCWait4IBE();
            SetPortVal(KBC_KEY_DATA, (IntPtr)0xe0, 1);
            KBCWait4IBE();
            if (SetPortVal(0x64, (IntPtr)0xD2, 1) == false)
                MessageBox.Show("弹起时");
            KBCWait4IBE();
            if ((SetPortVal(0x60, (IntPtr)(btScancode | 0x80), 1)==false))
                MessageBox.Show("弹起写入失败");          



        }


        private void Form1_Load(object sender, EventArgs e)
        {
            //初始化
            sendwinio();


        }


        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            ShutdownWinIo(); 
        } 


        
    }
}

/*
///
附上虚拟键位码表:
// mouse movements
            move = 0x0001,
            leftdown = 0x0002,
            leftup = 0x0004,
            rightdown = 0x0008,
            rightup = 0x0010,
            middledown = 0x0020,
            //keyboard stuff
            VK_LBUTTON = 1,
            VK_RBUTTON = 2,
            VK_CANCEL = 3,
            VK_MBUTTON = 4,
            VK_BACK = 8,
            VK_TAB = 9,
            VK_CLEAR = 12,
            VK_RETURN = 13,
            VK_SHIFT = 16,
            VK_CONTROL = 17,
            VK_MENU = 18,
            VK_PAUSE = 19,
            VK_CAPITAL = 20,
            VK_ESCAPE = 27,
            VK_SPACE = 32,
            VK_PRIOR = 33,
            VK_NEXT = 34,
            VK_END = 35,
            VK_HOME = 36,
            VK_LEFT = 37,
            VK_UP = 38,
            VK_RIGHT = 39,
            VK_DOWN = 40,
            VK_SELECT = 41,
            VK_PRINT = 42,
            VK_EXECUTE = 43,
            VK_SNAPSHOT = 44,
            VK_INSERT = 45,
            VK_DELETE = 46,
            VK_HELP = 47,
            VK_NUM0 = 48, //0
            VK_NUM1 = 49, //1
            VK_NUM2 = 50, //2
            VK_NUM3 = 51, //3
            VK_NUM4 = 52, //4
            VK_NUM5 = 53, //5
            VK_NUM6 = 54, //6
            VK_NUM7 = 55, //7
            VK_NUM8 = 56, //8
            VK_NUM9 = 57, //9
            VK_A = 65, //A
            VK_B = 66, //B
            VK_C = 67, //C
            VK_D = 68, //D
            VK_E = 69, //E
            VK_F = 70, //F
            VK_G = 71, //G
            VK_H = 72, //H
            VK_I = 73, //I
            VK_J = 74, //J
            VK_K = 75, //K
            VK_L = 76, //L
            VK_M = 77, //M
            VK_N = 78, //N
            VK_O = 79, //O
            VK_P = 80, //P
            VK_Q = 81, //Q
            VK_R = 82, //R
            VK_S = 83, //S
            VK_T = 84, //T
            VK_U = 85, //U
            VK_V = 86, //V
            VK_W = 87, //W
            VK_X = 88, //X
            VK_Y = 89, //Y
            VK_Z = 90, //Z
            VK_NUMPAD0 = 96, //0
            VK_NUMPAD1 = 97, //1
            VK_NUMPAD2 = 98, //2
            VK_NUMPAD3 = 99, //3
            VK_NUMPAD4 = 100, //4
            VK_NUMPAD5 = 101, //5
            VK_NUMPAD6 = 102, //6
            VK_NUMPAD7 = 103, //7
            VK_NUMPAD8 = 104, //8
            VK_NUMPAD9 = 105, //9
            VK_NULTIPLY = 106,
            VK_ADD = 107,
            VK_SEPARATOR = 108,
            VK_SUBTRACT = 109,
            VK_DECIMAL = 110,
            VK_DIVIDE = 111,
            VK_F1 = 112,
            VK_F2 = 113,
            VK_F3 = 114,
            VK_F4 = 115,
            VK_F5 = 116,
            VK_F6 = 117,
            VK_F7 = 118,
            VK_F8 = 119,
            VK_F9 = 120,
            VK_F10 = 121,
            VK_F11 = 122,
            VK_F12 = 123,
            VK_NUMLOCK = 144,
            VK_SCROLL = 145,
            middleup = 0x0040,
            xdown = 0x0080,
            xup = 0x0100,
            wheel = 0x0800,
            virtualdesk = 0x4000,
            absolute = 0x8000
*/

你可能感兴趣的:(C#,c#,byte,hook,object,button,cmd)