我嘗試在使用JNA注入我自己的WndProc方法的Java程序中捕獲Windows消息。由於我只會對幾種消息類型感興趣,因此我必須將消息轉發給以前的WndProc。在我的測試(Java 1.7.0_03,64位,在Windows 7)該轉發似乎將我的鼠標所創建的窗口儘快失敗,讓我有以下異常:用JNA替換WndProc失敗,出現異常
com.sun.jna.LastErrorException: [2]The system cannot find the file specified.
at com.sun.jna.Native.invokeLong(Native Method)
at com.sun.jna.Function.invoke(Function.java:347)
at com.sun.jna.Function.invoke(Function.java:276)
at com.sun.jna.Library$Handler.invoke(Library.java:216)
at $Proxy0.CallWindowProc(Unknown Source)
at JnaWinEvents$1.callback(JnaWinEvents.java:102)
at ...
我想這很奇怪,因爲我試圖訪問哪個文件?我想有一些內存訪問或完全錯誤,所以...... :(
我正在使用最新版本的JNA,3.4.0。我在這裏或在互聯網上的其他地方發現了很多代碼示例似乎使用JNA 3.2.x(分割成jna.jar和platform.jar之前的任何版本),其中User32定義了一些非常適合這類工作的方法。在較新版本的JNA/platform中,缺少這些方法。爲什麼我自己定義了大部分類型,只能使用jna.jar,而不能使用platform.jar 以下是我用來測試的代碼,它產生了Exception。任何想法出了什麼問題以及爲什麼異常發生?
import javax.swing.*;
import com.sun.jna.*;
import com.sun.jna.win32.*;
public class JnaWinEvents extends JFrame {
public LONG_PTR prevWndProc = null; // so it won't get GC'ed
public User32.WNDPROC wndProcCallbackListener = null; // so it won't get GC'ed
public JnaWinEvents() {
this.add(new JLabel("Hello StackExchange!"));
this.pack();
this.setVisible(true);
setupEventsListener();
}
public static class LONG_PTR extends IntegerType {
public LONG_PTR() {
this(0);
}
public LONG_PTR(long value) {
super(Pointer.SIZE, value);
}
}
static class HANDLE extends PointerType implements NativeMapped {
}
public static class HWND extends HANDLE {
public HWND() {
}
}
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 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 LRESULT extends LONG_PTR {
public LRESULT() {
this(0);
}
public LRESULT(long value) {
super(value);
}
}
public interface User32 extends StdCallLibrary {
static int GWL_WNDPROC = -4;
User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class, W32APIOptions.DEFAULT_OPTIONS);
interface WNDPROC extends StdCallCallback {
LRESULT callback(HWND hWnd, int uMsg, WPARAM uParam, LPARAM lParam);
}
LONG_PTR GetWindowLongPtr(HWND hWnd, int nIndex) throws LastErrorException;
LRESULT CallWindowProc(LONG_PTR proc, HWND hWnd, int uMsg, WPARAM uParam, LPARAM lParam) throws LastErrorException;
LONG_PTR SetWindowLongPtr(HWND hWnd, int nIndex, WNDPROC wndProc) throws LastErrorException;
}
private void setupEventsListener() {
HWND hWnd = new HWND();
hWnd.setPointer(Native.getWindowPointer(this));
this.prevWndProc = User32.INSTANCE.GetWindowLongPtr(hWnd, User32.GWL_WNDPROC);
this.wndProcCallbackListener = new User32.WNDPROC()
{
@Override
public LRESULT callback(HWND hWnd, int uMsg, WPARAM wParam, LPARAM lParam)
{
System.out.println(hWnd + "\t" + uMsg + "\t" + wParam + "\t" + lParam);
//Call the window's actual WndProc so the events get processed.
return User32.INSTANCE.CallWindowProc(prevWndProc, hWnd, uMsg, wParam, lParam);
}
@Override
protected void finalize() throws Throwable {
System.out.println("FINALIZE!!!!");
super.finalize();
}
};
//Set the WndProc function to use our callback listener instead of the window's one.
LONG_PTR result = User32.INSTANCE.SetWindowLongPtr(hWnd, User32.GWL_WNDPROC, wndProcCallbackListener);
System.out.println("setting my window proc, result = " + result);
System.out.println("old pointer = " + this.prevWndProc);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new JnaWinEvents();
}
});
}
}
任何幫助表示讚賞,謝謝!
消息文本可能不相關,因爲LastErrorException由於顯式測試了最後一次函數調用的返回碼而引發。更好地檢查** 2 **在特定函數調用的上下文中的含義。 – 2012-04-22 11:05:36