使用SetWindowLong覆盖WndProc

时间:2015-02-11 15:37:12

标签: java windows-ce jna

我需要设置一个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
); 

但是当我使用它时它总是返回0,根据微软“指定的32位整数的前一个值表示成功。零表示失败”。无论如何,我试图以这种方式执行它:

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

如果有人能给我一个提示,我会非常感激,谢谢。

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

您需要获取正确的HWND值才能传递给GetWindowLong()。如果它是Java窗口,您可以在其上使用Native.getWindowHandle()。否则,您必须找到某种方法来获取您所定位的窗口的HWND

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

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