在 Java 中获取当前活动窗口的标题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1354254/
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-08-12 08:32:45  来源:igfitidea点击:

Get current active window's title in Java

javauser-interfaceactive-window

提问by

I am trying to write a Java program that logs what application I'm using every 5 seconds (this is a time tracker app). I need some way to find out what the current active window is. I found KeyboardFocusManager.getGlobalActiveWindow() but I can't get it to work right. A cross platform solution is preferable, but if one doesn't exist, then I'm developing for linux with X.Org. Thanks.

我正在尝试编写一个 Java 程序,该程序每 5 秒记录一次我正在使用的应用程序(这是一个时间跟踪器应用程序)。我需要一些方法来找出当前活动窗口是什么。我找到了 KeyboardFocusManager.getGlobalActiveWindow() 但我无法让它正常工作。跨平台解决方案是可取的,但如果不存在,那么我正在使用 X.Org 为 linux 开发。谢谢。

回答by Kevin Boyd

To find the active Window(be it a frame or a dialog) in a java swing application you can use the following recursive method:

要在 java swing 应用程序中查找活动窗口(无论是框架还是对话框),您可以使用以下递归方法:

Window getSelectedWindow(Window[] windows) {
    Window result = null;
    for (int i = 0; i < windows.length; i++) {
        Window window = windows[i];
        if (window.isActive()) {
            result = window;
        } else {
            Window[] ownedWindows = window.getOwnedWindows();
            if (ownedWindows != null) {
                result = getSelectedWindow(ownedWindows);
            }
        }
    }
    return result;
}

this is from hereMore clues on Window state here.

这是从这里的窗口状态更多的线索在这里

回答by Matthew Phillips

I'm quite certain that you'll find there's no way to enumerate the active windows in pure Java (I've looked pretty hard before), so you'll need to code for the platforms you want to target.

我很确定您会发现无法在纯 Java 中枚举活动窗口(我之前仔细研究过),因此您需要为要定位的平台编写代码。

  • On Mac OS X, you can launch an AppleScriptusing "osascript".

  • On X11, you can use xwininfo.

  • On Windows, you can probably launch some VBScript (e.g. this linklooks promising).

  • 在 Mac OS X 上,您可以使用“osascript”启动AppleScript

  • 在 X11 上,您可以使用xwininfo

  • 在 Windows 上,您可能可以启动一些 VBScript(例如这个链接看起来很有希望)。

If you're using SWT, you may be able to find some undocumented, non-public methods in the SWT libs, since SWT provides wrappers for a lot of the OS API's (e.g. SWT on Cocoa has the org.eclipse.swt.internal.cocoa.OS#objc_msgSend()methods that can be used to access the OS). The equivalent "OS" classes on Windows and X11 may have API's you can use.

如果您使用 SWT,您可能会在 SWT 库中找到一些未记录的、非公共的方法,因为 SWT 为许多 OS API 提供了包装器(例如 Cocoa 上的 SWT 具有org.eclipse.swt.internal.cocoa.OS#objc_msgSend()可用于访问的方法)操作系统)。Windows 和 X11 上的等效“OS”类可能具有您可以使用的 API。

回答by user361601

I've written a bash script that logs the current active window: http://www.whitelamp.com/public/active-window-logger.htmlIt uses a patched version of wmctrl but provides details of an alternative (slower) method using xprop and xwininfo.

我编写了一个记录当前活动窗口的 bash 脚本:http: //www.whitelamp.com/public/active-window-logger.html它使用 wmctrl 的修补版本,但提供了替代(较慢)方法的详细信息使用 xprop 和 xwininfo。

The links to the wmctrl patch & source code and the script can be found above.

wmctrl 补丁和源代码以及脚本的链接可以在上面找到。

回答by vaibhav

I have written a java program using user361601's script. I hope this will help others.

我已经使用 user361601 的脚本编写了一个 java 程序。我希望这会帮助其他人。

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class WindowAndProcessInfo4Linux {

public static final String WIN_ID_CMD = "xprop -root | grep " + "\"_NET_ACTIVE_WINDOW(WINDOW)\"" + "|cut -d ' ' -f 5";
public static final String WIN_INFO_CMD_PREFIX = "xwininfo -id ";
public static final String WIN_INFO_CMD_MID = " |awk \'BEGIN {FS=\"\\"\"}/xwininfo: Window id/{print }\' | sed \'s/-[^-]*$//g\'";

public String execShellCmd(String cmd){
    try {  

        Runtime runtime = Runtime.getRuntime();  
        Process process = runtime.exec(new String[] { "/bin/bash", "-c", cmd });  
        int exitValue = process.waitFor();  
        System.out.println("exit value: " + exitValue);  
        BufferedReader buf = new BufferedReader(new InputStreamReader(process.getInputStream()));  
        String line = "";  
        String output = "";
        while ((line = buf.readLine()) != null) {
            output = line;
        }
        return output;
    } catch (Exception e) {  
        System.out.println(e);
        return null;
    }  
}

public String windowInfoCmd(String winId){
    if(null!=winId && !"".equalsIgnoreCase(winId)){
        return WIN_INFO_CMD_PREFIX+winId +WIN_INFO_CMD_MID;
    }
    return null;
}

public static void main (String [] args){
    WindowAndProcessInfo4Linux windowAndProcessInfo4Linux = new WindowAndProcessInfo4Linux();
    try {
        Thread.sleep(4000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    String winId = windowAndProcessInfo4Linux.execShellCmd(WIN_ID_CMD);
    String winInfoMcd = windowAndProcessInfo4Linux.windowInfoCmd(winId);
    String windowTitle = windowAndProcessInfo4Linux.execShellCmd(winInfoMcd);
    System.out.println("window title is: "+ windowTitle);

}
}

// the thread.sleep is there so that you get time to switch to other window :) also, you may use quartz from spring to schedule it.

// thread.sleep 在那里,以便您有时间切换到其他窗口 :) 此外,您可以使用 spring 中的石英来安排它。

回答by Henri

I created this applescript while looking into similar topic - this one gets the specific window size

我在研究类似主题时创建了这个 applescript - 这个获取了特定的窗口大小

global theSBounds

tell application "System Events"
 set this_info to {}
 set theSBounds to {}
 repeat with theProcess in processes
  if not background only of theProcess then
   tell theProcess
    set processName to name
    set theWindows to windows
   end tell
   set windowsCount to count of theWindows
   
   if processName contains "xxxxxxxx" then
    set this_info to this_info & processName
    
   else if processName is not "Finder" then
    if windowsCount is greater than 0 then
     repeat with theWindow in theWindows
      tell theProcess
       tell theWindow
        if (value of attribute "AXTitle") contains "Genymotion for personal use -" then
         -- set this_info to this_info & (value of attribute "AXTitle")
         set the props to get the properties of the theWindow
         set theSBounds to {size, position} of props
         set this_info to this_info & theSBounds
        end if
       end tell
      end tell
     end repeat
    end if
   end if
  end if
 end repeat
end tell
return theSBounds

回答by Brian_Entei

Using SWT internals, I was able to put this together, and it seems to work nicely:

使用 SWT 内部结构,我能够将它们放在一起,并且它似乎工作得很好:

    /** @return The currently active window's title */
    public static final String getActiveWindowText() {
        long /*int*/ handle = OS.GetForegroundWindow();
        int length = OS.GetWindowTextLength(handle);
        if(length == 0) return "";
        /* Use the character encoding for the default locale */
        TCHAR buffer = new TCHAR(0, length + 1);
        OS.GetWindowText(handle, buffer, length + 1);
        return buffer.toString(0, length);
    }
public static final void main(String[] args) {
    try {
        Thread.sleep(1000L);
    } catch(InterruptedException e) {
        Thread.currentThread().interrupt();
    }
    System.out.println(getActiveWindowText());
}

Prints: user interface - Get current active window's title in Java - Stack Overflow - Google Chrome

印刷: user interface - Get current active window's title in Java - Stack Overflow - Google Chrome