How to get list of all window handles in Java (Using JNA)?

Ahamed picture Ahamed · Jan 3, 2012 · Viewed 22.9k times · Source

I am novice for JNA. I am trying to get handles for all the windows including minimised ones. I need HWND of all the windows. I have gone thro the question Windows: how to get a list of all visible windows? which helped me to get list of windows, but it has hWnd type as int. I can't use it with com.sun.jna.platform.win32.User32 functions which asks for hWnd of type com.sun.jna.platform.win32.WinDef.HWND. So, Is there any way to get all the window handles of type com.sun.jna.platform.win32.WinDef.HWND rather than int pointer? Finally, why is the difference int and HWND? How does it accept both? I am bit confused. Thanks.

I have the following code(edited from Hovercreft's answer):

    import com.sun.jna.Native;
    import com.sun.jna.Pointer;
    import com.sun.jna.platform.win32.User32;
    import com.sun.jna.platform.win32.WinDef.HWND;
    import com.sun.jna.platform.win32.WinDef.RECT;
    import com.sun.jna.platform.win32.WinUser.WNDENUMPROC;

    public class TryWithHWND {

    public static void main(String[] args) {
        final User32 user32 = User32.INSTANCE;
        user32.EnumWindows(new WNDENUMPROC() {
            int count = 0;
            public boolean callback(HWND hWnd, Pointer arg1) {
                char[] windowText = new char[512];
                user32.GetWindowText(hWnd, windowText, 512);
                String wText = Native.toString(windowText);
                RECT rectangle = new RECT();
                user32.GetWindowRect(hWnd, rectangle);
                // get rid of this if block if you want all windows regardless
                // of whether
                // or not they have text
                // second condition is for visible and non minimised windows
                if (wText.isEmpty() || !(User32.INSTANCE.IsWindowVisible(hWnd)
                        && rectangle.left > -32000)) {
                    return true;
                }
                System.out.println("Found window with text " + hWnd
                        + ", total " + ++count + " Text: " + wText);
                return true;
            }
        }, null);
    }
}

I tried to use only(not custom interface) the default User32 class. It is working fine. I have doubt, why we are using userdefined interface instead of already existing one? One more thing, There is always difference between userdefined method signature and already existing ones. For instance, the variable windowText is char[], whereas Hovercraft's variable is of type byte[]. Can anyone explain me? Thanks.

Answer

Hovercraft Full Of Eels picture Hovercraft Full Of Eels · Jan 3, 2012

The latest version of JNA has had some changes that should fix this (as one of the authors of JNA, Luke Quinane, states here). If you use the latest version and check the JNA API, you'll see that the WinUser.WNDENUMPROC interface's method actually uses WinDef.HWND as its parameter, not long or int.

For example:

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinUser;
import com.sun.jna.platform.win32.WinUser.WNDENUMPROC;
import com.sun.jna.win32.StdCallLibrary;

public class TryWithHWND {
   public interface User32 extends StdCallLibrary {
      User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class);
      boolean EnumWindows(WinUser.WNDENUMPROC lpEnumFunc, Pointer arg);
      int GetWindowTextA(HWND hWnd, byte[] lpString, int nMaxCount);
   }

   public static void main(String[] args) {
      final User32 user32 = User32.INSTANCE;
      user32.EnumWindows(new WNDENUMPROC() {
         int count = 0;
         @Override
         public boolean callback(HWND hWnd, Pointer arg1) {
            byte[] windowText = new byte[512];
            user32.GetWindowTextA(hWnd, windowText, 512);
            String wText = Native.toString(windowText);

            // get rid of this if block if you want all windows regardless of whether
            // or not they have text
            if (wText.isEmpty()) {
               return true;
            }

            System.out.println("Found window with text " + hWnd + ", total " + ++count
                  + " Text: " + wText);
            return true;
         }
      }, null);
   }
}