- 浏览: 161138 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
兰斯洛特1987:
顶!!!!谢谢分享.最近我也在研究这玩意...
Java语言的Hook实现 -
pu02203:
我把Confidant.jar, 丢进去eclipse, 里面 ...
重磅推出诛仙辅助软件第二波:Java版按键精灵 -
泣血端午:
Calculagraph 这是哪个类啊?
A星算法 -
haitaohehe:
我使用的是jstl1.0 可是在使用<c:set va ...
JSTL1.0和JSTL1.1的区别 -
micheal19840929:
学习楼主,我也测试一下~看看兼容性吧。lanlanzhilia ...
手机版飞鸽传书:无线牵
引言:最近在玩完美时空的诛仙Online(不知道这里有没人有共同爱好的),这个游戏每晚七点会出现一个任务“新科试炼”。这个任务简单地说就是做选择题,范围小到柴米油盐,大到世界大千,所以多玩的YY上出现一个频道叫“诛仙答题频道”,这个频道会即时为玩家提供正确答案,所以当大家都上YY的时候,最终出来的成绩的高低并不取决于你的知识面,而是取决你家的网速及你的反应速度(答题越早,所获得的成绩越高)。我家的网速很好,可惜我的反应速度一般,所以从来没上过一次前十,因为每次听说YY上的答案后还要移动鼠标去点击相应的答案,这个过程平均需要0.5秒,这无疑是我成绩不高的根本所在。所以我想到了通过按下键盘上的某些按键实现将鼠标移动到指定位置并模拟鼠标键按下事件(以下简称模拟)。也许你会问:这还不简单,直接加个KeyListener不就完了?但是你想过没有,在模拟的时候,窗口的焦点是在游戏窗口,而不是Java程序的窗口(甚至连窗口都没有),所以我们需要一个监听所有进程的接口,这就是我接下要说的“Hook(钩子)”(了解外挂制作的人应该知道是什么东西,没看过?百度之)。不废话,进入正题:
首先,编写之前,我们要使用到一个第三方类库,它实现的功能就是让你直接调用API,而将对Window的调用交给它处理,下载地址是:http://feeling.sourceforge.net/
将包下载完后解压,并创建项目,结构如左图,lib下的三个dll文件要拷到window/system32下,下面就是编码了:首先我们定义一个抽象类来拦截键盘事件,如下:
import org.sf.feeling.swt.win32.extension.hook.data.HookData; import org.sf.feeling.swt.win32.extension.hook.data.KeyboardHookData; import org.sf.feeling.swt.win32.extension.hook.listener.HookEventListener; public abstract class KeyboardHookEventListener implements HookEventListener{ public void acceptHookData(HookData arg0) { KeyboardHookData khd = ((KeyboardHookData) arg0); { if(khd.getTransitionState()) //处理按下事件 { doPress(khd.getWParam()); } else { doReleased(khd.getWParam()); //处理释放事件 } } } public abstract void doPress(int keyNum); public abstract void doReleased(int keyNum); }
接着再定义一个抽象类到拦截鼠标事件,如下:
import org.sf.feeling.swt.win32.extension.hook.data.HookData; import org.sf.feeling.swt.win32.extension.hook.data.MouseHookData; import org.sf.feeling.swt.win32.extension.hook.listener.HookEventListener; public abstract class MouseHookEventListener implements HookEventListener{ public void acceptHookData(HookData hookData) { int x=((MouseHookData) hookData).getPointX(); int y=((MouseHookData) hookData).getPointY(); switch(hookData.getWParam()) { case 513: doLeftPressed(x,y); break; case 514: doLeftReleased(x,y); break; case 516: doRightPressed(x,y); break; case 517: doRightReleased(x,y); break; case 519: doMiddlePressed(x,y); break; case 520: doMiddleReleased(x,y); break; default: } } protected abstract void doLeftPressed(int x,int y); protected abstract void doLeftReleased(int x,int y); protected abstract void doRightPressed(int x,int y); protected abstract void doRightReleased(int x,int y); protected abstract void doMiddlePressed(int x,int y); protected abstract void doMiddleReleased(int x,int y); }
至此,我们的项目底层架构已经完成,下面就是业务流程的控制问题了,在贴上我的代码之前,我觉得有必要先做一下诛仙答题跟项目的介绍(又要废话了,顺便帮老池免费作下广告,遇上我是他的福分,^-^)。
答题是这样的:首先,诛仙这个游戏是支持窗口化(且提供几个固定窗口大小供选择),而其中的答题窗口就是窗口中的窗口了(可拖动的)。7点,答题系统开启,每个玩家可选择进入答题窗口,等下一分钟才真正开始,这一分钟中,页面会显示出3个幸运星,但是没有题目........经过一番分析,可以确定用户要输入的有:当前使用的窗口大小及幸运星的位置(幸运星跟选项的位置不固定的,幸运星一确定,选项的位置也就知道了)。以下是关于这个业务的代码:
定义一个特定的鼠标事件响应,如下:
import java.awt.Dimension; import java.util.LinkedList; import java.util.List; public class MyMouseHookEventListener extends MouseHookEventListener { private Dimension zeroDimension; private List<Dimension> dimensions=new LinkedList<Dimension>(); private boolean needFetchZeroDimension=false; private String currentOffsetSeries=""; public void resetZeroDimension() { this.needFetchZeroDimension=true; } public void resetDimensions(String dimensionSeries) { this.dimensions.clear(); String[] dimStrs=dimensionSeries.split(","); for(int i=0;dimStrs!=null&&i<dimStrs.length/2;i++) { int width=Integer.parseInt(dimStrs[i*2])+(int)zeroDimension.getWidth(); int height=Integer.parseInt(dimStrs[i*2+1])+(int)zeroDimension.getHeight(); dimensions.add(new Dimension(width,height)); } } public String getDimensionSeries() { String dimSeries=""; for(Dimension dim:this.dimensions) { dimSeries=dimSeries+","+(int)(dim.getWidth()-zeroDimension.getWidth())+","+(int)(dim.getHeight()-zeroDimension.getHeight()); } if(dimSeries.length()>0) { dimSeries=dimSeries.substring(1); } return dimSeries; } @Override protected void doLeftPressed(int x, int y) {} @Override protected void doLeftReleased(int x, int y) {} @Override protected void doMiddlePressed(int x, int y) {} @Override protected void doMiddleReleased(int x, int y) {} @Override protected void doRightPressed(int x, int y) { if(this.needFetchZeroDimension) { this.zeroDimension=new Dimension(x,y); resetDimensions(currentOffsetSeries); this.needFetchZeroDimension=false; System.out.println("幸运星位置已获取,关闭重置模式,\r\n现在你可以使用小键盘上的12345来实现鼠标事件模拟,如果你需要重新选择请按F11"); } } @Override protected void doRightReleased(int x, int y) {} public void setCurrentOffsetSeries(String currentOffsetSeries) { this.currentOffsetSeries = currentOffsetSeries; } public List<Dimension> getDimensions() { return dimensions; } }
再定义一个运行类:
import java.awt.AWTException; import java.awt.Robot; import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.Transferable; import java.awt.event.InputEvent; import org.sf.feeling.swt.win32.extension.hook.Hook; public class ZhuXianSwifter { public static final int NUM_1=97; public static final int NUM_2=98; public static final int NUM_3=99; public static final int NUM_4=100; public static final int NUM_5=101; public static final int F_11=122; public static final int F_12=123; private static final String OFFSET_SERIES_640_480="-125,84,-125,107,-125,130,-125,152,44,0,20,0,0,0"; private static final String OFFSET_SERIES_800_600="-156,105,-156,134,-156,163,-156,190,55,0,25,0,0,0"; private static final String OFFSET_SERIES_1024_768="-200,138,-200,172,-200,211,-200,248,70,0,32,0,0,0"; /** * 使用说明: * 1、启动后先选择所使用的分辨率,目前只支持640*480,800*600,1024*768; * 2、然后使用鼠标右键点击一下试炼答题窗口的第一个幸运星的中心点即可; * 3、使用小键盘的1234选择答案,使用5点星星(第一个使用完会自动用第二个), * 4、只支持命令行模式 * 5、F11为取坐标模式,按F11开始,再次按F11结束,并将零坐标跟之前的偏移坐标复制到系统剪贴板 * 6、按F12退出程序 * @throws AWTException */ public static void main(String[] args) throws AWTException { /*注册鼠标Hook*/ final MyMouseHookEventListener mouseListener=new MyMouseHookEventListener(); Hook.MOUSE.addListener(mouseListener); Hook.MOUSE.install(); /*系统剪贴板*/ final Clipboard systemClipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); final Robot robot=new Robot(); /*键盘监听器*/ final KeyboardHookEventListener keyboardListener=new KeyboardHookEventListener(){ private boolean haveChooseMode=false; private int count=0; @Override public void doPress(int keyNum) { String mode=""; if(keyNum==F_12) { if(!mouseListener.getDimensionSeries().equals("")) { System.out.println("内容已经复制到系统剪贴板"); Transferable text = new StringSelection(mouseListener.getDimensionSeries()); systemClipboard.setContents(text,null); } System.out.println("------程序退出------"); System.exit(0); } else if(keyNum==F_11) { haveChooseMode=false; count=0; System.out.println("启动重置模式"); printChooseMode(); } else { if(haveChooseMode==false) { switch(keyNum) { case NUM_1: mode="640*480"; mouseListener.setCurrentOffsetSeries(OFFSET_SERIES_640_480); break; case NUM_2: mode="800*600"; mouseListener.setCurrentOffsetSeries(OFFSET_SERIES_800_600); break; case NUM_3: mode="1024*768"; mouseListener.setCurrentOffsetSeries(OFFSET_SERIES_1024_768); break; default: System.out.println("请重新选择:"); printChooseMode(); return; } System.out.println("您选择了"+mode+"分辨率模式"); haveChooseMode=true; mouseListener.resetZeroDimension(); printFetchZeroCoordinate(); } else { switch (keyNum) { case NUM_1: robot.mouseMove((int)mouseListener.getDimensions().get(0).getWidth(),(int)mouseListener.getDimensions().get(0).getHeight()); robot.mousePress(InputEvent.BUTTON1_MASK); robot.mouseRelease(InputEvent.BUTTON1_MASK); break; case NUM_2: robot.mouseMove((int)mouseListener.getDimensions().get(1).getWidth(),(int)mouseListener.getDimensions().get(1).getHeight()); robot.mousePress(InputEvent.BUTTON1_MASK); robot.mouseRelease(InputEvent.BUTTON1_MASK); break; case NUM_3: robot.mouseMove((int)mouseListener.getDimensions().get(2).getWidth(),(int)mouseListener.getDimensions().get(2).getHeight()); robot.mousePress(InputEvent.BUTTON1_MASK); robot.mouseRelease(InputEvent.BUTTON1_MASK); break; case NUM_4: robot.mouseMove((int)mouseListener.getDimensions().get(3).getWidth(),(int)mouseListener.getDimensions().get(3).getHeight()); robot.mousePress(InputEvent.BUTTON1_MASK); robot.mouseRelease(InputEvent.BUTTON1_MASK); break; case NUM_5: robot.mouseMove((int)mouseListener.getDimensions().get(4+count).getWidth(),(int)mouseListener.getDimensions().get(4+count).getHeight()); robot.mousePress(InputEvent.BUTTON1_MASK); robot.mouseRelease(InputEvent.BUTTON1_MASK); count++; if(count==3) { count=0; } break; default: break; } } } } @Override public void doReleased(int keyNum) {} }; Hook.KEYBOARD.addListener(keyboardListener); Hook.KEYBOARD.install(); // 註冊事件 printChooseMode(); } private static void printChooseMode() { System.out.println("请选择窗口大小:"); System.out.println("NUM1:640*480"); System.out.println("NUM2:800*600"); System.out.println("NUM3:1024*768"); } private static void printFetchZeroCoordinate() { System.out.println("请在第一个幸运星的中心上点击鼠标右键"); } }
以上就是本项目的所以代码,运行时要先按小键盘的1/2/3选择使用的窗口大小,然后在第一个幸运星的中心点击下右键鼠标就可以了,之后你就可以用小键盘的1/2/3/4/5(5是幸运星)来选择你的答案了。
发表评论
-
快速开方算法比较
2010-08-18 17:34 1339快速开方算法比较: public class Test { ... -
Java父线程与子线程
2010-06-12 12:49 2712问:在父线程中New了一个子线程,想在停止父线程时也停止子线程 ... -
反射在设计模式中的应用
2010-06-08 10:52 698利用设计模式可以使我 ... -
Reader和InputStream的区别
2010-05-28 13:21 1234Reader支持16位的Unicode字符输出,InputSt ... -
[原创]多线程之队列式执行任务
2010-04-29 10:24 918前言:最近做的一个项目正好要用到多线程,而且要实现 ... -
java内存的思考与总结
2010-02-10 16:13 01. java中堆与栈 在Java程 ... -
关于switch语句
2010-02-10 16:10 779switch语句在一定程度上是有动态跳转(函数指针就是一种动态 ... -
代码优化之-优化除法
2010-02-09 13:57 2411说明:文章中的很多数据可能在新的CPU或不同的CPU或不同的系 ... -
Supported Encodings
2010-02-09 13:41 877The classes java.io.InputStream ... -
应用JAD批量反编译CLASS文件
2010-02-09 12:31 748反编译别人的程序是不对的,但是有时候由于某种原因,不得不反编译 ... -
数组快速复制
2010-02-08 15:33 667data[0] = 0 ; int len = 1 ; i ... -
深刻理解Java编程的7个例子
2010-01-14 10:13 6071. 阅读下列代码回答问 ... -
原子变量(AtomicLong, AtomicInteger, AtomicReference)
2009-11-06 09:30 3271J2SE 5.0提供了一组atomic class来帮助我们简 ... -
重磅推出诛仙辅助软件第二波:Java版按键精灵
2009-09-16 18:43 3931前言:上次推出诛仙答题辅助软件用起来不错(想上十名榜不难,YY ...
相关推荐
Java语言的Hook实现[参照].pdf
wxwork_pc_api 使用HOOK技术将核心功能封装成dll,并提供简易的接口给支持调用dll的语言使用。 你可以通过扩展 wxwork_pc_api 来实现: 监控或收集企业微信消息 自动消息推送 聊天机器人 通过企业微信远程控制你的...
java.lang.instrument 提供允许 Java 编程语言代理检测运行在 JVM 上的程序的服务。 java.lang.management 提供管理接口,用于监视和管理 Java 虚拟机以及 Java 虚拟机在其上运行的操作系统。 java.lang.ref 提供...
Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems公司于1995年5月正式发布。它的设计目标是“一次编写,到处运行(Write Once, Run Anywhere)”,这意味着开发者可以使用Java编写应用程序,并在支持...
java.lang.instrument 提供允许 Java 编程语言代理检测运行在 JVM 上的程序的服务。 java.lang.management 提供管理接口,用于监视和管理 Java 虚拟机以及 Java 虚拟机在其上运行的操作系统。 java.lang.ref 提供了...
java.lang.instrument 提供允许 Java 编程语言代理检测运行在 JVM 上的程序的服务。 java.lang.management 提供管理接口,用于监视和管理 Java 虚拟机以及 Java 虚拟机在其上运行的操作系统。 java.lang.ref 提供了...
java.lang.instrument 提供允许 Java 编程语言代理检测运行在 JVM 上的程序的服务。 java.lang.management 提供管理接口,用于监视和管理 Java 虚拟机以及 Java 虚拟机在其上运行的操作系统。 java.lang.ref 提供...
java.lang.instrument 提供允许 Java 编程语言代理检测运行在 JVM 上的程序的服务。 java.lang.management 提供管理接口,用于监视和管理 Java 虚拟机以及 Java 虚拟机在其上运行的操作系统。 java.lang.ref 提供...
java.lang.instrument 提供允许 Java 编程语言代理检测运行在 JVM 上的程序的服务。 java.lang.management 提供管理接口,用于监视和管理 Java 虚拟机以及 Java 虚拟机在其上运行的操作系统。 java.lang.ref 提供...
免费的微信HOOK和框架,提供HTTPAPI接口和封装好的框架,微信版本为3.6.0.18,内置HTTPAPI,方便您使用自己喜欢的编程语言快速开发。 支持文本代码,多人艾特,emoji表情,微信表情等,全面解决收发消息、昵称内的...
软件开发设计:PHP、QT、应用软件开发、系统软件开发、移动应用开发、网站开发C++、Java、python、web、C#等语言的项目开发与学习资料 硬件与设备:单片机、EDA、proteus、RTOS、包括计算机硬件、服务器、网络设备、...
java.lang.instrument 提供允许 Java 编程语言代理检测运行在 JVM 上的程序的服务。 java.lang.management 提供管理接口,用于监视和管理 Java 虚拟机以及 Java 虚拟机在其上运行的操作系统。 java.lang.ref 提供了...
java.lang.instrument 提供允许 Java 编程语言代理检测运行在 JVM 上的程序的服务。 java.lang.management 提供管理接口,用于监视和管理 Java 虚拟机以及 Java 虚拟机在其上运行的操作系统。 java.lang.ref 提供了...
您可以通过扩展wechat_pc_api来实现:监控或收集微信消息自动消息推聊天机器人通过微信远程控制你的设备测试可以使用语言有C / C ++,C#,易语言,Python,Java,Go,NodeJs,PHP,VB,Delphi。目前支持的微信PC...
BeikeShop商城 Beike多语言商城 多货币商城B2C商城系统 代码100%开源 PHP商城系统 H5/PC商城 跨境电商系统 跨境商城系统 电商商城... Event 机制实现Hook功能,自定义可视化装修。BeikeShop一款开源好用的跨境电商系统
特点:支付通知单,0程序费实时到账(不经过任何第三方,直接到账微信/支付宝余额),提供无依赖服务端源代码运行在自己的服务器上,支持php / java / python等任意开发语言监听,监听方式非xp框架HOOK的方式,无需...