使用 SetWindowLong 覆盖 WndProc

Using SetWindowLong to override WndProc

我需要设置一个 WindowLong 来覆盖 WndProc,我正在使用来自 coredll.dll:

的方法

public interface CoreDll extends StdCallLibrary {
 //loads the coredll with unicode options
    CoreDll INSTANCE = (CoreDll)Native.loadLibrary("coredll", CoreDll.class,
                                                   W32APIOptions.UNICODE_OPTIONS);
    //native calls
    HMODULE GetModuleHandle(String lpModuleName);
    long GetWindowLong(HWND hwnd, int gwlWndproc);
    long SetWindowLong(HWND hWnd,int nIndex,Callback dwNewLong);
    LRESULT DefWindowProc(HWND hWnd, int uMsg, WPARAM uParam,LPARAM lParam);
  }

coredll中原来的方法签名是:

LONG SetWindowLong( 
  HWND hWnd, 
  int nIndex, 
  LONG dwNewLong
); 

但根据 Microsoft "The previous value of the specified 32-bit integer indicates success. Zero indicates failure",当我使用它时,它总是 return 0。无论如何,我正在尝试以这种方式执行它:

public interface CallbackProc extends Callback, StdCall {
 LRESULT callback(HWND hWnd, int uMsg, WPARAM uParam, LPARAM lParam);
}

//Get a handle to the current process
final HWND mainHwnd = CoreDll.INSTANCE.GetModuleHandle(null);

//Get a reference to the current process to send it in the new WndProc
long value=CoreDll.INSTANCE.GetWindowLong(new HWND(mainHwnd.getPointer()), -4);
final LONG_PTR prevWndProc = new LONG_PTR(value); 

//Sets the new Method to override WndProc
final RfidCallbackProc ptr=new RfidCallbackProc() {
 @Override
    public LRESULT callback(HWND hWnd, int uMsg, WPARAM wParam,LPARAM lParam) {
        //returns the call to the process  
        return CoreDll.INSTANCE.CallWindowProc(prevWndProc, hWnd, uMsg, wParam, lParam);
    }
};

//Sets the new method to override Windows' WndProc
int num=(int)CoreDll.INSTANCE.SetWindowLong(new HWND(mainHwnd.getPointer()),-4 ,ptr);
//NUM IS ALWAYS 0

如果有人能给我提示,我将不胜感激,谢谢。

您正在检索模块句柄 (GetModuleHandle),此句柄引用加载到进程 space 中的可执行文件(exe 或 dll),而不是 window。 SetWindowsLong 失败,因为您传递给它的对象不是 window。 IIRC 你在 forms/controls 上有一个方法来获取本机 HWND,这是你应该传递给 SetWindowLong 的正确对象类型。 查看代码,我想您有一个通过 windows 消息发送代码的 RFID 库。您可以考虑使用一些本机代码将其包装到一个对象中,然后生成 "regular" .NET 事件。这会有点复杂,但避免了 SetWindowLong 可能产生的一些麻烦(例如:如果在 window 仍然有效时带有 wndproc 的对象被销毁)。

您需要获得正确的 HWND 值才能传递给 GetWindowLong()。如果是 Java window,你可以在上面使用 Native.getWindowHandle()。否则,您将不得不想出一些方法来为您定位的 window 获取 HWND

完成后,您需要将回调对象作为 dwNewLong 参数传入。您应该为 SetWindowLong() 定义一个新映射,其中第三个参数与您的回调具有相同的类型。

您还应避免使用 Java long。这是一个 64 位值,当您确定相应的本机变量也是 64 位时,应该只使用 。使用 int 表示 32 位,当本机类型为 [unsigned] long(或 LONG 表示 w32)时使用 NativeLong