使用 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
。
我需要设置一个 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
。