2014-02-17 42 views
3

我試圖通過使用JNA來訪問窗口消息(例如WM_POINTERDOWN)來構建Java應用程序。有了這個選項,我將把我的應用程序變成一個觸摸敏感的應用程序。到目前爲止,我的當前代碼獲取了此窗口消息,但可能會覆蓋其他一些重要的Java本機代碼,以便JFrame不會按我期望的方式做出反應(例如,在調整JFrame的大小時,它會填充新添加的區域黑色)。爲什麼我的JNA使用應用程序沒有正確的反應?

這是我的聽衆,當一個新的窗口收到的郵件將被稱爲:

public MyListener listener = new MyListener() { 
     public LRESULT callback(HWND hWnd, int uMsg, WPARAM uParam, 
       LPARAM lParam) { 

        //handle the window message here 

      return User32.INSTANCE.DefWindowProc(hWnd, uMsg, uParam, lParam); 
     } 
    }; 

接口myListener的:

import com.sun.jna.platform.win32.WinDef.HWND; 
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.win32.StdCallLibrary.StdCallCallback; 

public interface MyListener extends StdCallCallback { 

    public LRESULT callback(HWND hWnd, int uMsg, WPARAM uParam, LPARAM lParam); 
} 

在這個片段我覆蓋JFrame的原生功能,這將通常從操作系統調用,與我的聽衆:

HWND hWnd = new HWND(); 
    hWnd.setPointer(Native.getWindowPointer(this)); 

    MyUser32.MYINSTANCE 
      .SetWindowLong(hWnd, MyUser32.GWLP_WNDPROC, listener); 

該cl屁股MyUser32:

import com.sun.jna.Callback; 
import com.sun.jna.Native; 
import com.sun.jna.platform.win32.User32; 
import com.sun.jna.platform.win32.WinDef; 
import com.sun.jna.win32.W32APIOptions; 

public interface MyUser32 extends User32 { 

public static final MyUser32 MYINSTANCE = (MyUser32) Native.loadLibrary("user32", MyUser32.class, W32APIOptions.UNICODE_OPTIONS); 

/** 
* Sets a new address for the window procedure (value to be set). 
*/ 
public static final int GWLP_WNDPROC = -4; 

/** 
* Changes an attribute of the specified window 
* @param hWnd  A handle to the window 
* @param nIndex  The zero-based offset to the value to be set. 
* @param callback The callback function for the value to be set. 
*/ 
public int SetWindowLong(WinDef.HWND hWnd, int nIndex, Callback callback); 

}

也許有人有這個一個好主意。謝謝。

+0

確保您的回調實現如下窗口約定[鏈接到下一個回調(http://msdn.microsoft.com/en-us/library/windows/desktop/ms644959(V = vs.85)的.aspx#鏈)。 – technomage

回答

0

在您的回調過程中,您調用User32.INSTANCE.DefWindowProc時,實際上應該調用您用SetWindowLong覆蓋的過程。過程調用流程應該如下:

(根)默認的WndProc < - (A)自定義實現(搖擺)< - (B)你的實施

你的實現目前繞過A嵌段調用根實施直。這就是Swing特定內容被破壞的原因。

可以通過調用GetWindowLong/SetWindowLong函數(SetWindowLong分配新過程並返回替換的句柄)並使用CallWindowProc調用基本過程。

另一件事是你應該使用GetWindowLongPtr/SetWindowLongPtr函數而不是非ptr後綴版本兼容32位和64位Windows。請參閱該文檔爲SetWindowLong

提示:該功能已被SetWindowLongPtr 功能所取代。要編寫與Windows 32位和64位 版本兼容的代碼,請使用SetWindowLongPtr函數。

因此正確實施應該是沿着這些路線的東西:

MyUser32接口:

public interface MyUser32 extends User32 { 

     public static final MyUser32 MYINSTANCE = (MyUser32) Native.loadLibrary("user32", MyUser32.class, W32APIOptions.UNICODE_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, WinDef.LPARAM lParam) throws LastErrorException; 

     LONG_PTR SetWindowLongPtr(HWND hWnd, int nIndex, WNDPROC wndProc) throws LastErrorException; 
    } 

被覆蓋的過程:

private LONG_PTR baseWndProc; 

    public MyUser32.WNDPROC listener = new MyUser32.WNDPROC() { 
      public LRESULT callback(HWND hWnd, int uMsg, WPARAM uParam, 
        LPARAM lParam) { 

       // TODO handle the window message 

       // calling the base WndProc 
       return MyUser32.MYINSTANCE.CallWindowProc(this.baseWndProc, hWnd, uMsg, wParam, lParam); 
      } 
     }; 

覆蓋:

this.baseWndProc = MyUser32.MYINSTANCE.SetWindowLongPtr(hWnd, MyUser32.GWL_WNDPROC, this.listener); 

this.baseWndProc = MyUser32.MYINSTANCE.GetWindowLongPtr(hWnd, MyUser32.GWL_WNDPROC); 
    MyUser32.MYINSTANCE.SetWindowLongPtr(hWnd, MyUser32.GWL_WNDPROC, this.listener); 
相關問題