如何在 Java 中获取程序窗口的 x 和 y?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6091531/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 14:17:12  来源:igfitidea点击:

How to get the x and y of a program window in Java?

javaruntimecoordinatesjnaawtrobot

提问by Pedro Cimini

Is there a way for me to get the X and Y values of a window in java? I read that I'll have to use runtime, since java can't mess directly, however I am not so sure of how to do this. Can anyone point me some links/tips on how to get this?

有没有办法让我在 Java 中获取窗口的 X 和 Y 值?我读到我必须使用运行时,因为 java 不能直接混乱,但是我不太确定如何做到这一点。任何人都可以给我一些关于如何获得这个的链接/提示吗?

回答by Hovercraft Full Of Eels

To get the x and y position of "any other unrelated application" you're going to have to query the OS and that means likely using either JNI, JNA or some other scripting utility such as AutoIt (if Windows). I recommend either JNA or the scripting utility since both are much easier to use than JNI (in my limited experience), but to use them you'll need to download some code and integrate it with your Java application.

要获得“任何其他不相关的应用程序”的 x 和 y 位置,您将不得不查询操作系统,这意味着可能使用 JNI、JNA 或其他一些脚本实用程序,例如 AutoIt(如果是 Windows)。我推荐 JNA 或脚本实用程序,因为两者都比 JNI 更容易使用(以我有限的经验),但要使用它们,您需要下载一些代码并将其与您的 Java 应用程序集成。

EDIT 1I'm no JNA expert, but I do fiddle around with it some, and this is what I got to get the window coordinates for some named window:

编辑 1我不是 JNA 专家,但我确实摆弄了一些,这就是我获得某些命名窗口的窗口坐标的原因:

import java.util.Arrays;
import com.sun.jna.*;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.win32.*;

public class GetWindowRect {

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

      HWND FindWindow(String lpClassName, String lpWindowName);

      int GetWindowRect(HWND handle, int[] rect);
   }

   public static int[] getRect(String windowName) throws WindowNotFoundException,
            GetWindowRectException {
      HWND hwnd = User32.INSTANCE.FindWindow(null, windowName);
      if (hwnd == null) {
         throw new WindowNotFoundException("", windowName);
      }

      int[] rect = {0, 0, 0, 0};
      int result = User32.INSTANCE.GetWindowRect(hwnd, rect);
      if (result == 0) {
         throw new GetWindowRectException(windowName);
      }
      return rect;
   }

   @SuppressWarnings("serial")
   public static class WindowNotFoundException extends Exception {
      public WindowNotFoundException(String className, String windowName) {
         super(String.format("Window null for className: %s; windowName: %s", 
                  className, windowName));
      }
   }

   @SuppressWarnings("serial")
   public static class GetWindowRectException extends Exception {
      public GetWindowRectException(String windowName) {
         super("Window Rect not found for " + windowName);
      }
   }

   public static void main(String[] args) {
      String windowName = "Document - WordPad";
      int[] rect;
      try {
         rect = GetWindowRect.getRect(windowName);
         System.out.printf("The corner locations for the window \"%s\" are %s", 
                  windowName, Arrays.toString(rect));
      } catch (GetWindowRect.WindowNotFoundException e) {
         e.printStackTrace();
      } catch (GetWindowRect.GetWindowRectException e) {
         e.printStackTrace();
      }      
   }
}

Of course for this to work, the JNA libraries would need to be downloaded and placed on the Java classpath or in your IDE's build path.

当然,要使其正常工作,需要下载 JNA 库并将其放置在 Java 类路径或 IDE 的构建路径中。

回答by Andrew Thompson

This is easy to do with the help of the end user. Just get them to click on a point in a screen shot.

这在最终用户的帮助下很容易做到。只需让他们单击屏幕截图中的一个点即可。

E.G.

例如

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;

/** Getting a point of interest on the screen.
Requires the MotivatedEndUser API - sold separately. */
class GetScreenPoint {

    public static void main(String[] args) throws Exception {
        Robot robot = new Robot();
        final Dimension screenSize = Toolkit.getDefaultToolkit().
            getScreenSize();
        final BufferedImage screen = robot.createScreenCapture(
            new Rectangle(screenSize));

        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JLabel screenLabel = new JLabel(new ImageIcon(screen));
                JScrollPane screenScroll = new JScrollPane(screenLabel);
                screenScroll.setPreferredSize(new Dimension(
                    (int)(screenSize.getWidth()/2),
                    (int)(screenSize.getHeight()/2)));

                final Point pointOfInterest = new Point();

                JPanel panel = new JPanel(new BorderLayout());
                panel.add(screenScroll, BorderLayout.CENTER);

                final JLabel pointLabel = new JLabel(
                    "Click on any point in the screen shot!");
                panel.add(pointLabel, BorderLayout.SOUTH);

                screenLabel.addMouseListener(new MouseAdapter() {
                    public void mouseClicked(MouseEvent me) {
                        pointOfInterest.setLocation(me.getPoint());
                        pointLabel.setText(
                            "Point: " +
                            pointOfInterest.getX() +
                            "x" +
                            pointOfInterest.getY());
                    }
                });

                JOptionPane.showMessageDialog(null, panel);

                System.out.println("Point of interest: " + pointOfInterest);
            }
        });
    }
}

Typical output

典型输出

Point of interest: java.awt.Point[x=342,y=43]
Press any key to continue . . .

回答by GurpusMaximus

A little late to the party here but will add this to potentially save others a little time. If you are using a more recent version of JNA then WindowUtils.getAllWindows()will make this much easier to accomplish.

这里的聚会有点晚了,但会添加这个以潜在地为其他人节省一点时间。如果您使用的是更新版本的 JNA,那么WindowUtils.getAllWindows()这将更容易实现。

I am using the most recent stable versions as of this post from the following maven locations:

我正在使用来自以下 Maven 位置的最新稳定版本:

JNA Platform - net.java.dev.jna:jna-platform:5.2.0

JNA 平台 - net.java.dev.jna:jna-platform:5.2.0

JNA Core - net.java.dev.jna:jna:5.2.0

JNA 核心 - net.java.dev.jna:jna:5.2.0

Java 8 Lambda(Edit: rect is a placeholder and will need to be final or effectively final to work in a lambda)

Java 8 Lambda(编辑:rect 是一个占位符,需要是最终的或有效的最终才能在 lambda 中工作)

//Find IntelliJ IDEA Window
//import java.awt.Rectangle;
final Rectangle rect = new Rectangle(0, 0, 0, 0); //needs to be final or effectively final for lambda
WindowUtils.getAllWindows(true).forEach(desktopWindow -> {
    if (desktopWindow.getTitle().contains("IDEA")) {
        rect.setRect(desktopWindow.getLocAndSize());
    }
});

Other Java

其他 Java

//Find IntelliJ IDEA Window
Rectangle rect = null;
for (DesktopWindow desktopWindow : WindowUtils.getAllWindows(true)) {
    if (desktopWindow.getTitle().contains("IDEA")) {
         rect = desktopWindow.getLocAndSize();
    }
}

Then within a JPanel you can draw a captured image to fit (Will stretch image if different aspect ratios).

然后在 JPanel 中,您可以绘制捕获的图像以适合(如果纵横比不同,将拉伸图像)。

//import java.awt.Robot;
g2d.drawImage(new Robot().createScreenCapture(rect), 0, 0, getWidth(), getHeight(), this);