2010-06-20 237 views
13

我已经在Windows中安装了用于安装键盘挂钩的JNA代码(使用JNA示例)。代码编译和一切,我得到安装钩子(我成功处理钩),我也可以卸载钩成功。但是,当我按下键盘上的任何键时,回叫将永远不会被调用。这里是我的代码(大部分是类型定义从JNA例子了,转到“主”直接对我而言)Windows中的JNA键盘挂钩

import com.sun.jna.IntegerType; 
import com.sun.jna.Pointer; 
import com.sun.jna.PointerType; 
import com.sun.jna.Structure; 
import com.sun.jna.FromNativeContext; 
import com.sun.jna.ptr.IntByReference; 
import com.sun.jna.ptr.PointerByReference; 
import com.sun.jna.win32.StdCallLibrary; 
import com.sun.jna.win32.StdCallLibrary.StdCallCallback; 
import com.sun.jna.Native; 
import com.sun.jna.Platform; 
import com.sun.jna.Library; 
import com.sun.jna.win32.W32APITypeMapper; 
import com.sun.jna.win32.W32APIFunctionMapper; 

import java.util.Map; 
import java.util.HashMap; 

public class HelloWorld { 
    static Map UNICODE_OPTIONS = new HashMap() { 
     { 
      put("type-mapper", W32APITypeMapper.UNICODE); 
      put("function-mapper", W32APIFunctionMapper.UNICODE); 
     } 
    }; 

    public static class LONG_PTR extends IntegerType { 
     public LONG_PTR() { this(0); } 
     public LONG_PTR(long value) { super(Pointer.SIZE, value); } 
    } 

    public static class UINT_PTR extends IntegerType { 
     public UINT_PTR() { super(Pointer.SIZE); } 
     public UINT_PTR(long value) { super(Pointer.SIZE, value); } 
     public Pointer toPointer() { return Pointer.createConstant(longValue()); } 
    } 

    public static class ULONG_PTR extends IntegerType { 
     public ULONG_PTR() { this(0); } 
     public ULONG_PTR(long value) { super(Pointer.SIZE, value); } 
    } 

    public static class LRESULT extends LONG_PTR { 
     public LRESULT() { this(0); } 
     public LRESULT(long value) { super(value); } 
    } 

    public static class WPARAM extends UINT_PTR { 
     public WPARAM() { this(0); } 
     public WPARAM(long value) { super(value); } 
    } 

    public static class LPARAM extends LONG_PTR { 
     public LPARAM() { this(0); } 
     public LPARAM(long value) { super(value); } 
    } 

    public static class KBDLLHOOKSTRUCT extends Structure { 
     public int vkCode; 
     public int scanCode; 
     public int flags; 
     public int time; 
     public ULONG_PTR dwExtraInfo; 
    } 

    static HANDLE INVALID_HANDLE_VALUE = new HANDLE() { 
     { super.setPointer(Pointer.createConstant(-1)); } 
     public void setPointer(Pointer p) { 
      throw new UnsupportedOperationException("Immutable reference"); 
     } 
    }; 

    public static class HANDLE extends PointerType { 
     public Object fromNative(Object nativeValue, FromNativeContext context) { 
      Object o = super.fromNative(nativeValue, context); 
      if (INVALID_HANDLE_VALUE.equals(o)) 
       return INVALID_HANDLE_VALUE; 
      return o; 
     } 
    } 

    public static class HHOOK extends HANDLE { } 
    public static class HINSTANCE extends HANDLE { } 
    public static class HMODULE extends HINSTANCE { } 

    public interface User32 extends StdCallLibrary { 
     User32 INSTANCE = (User32)Native.loadLibrary("user32", User32.class, UNICODE_OPTIONS); 

     static final int WH_KEYBOARD_LL = 13; 

     public static interface HOOKPROC extends StdCallCallback { 
      LRESULT callback(int nCode, WPARAM wParam, KBDLLHOOKSTRUCT lParam); 
     } 

     HHOOK SetWindowsHookEx(int idHook, HOOKPROC lpfn, HMODULE hMod, int dwThreadId); 
     LRESULT CallNextHookEx(HHOOK idHook, int nCode, WPARAM wParam, LPARAM lParam); 
     LRESULT CallNextHookEx(HHOOK idHook, int nCode, WPARAM wParam, Pointer lParam); 

     boolean UnhookWindowsHookEx(HHOOK idHook); 
    } 

    public interface Kernel32 extends StdCallLibrary { 
     Kernel32 INSTANCE = (Kernel32)Native.loadLibrary("kernel32", Kernel32.class, UNICODE_OPTIONS); 

     HMODULE GetModuleHandle(String name); 
    } 

    public static HHOOK hHook; 
    public static User32.HOOKPROC lpfn; 
    public static volatile boolean quit = false; 

    public static void main(String[] args) throws Exception { 
     HMODULE hMod = Kernel32.INSTANCE.GetModuleHandle(null); 
     System.out.println(hMod); 

     lpfn = new User32.HOOKPROC() { 
      public LRESULT callback(int nCode, WPARAM wParam, KBDLLHOOKSTRUCT lParam) { 
       System.out.println("here"); 
       quit = true; 
       return User32.INSTANCE.CallNextHookEx(hHook, nCode, wParam, lParam.getPointer()); 
      } 
     }; 

     hHook = User32.INSTANCE.SetWindowsHookEx(User32.WH_KEYBOARD_LL, lpfn, hMod, 0); 
     System.out.println(hHook); 

     if(hHook != null) 
      System.out.println("Keyboard hooked, type anything to quit"); 

     while(!quit) { 
      Thread.sleep(100); 
     } 

     if(User32.INSTANCE.UnhookWindowsHookEx(hHook)) 
      System.out.println("Unhooked"); 

    } 
} 

我已经做了键盘/鼠标钩子多次使用C++和C#中过去。这是我第一次尝试使用Java,而我只是不知道我是否正确导入并映射了库。有任何想法吗?

谢谢。

回答

10

看来您需要拨打GetMessagePeekMessage,这很奇怪 - 在HooksLowLevelKeyboardProc的文档中未提及。我对API的这部分内容了解不够,无法猜测原因。

我只是用示例类:

import com.sun.jna.examples.win32.*; 

public class Callback { 
    public static User32.HHOOK hHook; 
    public static User32.LowLevelKeyboardProc lpfn; 
    public static volatile boolean quit = false; 

    public static void main(String[] args) throws Exception { 
    W32API.HMODULE hMod = Kernel32.INSTANCE.GetModuleHandle(null); 
    lpfn = new User32.LowLevelKeyboardProc() { 
     public W32API.LRESULT callback(int nCode, W32API.WPARAM wParam, 
      User32.KBDLLHOOKSTRUCT lParam) { 
     System.out.println("here"); 
     quit = true; 
     return User32.INSTANCE.CallNextHookEx(hHook, nCode, wParam, lParam 
      .getPointer()); 
     } 
    }; 
    hHook = User32.INSTANCE.SetWindowsHookEx(User32.WH_KEYBOARD_LL, lpfn, hMod, 
     0); 
    if (hHook == null) 
     return; 
    User32.MSG msg = new User32.MSG(); 
    while (!quit) { 
     User32.INSTANCE.PeekMessage(msg, null, 0, 0, 0); 
     Thread.sleep(100); 
    } 
    if (User32.INSTANCE.UnhookWindowsHookEx(hHook)) 
     System.out.println("Unhooked"); 
    } 
} 
+0

锯使用的GetMessage/DispatchMessage函数另一个例子,虽然从来没有想过有什么用键盘钩子本身(我从来不需要它们在C++/C#中)。真的很感谢你的帮助McDowell,我再次得到了我的理智:) – temp 2010-06-20 15:00:39

+2

如何获得com.sun.jna.examples.win32?我无法从jna.jar或platform.jar中找到它。请告诉我。谢谢。 – 2011-05-06 21:26:41

+3

@强李 - 我写这个代码反对JNA 3.0.9;示例类位于'examples.jar'中 – McDowell 2011-05-07 08:46:20

0

简约的例子:

import com.sun.jna.platform.win32.Kernel32; 
import com.sun.jna.platform.win32.User32; 
import com.sun.jna.platform.win32.WinDef.HINSTANCE; 
import com.sun.jna.platform.win32.WinDef.LPARAM; 
import com.sun.jna.platform.win32.WinDef.LRESULT; 
import com.sun.jna.platform.win32.WinDef.WPARAM; 
import com.sun.jna.platform.win32.WinUser.HOOKPROC; 

public class MainTestKeyHook { 


    public static void main(String[] args) throws Exception { 
     HOOKPROC hookProc = new HOOKPROC_bg(); 
     HINSTANCE hInst = Kernel32.INSTANCE.GetModuleHandle(null); 

     User32.HHOOK hHook = User32.INSTANCE.SetWindowsHookEx(User32.WH_KEYBOARD_LL, hookProc, hInst, 0); 
     if (hHook == null) 
      return; 
     User32.MSG msg = new User32.MSG(); 
     System.err.println("Please press any key ...."); 
     while (true) { 
      User32.INSTANCE.GetMessage(msg, null, 0, 0); 
     } 
    } 
} 

class HOOKPROC_bg implements HOOKPROC { 

    public HOOKPROC_bg() { 
    } 

    public LRESULT callback(int nCode, WPARAM wParam, LPARAM lParam) { 
     System.err.println("callback bbbnhkilhjkibh nCode: " + nCode); 
     return new LRESULT(0); 
    } 
}