我正在尝试编写一个 Java 程序,该程序每 5 秒记录一次我正在使用的应用程序(这是一个时间跟踪器应用程序)。我需要一些方法来找出当前的活动窗口是什么。我找到了 KeyboardFocusManager.getGlobalActiveWindow() 但我无法让它正常工作。最好使用跨平台解决方案,但如果不存在,那么我正在使用 X.Org 为 linux 开发。谢谢。
6 回答
我很确定你会发现没有办法在纯 Java 中枚举活动窗口(我以前看过很辛苦),所以你需要为你想要定位的平台编写代码。
在 Mac OS X 上,您可以使用“osascript”启动AppleScript 。
在 X11 上,您可以使用xwininfo。
在 Windows 上,您可能可以启动一些 VBScript(例如这个链接看起来很有希望)。
如果您使用 SWT,您可能会在 SWT 库中找到一些未记录的、非公共的方法,因为 SWT 为许多 OS API 提供了包装器(例如,Cocoa 上的 SWT 具有org.eclipse.swt.internal.cocoa.OS#objc_msgSend()
可用于访问的方法操作系统)。Windows 和 X11 上的等效“OS”类可能具有您可以使用的 API。
我使用 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 $2}\' | 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);
}
}
// thread.sleep 在那里,以便您有时间切换到其他窗口:) 此外,您可以使用 spring 中的石英来安排它。
要在 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;
}
这是从这里更多关于窗口状态的 线索。
我编写了一个记录当前活动窗口的 bash 脚本:http: //www.whitelamp.com/public/active-window-logger.html 它使用了 wmctrl 的修补版本,但提供了替代(较慢)方法的详细信息使用 xprop 和 xwininfo。
wmctrl 补丁和源代码和脚本的链接可以在上面找到。
使用 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());
}
印刷:user interface - Get current active window's title in Java - Stack Overflow - Google Chrome
我在研究类似主题时创建了这个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