JNA介绍及使用JNA监听鼠标实现

Java本身是没有提供直接访问系统的API方法,查了下资料,要实现鼠标钩子有3种方法, 
1、使用JNI方法,需要自己写C实现,比较复杂。 
2、使用swt extension,直接提供了鼠标钩子的实现,但是用它调用其它windows api,没有成功,放弃了使用它。 
3、使用JNA,JNA是建立在JNI 技术之上的,简化了Java访问window api的方法。 

JNA(Java Native Access )提供一组Java工具类用于在运行期动态访问系统本地库(native library:如Window的dll)而不需要编写任何Native/JNI代码。开发人员只要在一个java接口中描述目标native library的函数与结构,JNA将自动实现Java接口到native function的映射。 
优点: 
JNA可以让你像调用一般java方法一样直接调用本地方法。就和直接执行本地方法差不多,而且调用本地方法还不用额外的其他处理或者配置什么的,也不需要多余的引用或者编码,使用很方便。 
JNA描述: 
JNA类库使用一个很小的本地类库sub动态的调用本地代码。程序员只需要使用一个特定的java接口描述一下将要调用的本地代码的方法的结构和一些基本属性。这样就省了为了适配多个平台而大量的配置和编译代码。因为调用的都是JNA提供的公用jar 包中的接口。 

官网:https://jna.java.net/

源码:https://github.com/twall/jna

学习文档: http://www.cnblogs.com/lanxuezaipiao/p/3635556.html

maven repository:http://mvnrepository.com/artifact/net.java.dev.jna/jna

<dependency> 
<groupId>net.java.dev.jna</groupId> 
<artifactId>jna</artifactId> 
<version>4.1.0</version> 
</dependency> 
<dependency> 
<groupId>net.java.dev.jna</groupId> 
<artifactId>platform</artifactId> 
<version>3.5.2</version> 
</dependency>

下面我们用JNA实现鼠标的钩子:
1.定义鼠标钩子数据结构体
package cn.slimsmart.test.jna;

import java.util.Arrays;
import java.util.List;

import com.sun.jna.Structure;
import com.sun.jna.platform.win32.BaseTSD.ULONG_PTR;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinUser.POINT;

/**
 * 定义鼠标钩子数据结构体
 */
public class MouseHookStruct extends Structure{

 public static class ByReference extends MouseHookStruct implements Structure.ByReference {};
    public POINT pt; //点坐标
    public HWND hwnd;//窗口句柄
    public int wHitTestCode;
    public ULONG_PTR dwExtraInfo; //扩展信息
   
    //返回属性顺序
 @Override
 protected List getFieldOrder() {
  return Arrays.asList("dwExtraInfo","hwnd","pt","wHitTestCode");
 }
}
2.定义钩子
package cn.slimsmart.test.jna;

import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.LRESULT;
import com.sun.jna.platform.win32.WinDef.WPARAM;
import com.sun.jna.platform.win32.WinUser.HHOOK;
import com.sun.jna.platform.win32.WinUser.HOOKPROC;

/**
 * 定义鼠标钩子,及事件监听回调
 */
public abstract class MouseHookListener implements HOOKPROC {
 public User32 lib = null; //window应用程序接口
 public HHOOK hhk; //钩子的句柄
 //回调
 //返回这个值链中的下一个钩子程序,返回值的含义取决于钩型
 public abstract LRESULT callback(int nCode, WPARAM wParam, MouseHookStruct lParam);
}
3.实现监听鼠标事件

package cn.slimsmart.test.jna;

import com.sun.jna.Platform;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.HMODULE;
import com.sun.jna.platform.win32.WinDef.LRESULT;
import com.sun.jna.platform.win32.WinDef.WPARAM;
import com.sun.jna.platform.win32.WinUser;
import com.sun.jna.platform.win32.WinUser.HHOOK;
import com.sun.jna.platform.win32.WinUser.MSG;

/**
 * 鼠标钩子
 */
public class MouseHook {
 //鼠标事件编码
 public static final int WM_MOUSEMOVE = 512;
 public static final int WM_LBUTTONDOWN = 513;
 public static final int WM_LBUTTONUP = 514;
 public static final int WM_RBUTTONDOWN = 516;
 public static final int WM_RBUTTONUP = 517;
 public static final int WM_MBUTTONDOWN = 519;
 public static final int WM_MBUTTONUP = 520;
 public User32 lib;
 private static HHOOK hhk;
 private MouseHookListener mouseHook;
 private HMODULE hMod;
 private boolean isWindows = false;

 public MouseHook() {
  isWindows = Platform.isWindows();
  if (isWindows) {
   lib = User32.INSTANCE;
   hMod = Kernel32.INSTANCE.GetModuleHandle(null);
  }

 }
 //添加钩子监听
 public void addMouseHookListener(MouseHookListener mouseHook) {
  this.mouseHook = mouseHook;
  this.mouseHook.lib = lib;
 }
 //启动
 public void startWindowsHookEx() {
  if (isWindows) {
   lib.SetWindowsHookEx(WinUser.WH_MOUSE_LL, mouseHook, hMod, 0);
   int result;
   MSG msg = new MSG();
   while ((result = lib.GetMessage(msg, null, 0, 0)) != 0) {
    if (result == -1) {
     System.err.println("error in get message");
     break;
    } else {
     System.err.println("got message");
     lib.TranslateMessage(msg);
     lib.DispatchMessage(msg);
    }
   }
  }

 }
 //关闭
 public void stopWindowsHookEx() {
  if (isWindows) {
   lib.UnhookWindowsHookEx(hhk);
  }

 }

 public static void main(String[] args) {
  try {
   MouseHook mouseHook = new MouseHook();
   mouseHook.addMouseHookListener(new MouseHookListener() {
    //回调监听
    public LRESULT callback(int nCode, WPARAM wParam, MouseHookStruct lParam) {
     if (nCode >= 0) {
      switch (wParam.intValue()) {
      case MouseHook.WM_MOUSEMOVE:
       System.err.println("mouse move left button down, x=" + lParam.pt.x + " y=" + lParam.pt.y);
       break;
      case MouseHook.WM_LBUTTONDOWN:
       System.err.println("mouse down left button down, x=" + lParam.pt.x + " y=" + lParam.pt.y);
       break;
      case MouseHook.WM_LBUTTONUP:
       System.err.println("mouse up left button up, x=" + lParam.pt.x + " y=" + lParam.pt.y);
       break;
      case MouseHook.WM_MBUTTONDOWN:
       break;
      case MouseHook.WM_MBUTTONUP:
       break;
      }
     }
     //将钩子信息传递到当前钩子链中的下一个子程,一个钩子程序可以调用这个函数之前或之后处理钩子信息
     //hhk:当前钩子的句柄
     //nCode :钩子代码; 就是给下一个钩子要交待的,钩传递给当前Hook过程的代码。下一个钩子程序使用此代码,以确定如何处理钩的信息。
     //wParam:要传递的参数; 由钩子类型决定是什么参数,此参数的含义取决于当前的钩链与钩的类型。
     //lParam:Param的值传递给当前Hook过程。此参数的含义取决于当前的钩链与钩的类型。
     return lib.CallNextHookEx(hhk, nCode, wParam, lParam.getPointer());
    }
   });
   mouseHook.startWindowsHookEx();

   Thread.sleep(20000);
   mouseHook.stopWindowsHookEx();
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
}

你可能感兴趣的:(java)