Help with SetWindowLongPtr in 4.1.0

390 views
Skip to first unread message

Wenjun Che

unread,
Mar 9, 2015, 2:41:50 PM3/9/15
to jna-...@googlegroups.com
Hello

        I am kinda new to JNA and having trouble getting SetWindowLongPtr to compile.  Here is my code based on some research:

        int GWL_WNDPROC = -4;
        WinUser.WindowProc proc = new WinUser.WindowProc() {
               ...
        }
         WinDef.HWND hWnd = new WinDef.HWND(Native.getWindowPointer(myWIndow));
        User32.INSTANCE.SetWindowLongPtr(hWnd, GWL_WNDPROC, proc);

        The last line does not compile because SetWindowLongPtr expect LONG_PTR or Pointer.  How do I convert WindowProc to either type, or my code is completely wrong ?



Thank you 

Wenjun

Timothy Wall

unread,
Mar 9, 2015, 6:02:27 PM3/9/15
to jna-...@googlegroups.com
Make a new method declaration with the same name but with the desired parameter types

Sent from my iPhone
--
You received this message because you are subscribed to the Google Groups "Java Native Access" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jna-users+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Wenjun Che

unread,
Mar 10, 2015, 12:19:17 AM3/10/15
to jna-...@googlegroups.com
Hello 

Thank you for the response.

So I created MyUser32 class that extends User32 with

   LONG_PTR SetWindowLongPtr(HWND hWnd, int nIndex, WindowProc wndProc)

When I ran it, I got an exception about SetWindowLongPtr not found.  So, I changed it to 

   int SetWindowLong(HWND hWnd, int nIndex, WindowProc wndProc)

Now I am getting:  JNA: Callback threw the following exception:
                              com.sun.jna.LastErrorException: [2] The system cannot find the file specified.

Here is the code:

        this.prevWndProc = MyUser32.INSTANCE.GetWindowLong(hWnd, User32.GWL_WNDPROC);
       
this.wndProcCallbackListener = new MyWinProc();
       
MyUser32.INSTANCE.SetWindowLong(hWnd, User32.GWL_WNDPROC, wndProcCallbackListener);


   
public class MyWinProc implements WinUser.WindowProc {
       
@Override
       
public WinDef.LRESULT callback(WinDef.HWND hWnd, int uMsg, WinDef.WPARAM uParam, WinDef.LPARAM lParam) {
           
return MyUser32.INSTANCE.CallWindowProc(prevWndProc, hWnd, uMsg, uParam, lParam);
       
}
   
}


I am running 32bits jdk on Windows 8.

Thanks
Wenjun
Message has been deleted

Lauri W Ahonen

unread,
Mar 10, 2015, 6:34:11 AM3/10/15
to jna-...@googlegroups.com
Hi,

The export name is different on x86 and x64

        Pointer previousFunction;
        
if (is64Bit())
            previousFunction 
= User32RW.INSTANCE.SetWindowLongPtr(handle, GWLP_WNDPROC,listener);
        
else
            previousFunction 
= User32RW.INSTANCE.SetWindowLong(handle, GWLP_WNDPROC,listener);

public static boolean is64Bit() {
        String model = System.getProperty("sun.arch.data.model");
        return model.equals("64");
}




With the signatures 
Pointer SetWindowLongPtr(HWND hWnd, int nIndex, MyWindowProc callback);
Pointer SetWindowLong(HWND hWnd, int nIndex, MyWindowProc callback);

LRESULT 
CallWindowProc(Pointer previousFunction, HWND hWnd, int uMsg, WPARAM wParam, LPARAM lParam);
public static interface MyWindowProc extends StdCallCallback {
        com
.sun.jna.platform.win32.WinDef.LRESULT callback(com.sun.jna.platform.win32.WinDef.HWND hwnd, int uMsg, com.sun.jna.platform.win32.WinDef.WPARAM wparam, Pointerlparam);
}


Also, we got the very occasional crash until we made the previous function a Pointer instead of MyWindowProc, for what it's worth.

Br,
Will

Wenjun Che

unread,
Mar 10, 2015, 11:48:17 AM3/10/15
to jna-...@googlegroups.com
Hello 

I made the changes as suggested.   Now I am getting:
 com.sun.jna.LastErrorException: [2] The system cannot find the file specified
for uMsg == 0x0084 (WM_NCHITTEST) from 
  MyUser32.INSTANCE.CallWindowProc(prevWndProc, hwnd, uMsg, wparam, lparam)

prevWndProc has the result value from SetWindowLongPtr (or SetWindowLong in 32bits java).

I am seeing same error with 32 and 64 bits java on Window7 and windows8.

Any help is greatly appreciated.
Wenjun

L Will Ahonen

unread,
Mar 10, 2015, 10:30:44 PM3/10/15
to jna-...@googlegroups.com

Can you post your callback and the error stack trace

Wenjun Che

unread,
Mar 10, 2015, 11:39:10 PM3/10/15
to jna-...@googlegroups.com
Hi,

I simplified my code to followings:

    private Pointer prevWndProc;


        myUser32 = (MyUser32) Native.loadLibrary("user32", MyUser32.class,  W32APIOptions.DEFAULT_OPTIONS);
        prevWndProc = myUser32.SetWindowLong(hwnd, User32.GWL_WNDPROC, new MyWindowProc() {
                    @Override
                    public WinDef.LRESULT callback(WinDef.HWND hwnd, int msg, WinDef.WPARAM wp, WinDef.LPARAM lp) {
                        System.out.println(msg + " " + wp + " " + lp);
                        return myUser32.CallWindowProc(prevWndProc, hwnd, msg, wp, lp);
                    }
                });

    private static interface MyWindowProc extends StdCallLibrary.StdCallCallback {
        public WinDef.LRESULT callback(WinDef.HWND hwnd, int msg, WinDef.WPARAM wp, WinDef.LPARAM lp);
    }
    private static interface MyUser32 extends StdCallLibrary {
        Pointer SetWindowLong(WinDef.HWND hwnd, int index, MyWindowProc newProc);
        Pointer SetWindowLongPtr(WinDef.HWND hwnd, int index, BaseTSD.LONG_PTR newProc);
        WinDef.LRESULT CallWindowProc(Pointer proc, WinDef.HWND hWnd, int uMsg, WinDef.WPARAM uParam, WinDef.LPARAM lParam) throws LastErrorException;
    }

When I run the code with 32bit jdk on Windows 8, I get the following exception when moving cursor around the JFrame:

132 0 13041941  (This line is output from System.out.println in the callback.  132 is msg)
JNA: Callback WinMsg$1@e05898 threw the following exception:
com.sun.jna.LastErrorException: [2] The system cannot find the file specified.

        at com
.sun.jna.Native.invokeInt(Native Method)
        at com
.sun.jna.Function.invoke(Function.java:383)
        at com
.sun.jna.Function.invoke(Function.java:315)
        at com
.sun.jna.Library$Handler.invoke(Library.java:212)
        at com
.openfin.$Proxy0.CallWindowProc(Unknown Source)
        at com
.openfin.WinMsg$1.callback(WinMsg.java:44)
        at sun
.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
        at sun
.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java
.lang.reflect.Method.invoke(Unknown Source)
        at com
.sun.jna.CallbackReference$DefaultCallbackProxy.invokeCallback(CallbackReference.java:470)
        at com
.sun.jna.CallbackReference$DefaultCallbackProxy.callback(CallbackReference.java:500)
        at sun
.awt.windows.WToolkit.eventLoop(Native Method)
        at sun
.awt.windows.WToolkit.run(Unknown Source)
        at java
.lang.Thread.run(Unknown Source)


The exception ONLY happens to msg type 132 (0x84, WM_NCHITTEST).  Same thing happens with 64bit JDK on Window 7 (replacing SetWindowLong with SetWindowLongPtr).  I also tried various data types for prevWndProc such int, BaseTSD.LONG_PTR.

Here is the command I run:

java -cp jna-example-1.0-SNAPSHOT.jar;jna-4.1.0.jar;jna-platform-4.1.0.jar  WinMsg

All I am trying to do is to intercept Window messages, read some info and forward to previously installed listener.

Thank you very much for the help
Wenjun

On Tuesday, March 10, 2015 at 6:34:11 AM UTC-4, L Will Ahonen wrote:

L Will Ahonen

unread,
Mar 11, 2015, 3:01:47 AM3/11/15
to jna-...@googlegroups.com
Hi,

throws LastErrorException means basically "if this function sets Kernel32.INSTANCE.GetLastError() to anything but zero, throw an exception". Apparently the default handler sets it to 2 sometimes. So your fix is easy: remove throws LastErrorException. Optionally you can try to locate the people responsible for the default handler for Java frames and make them fix their code, but that exercise is left to the reader :)

Cheers,

Will

Timothy Wall

unread,
Mar 11, 2015, 5:09:57 AM3/11/15
to jna-...@googlegroups.com
Thanks Lauri. BTW, JNA provides a 64-bit test within its Platform class (is64Bit()).

Seems odd that MyWindowProc and Pointer would have different behavior. What was your definition for MyWindowProc? There are some differences between callback memory allocation and regular memory.

> On Mar 10, 2015, at 6:33 AM, Lauri W Ahonen <lwah...@gmail.com> wrote:
>
> Hi,
>
> The export name is different on x86 and x64
>
> Pointer previousFunction;
> if (is64Bit())
> previousFunction = User32RW.INSTANCE.SetWindowLongPtr(handle, GWLP_WNDPROC, listener);
> else
> previousFunction = User32RW.INSTANCE.SetWindowLong(handle, GWLP_WNDPROC, listener);
>
> public static boolean is64Bit() {
> String model = System.getProperty("sun.arch.data.model");
> return model.equals("64");
> }
>
>
>
>
> With the signatures
> Pointer SetWindowLongPtr(HWND hWnd, int nIndex, MyWindowProc callback);
> Pointer SetWindowLong(HWND hWnd, int nIndex, MyWindowProc callback);
>
> LRESULT CallWindowProc(Pointer previousFunction, HWND hWnd, int uMsg, WPARAM wParam, LPARAM lParam);
> public static interface MyWindowProc extends StdCallCallback {
> com.sun.jna.platform.win32.WinDef.LRESULT callback(com.sun.jna.platform.win32.WinDef.HWND hwnd, int uMsg, com.sun.jna.platform.win32.WinDef.WPARAM wparam, Pointer lparam);
> }
>
>
> Also, we got the very occasional crash until we made the previous function a Pointer instead of MyWindowProc, for what it's worth.
>
> Br,
> Will
>
>
> On Monday, March 9, 2015 at 9:19:17 PM UTC-7, Wenjun Che wrote:

Wenjun Che

unread,
Mar 11, 2015, 11:04:32 PM3/11/15
to jna-...@googlegroups.com
Hi

Removing "throws LastErrorException" fixes the issue.

Thank you very much for the help
Wenjun

L Will Ahonen

unread,
Mar 12, 2015, 4:13:22 AM3/12/15
to jna-...@googlegroups.com
Hi,

Unfortunately our git history doesn't go back far enough to check what the exact definition was, and it's quite possible that the bug doesn't even exist in JNA anymore. At the time we were speculating that it stemmed from using a JNA callback pointer to memory that was not managed by JNA, but we never found the time to do anything beyond "Hmm, changing the type here seems to fix it. Shipping time!".

-Will
Reply all
Reply to author
Forward
0 new messages