使用JNA访问WindowsAPI操作Windows窗口元素

使用JNA访问WindowsAPI操作Windows窗口元素

2023年7月10日发(作者:)

使⽤JNA访问WindowsAPI操作Windows窗⼝元素问题背景:我的毕业设计中需要在Windows平台上⾯跨进程操作窗⼝。实际上是获取浏览器上⾯的⽹页中的⽂本框元素,还有windows32窗体上⾯的编辑框。然后进⾏⾃动填值等的操作。我能想到的⼀共有这么⼏种⽅法:使⽤C#编写窗体应⽤程序,然后使⽤WebBrowser浏览器控件或者嵌⼊其他应⽤程序窗⼝。如果使⽤WebBrowser控件,只能强制⽤户使⽤该C#应⽤程序上⽹,影响⽤户体验,不切实际。如果使⽤嵌⼊其他应⽤程序窗⼝的⽅式,其实就转化为了跨进程获取窗⼝的⽅法了。使⽤浏览器插件的⽅式,针对不同浏览器编写不同插件,然后让⽤户安装。当浏览器页⾯载⼊后,使⽤驻留程序(这是我毕设的核⼼进程)向浏览器发消息,执⾏浏览器插件中的JS代码操作⽹页DOM元素。但是缺点是需要编写很多插件,且调试起来,真正执⾏起来很艰难。先使⽤远程线程注⼊到⽬标进程的线程空间,创建⼀个虚拟线程,然后执⾏这个虚拟线程,向拥有这个窗⼝的界⾯线程发送消息。实际上这个⽅法和上⾯的⽅法⼤同⼩异。只不过进程注⼊⾏为会被⽤户系统的安全机制检测到,类似360安全卫⼠这种神经质的安全软件会让⽤户把我们的程序查杀掉。另外需要针对各种浏览器,各种程序窗体做特定的分析处理,代价太⼤,⽽我只不过是完成⼀个毕设,没必要⽤⽜⼑吧。使⽤模拟⽤户操作⽅式。先拿简单的⽅法说,很多脚本语⾔例如在Windows上⾯的VBS脚本执⾏时会启动WScript驻留进程,使⽤VBS的

sendKey 命令可以模拟⽤户的输⼊,甚⾄VBS能模拟⽤户⿏标的点击。还可以使⽤Python,JS(需要先让⽤户下载python)等都可以。他们的核⼼其实都是调⽤Windows系统API来完成功能,从结构上来看都是要运⾏⼀个本地即时解释器,它可以调⽤WindowsAPI,然后解释脚本执⾏操作。再说深层次⼀点就是先获取⽬标窗⼝的句柄,然后对该窗体的消息处理队列发送WM_SET_TEXT,WM_GET_TEXT,WM_EXIT等各种消息。本⽂考虑到毕设需要具有跨平台的特性,并且最好能够兼容各种不同版本的Windows。因此使⽤Java语⾔的JNA包提供的⽅便的功能调⽤WindowsAPI。⽽是⽤JNI也可以。只不过还要编写DLL,编译再加调试,会浪费很长时间。如果不是针对特定问题,使⽤成熟的JNA况且会帮助你解决低层调⽤的各种问题,何乐⽽不为呢。摘取⼀些JNA简介:JNA提供Java程序轻松访问本机共享库,⽽不需要编写任何Java代码 - 不需要JNI或本机代码。这个功能与Windows的Platform / Invoke和Python的ctypes类似。JNA允许您使⽤Java的⽅法调⽤来直接调⽤本机函数。调⽤看起来就像本机代码中的调⽤⼀样。⼤多数的⽅法调⽤不需要特殊的处理或配置。JNA使⽤⼀个⼩的JNI库存根来动态调⽤本地代码。开发⼈员使⽤Java接⼝描述⽬标本机库中的函数和结构。这使得很容易利⽤本机平台功能,⽽不会导致为多个平台配置和构建JNI代码的⾼开销。因此,JNA提供了相⽐较性能来说更关注平台适应以及便利性,节省使⽤者需要⾯对多版本,多平台开发程序的时间。除了Windows, JNA还⽀持多种其他的平台。例如ARM,安卓,Linux等。JNA可以通过Maven包管理下载。如果不适⽤Maven管理包,可以⾃⼰下载下⾯的两个包放到项⽬中:这个是必备的参考⽂档:JNA的GitHub地址:为了⽰范其简单性,看下⾯的代码。import 32;import ;import r;/** * Created by lenovo on 2017/4/27. * 使⽤winID来获得窗⼝的类型和标题,然后发送消息或者其他操作 * */public class jnaTest { public static void main(String[] args) { HWND hwnd = ndow (null, "QQ"); // 第⼀个参数是Windows窗体的窗体类,第⼆个参数是窗体的标题。不熟悉windows编程的需要先找⼀些Windows窗体数据结构的知识来看看,还有windows消息循环处理,其他的东西不⽤看太多。 if (hwnd == null) { n("QQ is not running"); } else{ ndow(hwnd, 9 ); // SW_RESTORE egroundWindow(hwnd); // bring to front //egroundWindow() //获取现在前台窗⼝ qqwin_rect = new (); dowRect(hwnd, qqwin_rect); int qqwin_width = qqwin_-qqwin_; int qqwin_height = qqwin_-qqwin_; ndow(hwnd, 700, 100, qqwin_width, qqwin_height, true); for(int i = 700; i > 100; i -=10) { ndow(hwnd, i, 100, qqwin_width, qqwin_height, true); // bring to front try { (80); }catch(Exception e){} } //ssage(hwnd, _CLOSE, null, null); // can be WM_QUIT in some occasio }//在Windows中,⽂件拥有⼤量的操作⽤户界⾯的API。可以看到JNA在包命名上也遵照了DLL的命名规律。如果我们事先打开QQ程序的登陆界⾯,当我们运⾏上⾯的程序时,就会将QQ登陆窗体置于前台显⽰同时将他从屏幕的右边移动到屏幕的左⾯。另外,学过windows编程的都知道,⼀个windows32程序⼀般都会有⾃⼰独有的窗体类,即叫做 Window Class,例如 windows下的图⽚查看器的主窗⼝类为"Photo_lightweight_Viewer", 记事本窗⼝的窗体类叫做"Notepad"。⼀个窗⼝类是⼀个窗体风格,程序中可以定义多个窗体类。当然,WIndows32程序也可以使⽤其他程序的窗体类。上⾯的

FindWindow 函数的第⼀个参数可以传⼊⼀个窗体类名,这样可以缩⼩低层JNA调⽤

FindWindowEX 函数查找的范围。对于Windows窗体的信息,可以使⽤

WinID 这个软件来查询。VS编程的同学可以使⽤Spy++⼯具查看。下⾯来解决我上⾯说的主要问题:import D;import 32;import ;import r;/** * Created by lenovo on 2017/4/27. * 使⽤winID来获得窗⼝的类型和标题,然后发送消息或者其他操作 * */public class jnaTest { public static void main(String[] args) { hwnd = ndow (null, "QQ"); // 第⼀个参数是Windows窗体的窗体类,第⼆个参数是窗体的标题。不熟悉windows编程的需要先找⼀些Windows窗体数据结构的知识来看看,还有windows消息循环处理,其他的东西不⽤看太多。 if (hwnd == null) { n("Excel is not running"); } else{ ndow(hwnd, 9 ); // SW_RESTORE egroundWindow(hwnd); // bring to front String username = "yourQQnumber"; for(Character c: Array()) sendChar(c); } } static input = new ( ); static void sendChar(char ch){ = new ( _KEYBOARD ); e("ki"); // Because setting INPUT_INPUT_KEYBOARD is not enough: /d/msg/jna-users/NDBGwC1VZbU/cjYCQ1CjBwAJ = new ( 0 ); = new ( 0 ); aInfo = new _PTR( 0 ); // Press = new ( rCase(ch) ); // 0x41 s = new ( 0 ); // keydown put( new ( 1 ), ( [] ) y( 1 ), () ); // Release = new ( rCase(ch) ); // 0x41 s = new ( 2 ); // keyup put( new ( 1 ), ( [] ) y( 1 ), () ); }}注意,使⽤前需要先选定⽬标焦点。感谢强⼤的⾕歌

发布者:admin,转转请注明出处:http://www.yc00.com/web/1688931499a184820.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信