【问题标题】:Why my JNA using application doesn't react in a right way?为什么我的 JNA 使用应用程序没有以正确的方式做出反应?
【发布时间】:2014-02-17 16:14:07
【问题描述】:

我正在尝试通过使用 JNA 来构建一个 java 应用程序来访问窗口消息(例如 WM_POINTERDOWN)。使用此选项,我将把我的应用程序变成一个触摸感应应用程序。到目前为止,我当前的代码收到了这个窗口消息,但可能会覆盖一些其他重要的 Java 本机代码,因此 JFrame 不会以我期望的方式做出反应(例如,在将 JFrame 调整为更大的时候,它会填充新添加的区域黑色)。

这是我的监听器,当有新的窗口消息到达时会调用它:

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);
}

在这个 sn-p 中,我用我的侦听器覆盖了 JFrame 的本机函数,该函数通常会从操作系统调用:

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

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

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);

}

也许有人对此有一个好主意。谢谢。

【问题讨论】:

标签: java swing jna


【解决方案1】:

在您的回调过程中,您正在调用 User32.INSTANCE.DefWindowProc,而实际上您应该调用您使用 SetWindowLong 覆盖的过程。过程调用流程如下:

(root) 默认 WndProc

您的实现当前正在绕过直接调用根实现的 A 块。这就是 Swing 特定的东西被破坏的原因。

基过程可以通过调用GetWindowLong/SetWindowLong函数获得(SetWindowLong分配新过程并将句柄返回给被替换的过程)并使用CallWindowProc调用。

另一件事是您应该使用 GetWindowLongPtr/SetWindowLongPtr 函数而不是非 ptr-postfixed 版本来兼容 32 位和 64 位 Windows。请参阅SetWindowLong 的文档:

注意此函数已被 SetWindowLongPtr 取代 功能。编写与 32 位和 64 位兼容的代码 Windows 版本,请使用 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);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-04-15
    • 2020-01-04
    • 2011-11-25
    • 1970-01-01
    • 2018-08-02
    • 1970-01-01
    • 2018-06-26
    • 1970-01-01
    相关资源
    最近更新 更多