最近想玩网游,想用按键精灵来自动做一些事情,可惜游戏屏蔽了按键精灵,也没办法用普通的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 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);
}} 最后附上源码,界面如下