驅動級鍵盤模擬(C#)
阿新 • • 發佈:2019-02-20
我們決定來模擬“八神”的最簡單一招: 暗殺炎(就是從地上放把火過去),如果“八神”在左側,其鍵盤操作為::↓↘→+A或C。就是上圖中的SDU或SDJ按鍵。以SDJ為例子,在模擬這個鍵盤時要非常細心才行,我一開始這樣模擬:
m_IoSys.KeyPress(WinIoSys.Key.VK_S);
Thread.Sleep(200);
m_IoSys.KeyPress(WinIoSys.Key.VK_D);
Thread.Sleep(200);
m_IoSys.KeyPress(WinIoSys.Key.VK_J,200);
結果沒有成功。仔細研究了一下,其實我們按SDJ按鍵的時候,是先將S 按下,再將D鍵按下,然後彈起S鍵,再彈起D鍵,最後再按下J鍵的。那麼真正的過程應該這樣寫:
m_IoSys.KeyDown(WinIoSys.Key.VK_S);
Thread.Sleep(100);
m_IoSys.KeyDown(WinIoSys.Key.VK_D);
Thread.Sleep(100);
m_IoSys.KeyUp(WinIoSys.Key.VK_S);
Thread.Sleep(100);
m_IoSys.KeyUp(WinIoSys.Key.VK_D);
Thread.Sleep(10); //這個地方不能間隔太大,太大就整個動作連不起來了。
m_IoSys.KeyPress(WinIoSys.Key.VK_J, 200);
經過測試,成功模擬我們想要的操作。大家可以看到實際的模擬按鍵效果。
本程式在VS2008 + WinXP SP3 + WinKawaks1.48XP + KOF 2000 + P/S鍵盤 下除錯通過。
using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; namespace lizheAionWG { public class WinIo { public const int KBC_KEY_CMD = 0x64; public const int KBC_KEY_DATA = 0x60; [DllImport("winio.dll")] public static extern bool InitializeWinIo(); [DllImport("winio.dll")] public static extern bool GetPortVal(IntPtr wPortAddr, out int pdwPortVal, byte bSize); [DllImport("winio.dll")] public static extern bool SetPortVal(uint wPortAddr, IntPtr dwPortVal, byte bSize); [DllImport("winio.dll")] public static extern byte MapPhysToLin(byte pbPhysAddr, uint dwPhysSize, IntPtr PhysicalMemoryHandle); [DllImport("winio.dll")] public static extern bool UnmapPhysicalMemory(IntPtr PhysicalMemoryHandle, byte pbLinAddr); [DllImport("winio.dll")] public static extern bool GetPhysLong(IntPtr pbPhysAddr, byte pdwPhysVal); [DllImport("winio.dll")] public static extern bool SetPhysLong(IntPtr pbPhysAddr, byte dwPhysVal); [DllImport("winio.dll")] public static extern void ShutdownWinIo(); [DllImport("user32.dll")] public static extern int MapVirtualKey(uint Ucode, uint uMapType); public void sendwinio() { if (InitializeWinIo()) { KBCWait4IBE(); } } ///Wait for Buffer gets empty private void KBCWait4IBE() { int dwVal = 0; do { bool flag = GetPortVal((IntPtr)0x64, out dwVal, 1); } while ((dwVal & 0x2) > 0); } /// key down public void MykeyDown(int vKeyCoad) { int btScancode = 0; btScancode = MapVirtualKey((byte)vKeyCoad, 0); 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); } /// Key up public void MykeyUp(int vKeyCoad) { int btScancode = 0; btScancode = MapVirtualKey((byte)vKeyCoad, 0); KBCWait4IBE(); SetPortVal(KBC_KEY_CMD, (IntPtr)0xD2, 1); KBCWait4IBE(); SetPortVal(KBC_KEY_DATA, (IntPtr)0xe0, 1); KBCWait4IBE(); SetPortVal(KBC_KEY_CMD, (IntPtr)0xD2, 1); KBCWait4IBE(); SetPortVal(KBC_KEY_DATA, (IntPtr)btScancode, 1); } /// Simulate mouse down public void MyMouseDown(int vKeyCoad) { int btScancode = 0; btScancode = MapVirtualKey((byte)vKeyCoad, 0); KBCWait4IBE(); // 'wait for buffer gets empty SetPortVal(KBC_KEY_CMD, (IntPtr)0xD3, 1);// 'send write command KBCWait4IBE(); SetPortVal(KBC_KEY_DATA, (IntPtr)(btScancode | 0x80), 1);// 'write in io } /// Simulate mouse up public void MyMouseUp(int vKeyCoad) { int btScancode = 0; btScancode = MapVirtualKey((byte)vKeyCoad, 0); KBCWait4IBE(); // 'wait for buffer gets empty SetPortVal(KBC_KEY_CMD, (IntPtr)0xD3, 1); //'send write command KBCWait4IBE(); SetPortVal(KBC_KEY_DATA, (IntPtr)(btScancode | 0x80), 1);// 'write in io } //---------------------------------------------------------------------------------- //VK codes //---------------------------------------------------------------------------------- public enum Key { // 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 } } }
InitSuperKeys() 安裝WINIO驅動,一般用於Form_Load事件中呼叫 CloseSuperKeys() 解除安裝WINIO驅動,一般用於Form_Closed事件中呼叫 KeyDown(Key) 模擬普通Key鍵按下。 KeyDownEx(Key)模擬擴充套件Key鍵按下。 KeyUp(Key)模擬普通Key鍵彈起。 KeyUpEx(Key)模擬擴充套件Key鍵彈起。 KeyPress(Key)模擬普通Key鍵按下並彈起一次。其中按下和彈起的預設時間間隔是200毫秒 KeyPress(Key,Int32)模擬普通Key鍵按下並彈起一次。其中按下和彈起的時間間隔是第二個引數,單位為毫秒。 KeyPressEx(Key)模擬擴充套件按鍵Key按下並彈起一次。其中按下和彈起的預設時間間隔是200毫秒,寫入擴充套件按鍵資訊間隔時間為100毫秒 KeyPressEx(Key,Int32)模擬擴充套件按鍵Key按下並彈起一次。其中按下和彈起的時間間隔是第二個引數,單位為毫秒,寫入擴充套件按鍵資訊間隔時間為100毫秒。 KeyPressEx(Key,Int32,Int32)模擬擴充套件按鍵Key按下並彈起一次。其中按下和彈起的時間間隔是第二個引數,單位為毫秒,寫入擴充套件按鍵資訊間隔時間是第三個引數,單位為毫秒。