最近想玩网游,想用按键精灵来自动做一些事情,可惜游戏屏蔽了按键精灵,也没办法用普通的window消息来实现。
郁闷中,偶然发现一个winIO,可以实现驱动级模拟,
http://apps.hi.baidu.com/share/detail/22536342
不过呢本人对vb不熟,于是萌生了改成java版的念头。
首先是java调用dll,不用说了,最容易的是jnative。
首先实现winIO部分api
import org.xvolks.jnative.JNative; import org.xvolks.jnative.Type; import org.xvolks.jnative.pointers.Pointer; import org.xvolks.jnative.pointers.memory.MemoryBlockFactory; public class WinIOAPI { public static final int CONTROL_PORT = 0x64; public static final int DATA_PORT = 0x60; static{ System.loadLibrary("WinIo32"); JNative.setLoggingEnabled(true); if(!InitializeWinIo()){ System.err.println("Cannot Initialize the WinIO"); System.exit(1); } } public static void KBCWait4IBE() throws Exception{ int val=0; do { Pointer p=new Pointer(MemoryBlockFactory.createMemoryBlock(8)); if(!GetPortVal(CONTROL_PORT,p, 1)){ System.err.println("Cannot get the Port"); } val = p.getAsInt(0); } while ((0x2&val)>0); } public static boolean InitializeWinIo() { try{ JNative jnative = new JNative("WinIo32","InitializeWinIo"); jnative.setRetVal(Type.INT); jnative.invoke(); int re=jnative.getRetValAsInt(); jnative.dispose(); return re>0; }catch (Exception e) { e.printStackTrace(); return false; }finally{ } } public static boolean GetPortVal(int portAddr, Pointer pPortVal, int size) throws Exception{ JNative j2 = new JNative("WinIo32","GetPortVal"); j2.setRetVal(Type.INT); j2.setParameter(0, portAddr); j2.setParameter(1, pPortVal); j2.setParameter(2, size); j2.invoke(); int re=j2.getRetValAsInt(); j2.dispose(); return re>0; } public static boolean SetPortVal(int portAddr, int portVal, int size) throws Exception{ JNative j2 = new JNative("WinIo32","SetPortVal"); j2.setRetVal(Type.INT); j2.setParameter(0, portAddr); j2.setParameter(1,portVal); j2.setParameter(2, size); j2.invoke(); int re=j2.getRetValAsInt(); j2.dispose(); return re>0; } }
由于输入的不是VK值,所以我们还需要一个函数来把vk转化为键盘值
import java.awt.event.KeyEvent; import java.util.HashMap; import java.util.Map; import org.xvolks.jnative.JNative; import org.xvolks.jnative.Type; import org.xvolks.jnative.exceptions.NativeException; public class User32 extends org.xvolks.jnative.util.User32{ private static Map<Integer,Integer> keycache=new HashMap(); public static int MapVirtualKeyA(int key) throws Exception{ if(!keycache.containsKey(key)){ JNative jnative=new JNative(DLL_NAME, "MapVirtualKeyA"); jnative.setRetVal(Type.INT); jnative.setParameter(0, key); jnative.setParameter(1, 0); jnative.invoke(); int re=jnative.getRetValAsInt(); keycache.put(key, re); } return keycache.get(key); } }
最后就是按键部分
public class VirtualKeyBoard { public static void KeyDown(int key) throws Exception{ WinIOAPI.KBCWait4IBE(); WinIOAPI.SetPortVal(WinIOAPI.CONTROL_PORT,0xd2,1); WinIOAPI.KBCWait4IBE(); WinIOAPI.SetPortVal(WinIOAPI.DATA_PORT,key,1); } public static void KeyDownEx(int key) throws Exception{ WinIOAPI.KBCWait4IBE(); WinIOAPI.SetPortVal(WinIOAPI.CONTROL_PORT,0xd2,1); WinIOAPI.KBCWait4IBE(); WinIOAPI.SetPortVal(WinIOAPI.DATA_PORT,0xe0,1); WinIOAPI.KBCWait4IBE(); WinIOAPI.SetPortVal(WinIOAPI.CONTROL_PORT,0xd2,1); WinIOAPI.KBCWait4IBE(); WinIOAPI.SetPortVal(WinIOAPI.DATA_PORT,key,1); } public static void KeyUpEx(int key) throws Exception{ WinIOAPI.KBCWait4IBE(); WinIOAPI.SetPortVal(WinIOAPI.CONTROL_PORT,0xd2,1); WinIOAPI.KBCWait4IBE(); WinIOAPI.SetPortVal(WinIOAPI.DATA_PORT,0xe0,1); WinIOAPI.KBCWait4IBE(); WinIOAPI.SetPortVal(WinIOAPI.CONTROL_PORT,0xd2,1); WinIOAPI.KBCWait4IBE(); WinIOAPI.SetPortVal(WinIOAPI.DATA_PORT,(key|0x80),1); } public static void KeyUp(int key) throws Exception{ WinIOAPI.KBCWait4IBE(); WinIOAPI.SetPortVal(WinIOAPI.CONTROL_PORT,0xd2,1); WinIOAPI.KBCWait4IBE(); WinIOAPI.SetPortVal(WinIOAPI.DATA_PORT,(key|0x80),1); } public static void KeyPress(int key) throws Exception{ KeyDown(key); KeyUp(key); } }
最后附上源码,界面如下