java sending keystrokes using robot class

前端 未结 1 1405
-上瘾入骨i
-上瘾入骨i 2021-02-06 11:25

I know it\'s possible to send keystrokes in java using Robot Class , but is there any way to specify the target process when it\'s already started ?

相关标签:
1条回答
  • 2021-02-06 12:26

    The Robot will send the keystrokes to whichever application window is on top. To send keystrokes to a specific target, you will want to set the target as the platform's foreground window first. Doing this may require native code such as that provided by JNI or (what I use) JNA. If you desire to send keystrokes to a background window, I believe that you cannot use Robot, that you will have to write native code. Of course all native code solutions will be platform dependent.


    You ask:

    Would you please give me some more details on how to do it with JNA
    sorry , I'm writing for windows

    For Windows, you would interface with the user32.dll library. Something like this has worked for me:

    User32.java

    import com.sun.jna.Native;
    import com.sun.jna.Pointer;
    import com.sun.jna.platform.win32.BaseTSD.LONG_PTR;
    import com.sun.jna.platform.win32.WinDef.HWND;
    import com.sun.jna.platform.win32.WinDef.RECT;
    import com.sun.jna.win32.StdCallLibrary;
    
    /**
     * JNA interface with Window's user32.dll
     * 
     * @author Pete S
     * 
     */
    public interface User32 extends StdCallLibrary {
       User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class);
    
       interface WNDENUMPROC extends StdCallCallback {
          boolean callback(Pointer hWnd, Pointer arg);
       }
    
       public static final int GW_OWNER = 4; // used with GetWindow to get win owner
       public static final int GW_HWNDNEXT = 2; // used with GetNextWindow
       public static final int GA_ROOT = 2; // used with GetAncestor
       public static final int GWL_EXSTYLE = -20; // used with GetWindowLong
       public static final long WS_EX_APPWINDOW = 0x00040000L;
       public static final Pointer HWND_TOP = new Pointer(0L); // used with
                                                               // SetWindowPos
    
       boolean EnumWindows(WNDENUMPROC lpEnumFunc, Pointer userData);
    
       int GetWindowTextA(Pointer hWnd, byte[] lpString, int nMaxCount);
    
       int SetForegroundWindow(Pointer hWnd);
    
       Pointer GetForegroundWindow();
    
       boolean GetWindowRect(Pointer hWnd, RECT rect);
    
       boolean SetWindowPos(Pointer hWnd, Pointer hWndInsertAfter, int x, int y,
             int cx, int cy, int uFlags);
    
       boolean MoveWindow(Pointer hWnd, int x, int y, int nWidth, int nHeight, boolean bRepaint);
    
       boolean IsWindow(Pointer hWnd);
    
       Pointer GetWindow(Pointer hWnd, int uCmd);
    
       LONG_PTR GetWindowLongPtr(HWND hWnd, int nIndex);
    
       Pointer GetParent(Pointer hWnd);
    
       Pointer GetAncestor(Pointer hWnd, int gaFlags);
    
       boolean IsWindowVisible(Pointer hWnd);
    }
    

    JnaUtil.java

    import java.awt.AWTException;
    import java.awt.Rectangle;
    import java.awt.Robot;
    import java.awt.image.BufferedImage;
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.swing.ImageIcon;
    import javax.swing.JLabel;
    import javax.swing.JOptionPane;
    import javax.swing.SwingUtilities;
    
    import com.sun.jna.Native;
    import com.sun.jna.Pointer;
    import com.sun.jna.platform.win32.BaseTSD.LONG_PTR;
    import com.sun.jna.platform.win32.WinDef.HWND;
    import com.sun.jna.platform.win32.WinDef.RECT;
    
    /**
     * static methods to allow Java to call Windows code. user32.dll code is as
     * specified in the JNA interface User32.java
     * 
     * @author Pete S
     * 
     */
    public class JnaUtil {
       private static final User32 user32 = User32.INSTANCE;
       private static Pointer callBackHwnd;
    
       public static boolean windowExists(final String startOfWindowName) {
          return !user32.EnumWindows(new User32.WNDENUMPROC() {
             @Override
             public boolean callback(Pointer hWnd, Pointer userData) {
                byte[] windowText = new byte[512];
                user32.GetWindowTextA(hWnd, windowText, 512);
                String wText = Native.toString(windowText).trim();
    
                if (!wText.isEmpty() && wText.startsWith(startOfWindowName)) {
                   return false;
                }
                return true;
             }
          }, null);
       }
    
       public static List<String> getAllWindowNames() {
          final List<String> windowNames = new ArrayList<String>();
          user32.EnumWindows(new User32.WNDENUMPROC() {
    
             @Override
             public boolean callback(Pointer hWnd, Pointer arg) {
                byte[] windowText = new byte[512];
                user32.GetWindowTextA(hWnd, windowText, 512);
                String wText = Native.toString(windowText).trim();
                if (!wText.isEmpty()) {
                   windowNames.add(wText);
                }
                return true;
             }
          }, null);
    
          return windowNames;
       }
    
       public static boolean windowExists(Pointer hWnd) {
          return user32.IsWindow(hWnd);
       }
    
       public static Pointer getWinHwnd(final String startOfWindowName) {
          callBackHwnd = null;
    
          user32.EnumWindows(new User32.WNDENUMPROC() {
             @Override
             public boolean callback(Pointer hWnd, Pointer userData) {
                byte[] windowText = new byte[512];
                user32.GetWindowTextA(hWnd, windowText, 512);
                String wText = Native.toString(windowText).trim();
    
                if (!wText.isEmpty() && wText.startsWith(startOfWindowName)) {
                   callBackHwnd = hWnd;
                   return false;
                }
                return true;
             }
          }, null);
          return callBackHwnd;
       }
    
       public static boolean setForegroundWindow(Pointer hWnd) {
          return user32.SetForegroundWindow(hWnd) != 0;
       }
    
       public static Pointer getForegroundWindow() {
          return user32.GetForegroundWindow();
       }
    
       public static String getForegroundWindowText() {
          Pointer hWnd = getForegroundWindow();
          int nMaxCount = 512;
          byte[] lpString = new byte[nMaxCount];
          int getWindowTextResult = user32
                .GetWindowTextA(hWnd, lpString, nMaxCount);
          if (getWindowTextResult == 0) {
             return "";
          }
    
          return Native.toString(lpString);
       }
    
       public static boolean isForegroundWindow(Pointer hWnd) {
          return user32.GetForegroundWindow().equals(hWnd);
       }
    
       public static boolean setForegroundWindow(String startOfWindowName) {
          Pointer hWnd = getWinHwnd(startOfWindowName);
          return user32.SetForegroundWindow(hWnd) != 0;
       }
    
       public static Rectangle getWindowRect(Pointer hWnd) throws JnaUtilException {
          if (hWnd == null) {
             throw new JnaUtilException(
                   "Failed to getWindowRect since Pointer hWnd is null");
          }
          Rectangle result = null;
          RECT rect = new RECT();
          boolean rectOK = user32.GetWindowRect(hWnd, rect);
          if (rectOK) {
             int x = rect.left;
             int y = rect.top;
             int width = rect.right - rect.left;
             int height = rect.bottom - rect.top;
             result = new Rectangle(x, y, width, height);
          }
    
          return result;
       }
    
       /**
        * set window at x and y position with w and h width. Set on top of z-order
        * 
        * @param hWnd
        * @param x
        * @param y
        * @param w
        * @param h
        * @return boolean -- did it work?
        */
       public static boolean setWindowPos(Pointer hWnd, int x, int y, int w, int h) {
          int uFlags = 0;
          return user32.SetWindowPos(hWnd, User32.HWND_TOP, x, y, w, h, uFlags);
       }
    
       public static boolean moveWindow(Pointer hWnd, int x, int y, int nWidth,
             int nHeight) {
          boolean bRepaint = true;
          return user32.MoveWindow(hWnd, x, y, nWidth, nHeight, bRepaint );
       }
    
       public static Rectangle getWindowRect(String startOfWindowName)
             throws JnaUtilException {
          Pointer hWnd = getWinHwnd(startOfWindowName);
          if (hWnd != null) {
             return getWindowRect(hWnd);
          } else {
             throw new JnaUtilException("Failed to getWindowRect for \""
                   + startOfWindowName + "\"");
          }
       }
    
       public static Pointer getWindow(Pointer hWnd, int uCmd) {
          return user32.GetWindow(hWnd, uCmd);
       }
    
       public static String getWindowText(Pointer hWnd) {
          int nMaxCount = 512;
          byte[] lpString = new byte[nMaxCount];
          int result = user32.GetWindowTextA(hWnd, lpString, nMaxCount);
          if (result == 0) {
             return "";
          }
          return Native.toString(lpString);
       }
    
       public static Pointer getOwnerWindow(Pointer hWnd) {
          return user32.GetWindow(hWnd, User32.GW_OWNER);
       }
    
       public static String getOwnerWindow(String childTitle) {
          Pointer hWnd = getWinHwnd(childTitle);
          Pointer parentHWnd = getOwnerWindow(hWnd);
          if (parentHWnd == null) {
             return "";
          }
          return getWindowText(parentHWnd);
    
       }
    
       public static Pointer getNextWindow(Pointer hWnd) {
          if (hWnd == null) {
             return null;
          }
    
          return user32.GetWindow(hWnd, User32.GW_HWNDNEXT);
       }
    
       public static boolean isWindowVisible(Pointer hWnd) {
          return user32.IsWindowVisible(hWnd);
       }
    
       public static Pointer getParent(Pointer hWnd) {
          return user32.GetParent(hWnd);
       }
    
       public static Pointer getRoot(Pointer hWnd) {
          return user32.GetAncestor(hWnd, User32.GA_ROOT);
       }
    
       public static LONG_PTR getWindowLongPtr(Pointer hWndP, int nIndex) {
          HWND hwnd = new HWND(hWndP);
          return user32.GetWindowLongPtr(hwnd, nIndex);
       }
    
       // main method to test the library
       public static void main(String[] args) throws InterruptedException {
          List<String> winNameList = getAllWindowNames();
          for (String winName : winNameList) {
             System.out.println(winName);
          }
    
          String[] testStrs = { "Untitled-Notepad", "Untitled - Notepad",
                "Untitled  -  Notepad", "Java-Epic", "Java - Epic", "Fubars rule!",
                "The First Night", "New Tab", "Citrix X", "EHR PROD - SVC" };
          for (String testStr : testStrs) {
             Pointer hWnd = getWinHwnd(testStr);
             boolean isWindow = windowExists(hWnd);
             System.out.printf("%-22s %5b %16s %b%n", testStr,
                   windowExists(testStr), hWnd, isWindow);
          }
    
          String notePad = "Untitled - Notepad";
          Pointer hWnd = getWinHwnd(notePad);
          System.out
                .println("is it foreground window? " + isForegroundWindow(hWnd));
          boolean foo = setForegroundWindow(notePad);
          System.out.println("foregroundwindow: " + foo);
          Thread.sleep(400);
          System.out
                .println("is it foreground window? " + isForegroundWindow(hWnd));
          Thread.sleep(1000);
          System.out.println("here A");
          try {
             Rectangle rect = getWindowRect(notePad);
             System.out.println("rect: " + rect);
             Robot robot = new Robot();
             System.out.println("here B");
    
             BufferedImage img = robot.createScreenCapture(rect);
             System.out.println("here C, img is " + img);
             Thread.sleep(500);
             ImageIcon icon = new ImageIcon(img);
             System.out.println("here D. icon is null? " + icon);
             Thread.sleep(500);
             final JLabel label = new JLabel(icon);
             System.out.println("here E. label is null? " + label);
             Thread.sleep(500);
             SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                   System.out.println("here F");               
                   JOptionPane.showMessageDialog(null, label);
                   System.out.println("here G");
                }
             });
    
          } catch (AWTException e) {
             e.printStackTrace();
          } catch (JnaUtilException e) {
             e.printStackTrace();
          }
       }
    
    }
    

    JnaUtilException.java

    public class JnaUtilException extends Exception {
       private static final long serialVersionUID = 1L;
    
       public JnaUtilException(String text) {
          super(text);
       }
    
    }
    
    0 讨论(0)
提交回复
热议问题