我知道可以使用Robot Class在
java中发送击键,但有没有办法在目标进程已经启动时指定它?
解决方法
机器人会将击键发送到顶部的任何应用程序窗口.要将击键发送到特定目标,您需要首先将目标设置为平台的前景窗口.这样做可能需要本机代码,例如JNI或(我使用的)JNA提供的代码.如果您希望将键击发送到后台窗口,我相信您不能使用Robot,您必须编写本机代码.当然,所有本机代码解决方案都将取决于平台.
你问:
Would you please give me some more details on how to do it with JNA
sorry,I’m writing for windows
对于Windows,您将与user32.dll库进行交互.像这样的东西对我有用:
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 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,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,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 w,int h) { int uFlags = 0; return user32.SetWindowPos(hWnd,User32.HWND_TOP,x,w,h,uFlags); } public static boolean moveWindow(Pointer hWnd,int nHeight) { boolean bRepaint = true; return user32.MoveWindow(hWnd,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,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); } }