Java JNA focus a specific Window

2020-03-06 10:15发布

问题:

I am trying to give my application the power to focus another Window (Notepad in this case)

My Class is looking like this

 public static class Win32WindowUtils {

  public interface User32 extends StdCallLibrary {
        User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class, W32APIOptions.DEFAULT_OPTIONS);
        HWND GetParent(HWND hWnd);
        HWND FindWindow(String lpClassName, String lpWindowName);
        HWND SetFocus(HWND hWnd);
        HWND FindWindowEx(HWND hwndParent, HWND hwndChildAfter, String lpszClass, String lpszWindow);
        int GetWindowText(HWND hWnd, char[] lpString, int nMaxCount);
    }

    private static final int WIN_TITLE_MAX_SIZE = 512;

    public static HWND GetWindowHandle(String strSearch, String strClass) {
        char[] lpString = new char[WIN_TITLE_MAX_SIZE];
        String strTitle;
        int iFind = -1;
        HWND hWnd = User32.INSTANCE.FindWindow(strClass, null);
        while(hWnd != null) {
            User32.INSTANCE.GetWindowText(hWnd, lpString, WIN_TITLE_MAX_SIZE);
            strTitle = new String(lpString);
            strTitle = strTitle.toUpperCase();
            iFind = strTitle.indexOf(strSearch);
            if(iFind != -1) {
                return hWnd;
            }
            hWnd = (User32.INSTANCE).FindWindowEx(null, hWnd, strClass, null);
        }
        return hWnd;
    }
}

And I am calling it by using:

User32.INSTANCE.SetFocus(Win32WindowUtils.GetWindowHandle(windowTitle, null));

Note:

public String windowTitle = "Unbennant - Editor";

Sadly nothing is happening and I dont know why

回答1:

The below code snippet iterates through all the windows open in the machine , stops when a Notepad++ window with a specific title is found and then brings it into focus.On bringing it to focus it presses the enter key three times.

import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.KeyEvent;

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinDef;
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);

    WinDef.HWND SetFocus(WinDef.HWND hWnd);

    int GetWindowTextA(HWND hWnd, byte[] lpString, int nMaxCount);

    boolean SetForegroundWindow(WinDef.HWND hWnd);
}

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) {
            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);
            if (wText
                    .equals("C:\\Users\\Avi.J\\Desktop\\Datasource and Mq setup commands.txt - Notepad++")) {
                user32.SetForegroundWindow(hWnd);
                return false;
            }
            return true;
        }
    }, null);
    // user32.SetFocus(hWnd);
    try {
        Robot r = new Robot();
        r.keyPress(KeyEvent.VK_ENTER);
        r.keyRelease(KeyEvent.VK_ENTER);
        r.keyPress(KeyEvent.VK_ENTER);
        r.keyRelease(KeyEvent.VK_ENTER);
        r.keyPress(KeyEvent.VK_ENTER);
        r.keyRelease(KeyEvent.VK_ENTER);
        r.keyPress(KeyEvent.VK_ENTER);
        r.keyRelease(KeyEvent.VK_ENTER);
    } catch (AWTException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
}

Hope this helps , I believe the part of sending keystrokes can be done by User32 library as well.



回答2:

I know im like 3 years late, but because of the limitation of the windows api when trying to make modifications at other programs with a different origin than yours, the current answers doesn't work at least with JNA. I've done some hours of research trying lots of different functions without success. Finally I've found the way to do it really clean. Using Avinash Jha code base here is the way to do it:

public class JnaInstances {

    public interface User32 extends StdCallLibrary {
        User32 INSTANCE = Native.loadLibrary("user32", User32.class);

        boolean EnumWindows(WinUser.WNDENUMPROC lpEnumFunc,
                            Pointer data);

        int GetWindowTextW(WinDef.HWND hWnd, char[] lpString, int nMaxCount);

        boolean ShowWindow(WinDef.HWND hWnd, int nCmdShow);

    }

}

public static void main(String[] args) {
    JnaInstances.User32 user32 = JnaInstances.User32.INSTANCE;

    user32.EnumWindows(new WinUser.WNDENUMPROC() {

        @Override
        public boolean callback(WinDef.HWND hwnd, Pointer pointer) {
            char[] windowText = new char[512];
            user32.GetWindowTextW(hwnd, windowText, 512);

            String windowName = Native.toString(windowText);

            System.out.println("The window is called: "+ windowName);

            if(windowName.contains("Window name")) { //Here you can use the .equals if you want more accurancy

                user32.ShowWindow(hwnd, User32.SW_RESTORE);
                return false;
            }

            return true;
        }

    }, null);
}


回答3:

It should probably read

public String windowTitle = "Unbenannt - Editor";


回答4:

Answer by Avinash Jha is good. Just add following two lines after user32.SetForegroundWindow(hWnd);, you will not need to add robot keys VK_ENTER to activate window, as clicking enter will cause clicking default key of window (e.g. button OK, Run)

...
user32.SetForegroundWindow(hWnd);

user32.SetFocus( winOne.winHandle);
Thread.sleep(500);
user32.ShowWindow(winOne.winHandle, WinUser.SW_SHOWNOACTIVATE);

return false;
...