我想知道如何编写一个知道哪个Windows应用程序是焦点的Java程序.我可以打开很多窗口,但我想知道正在使用的那个窗口(就像我正在键入的那样,就像谷歌Chrome一样).
我不需要在窗口或应用程序中更改任何内容,只需要知道它的名称.
ste*_*hke 32
由于其他人已经指出,所以在所有平台上都没有可移植的方法.但更糟糕的是:在MS Windows上甚至没有一致的方法.我将提供一些代码来解决不同平台的问题,并指出其局限性.使用风险自负,代码可能会提供错误的结果或由于安全原因而无法运行.如果它在您的计算机上运行,并不意味着它将在其他计算机上运行良好.
代码使用JNA.在我的实验中,我遇到了不同版本的JNA和JNA平台库的问题.最好自己编译,这样你就拥有了一致的环境.
kichik提供的答案在当时是正确的,但在所有情况下都不适用于Windows 8.问题是,它无法正确处理Metro应用程序.不幸的是,目前没有稳定的API来获取当前运行的Metro应用程序的名称.我在代码中插入了一些提示,但最好等到Microsoft为您提供API.
在Windows上,您还将遇到特权应用程序和UAC对话框的问题.所以你不会总是得到正确的答案.
public interface Psapi extends StdCallLibrary {
Psapi INSTANCE = (Psapi) Native.loadLibrary("Psapi", Psapi.class);
WinDef.DWORD GetModuleBaseNameW(Pointer hProcess, Pointer hModule, byte[] lpBaseName, int nSize);
}
if (Platform.isWindows()) {
final int PROCESS_VM_READ=0x0010;
final int PROCESS_QUERY_INFORMATION=0x0400;
final User32 user32 = User32.INSTANCE;
final Kernel32 kernel32=Kernel32.INSTANCE;
final Psapi psapi = Psapi.INSTANCE;
WinDef.HWND windowHandle=user32.GetForegroundWindow();
IntByReference pid= new IntByReference();
user32.GetWindowThreadProcessId(windowHandle, pid);
WinNT.HANDLE processHandle=kernel32.OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, true, pid.getValue());
byte[] filename = new byte[512];
Psapi.INSTANCE.GetModuleBaseNameW(processHandle.getPointer(), Pointer.NULL, filename, filename.length);
String name=new String(filename);
System.out.println(name);
if (name.endsWith("wwahost.exe")) { // Metro App
// There is no stable API to get the current Metro app
// But you can guestimate the name form the current directory of the process
// To query this, see:
// http://stackoverflow.com/questions/16110936/read-other-process-current-directory-in-c-sharp
}
Run Code Online (Sandbox Code Playgroud)
使用X11,我们有三个问题:
在X11上,查询当前具有焦点的窗口更有意义.
public interface XLib extends StdCallLibrary {
XLib INSTANCE = (XLib) Native.loadLibrary("XLib", Psapi.class);
int XGetInputFocus(X11.Display display, X11.Window focus_return, Pointer revert_to_return);
}
if(Platform.isLinux()) { // Possibly most of the Unix systems will work here too, e.g. FreeBSD
final X11 x11 = X11.INSTANCE;
final XLib xlib= XLib.INSTANCE;
X11.Display display = x11.XOpenDisplay(null);
X11.Window window=new X11.Window();
xlib.XGetInputFocus(display, window,Pointer.NULL);
X11.XTextProperty name=new X11.XTextProperty();
x11.XGetWMName(display, window, name);
System.out.println(name.toString());
}
Run Code Online (Sandbox Code Playgroud)
Mac OS X不专注于Windows,而是专注于应用程序.因此,请求当前活动的应用程序是有意义的.较早版本的Mac OS X提供多个桌面.较新的版本可以同时打开多个全屏应用程序.所以你可能并不总能得到正确的答案.
if(Platform.isMac()) {
final String script="tell application \"System Events\"\n" +
"\tname of application processes whose frontmost is tru\n" +
"end";
ScriptEngine appleScript=new ScriptEngineManager().getEngineByName("AppleScript");
String result=(String)appleScript.eval(script);
System.out.println(result);
}
Run Code Online (Sandbox Code Playgroud)
当我玩这个代码时,它在最基本的情况下工作.但是,如果您希望此代码运行可靠,则必须进行大量修改.如果值得的话,自己决定.
为了完成代码,这里是我使用的导入部分:
import com.sun.jna.Native;
import com.sun.jna.Platform;
import com.sun.jna.Pointer;
import com.sun.jna.platform.unix.X11;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.win32.StdCallLibrary;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
Run Code Online (Sandbox Code Playgroud)
当然,您必须重新排列代码的各个部分.我在一个大的主要方法中使用了一个大类,其中的接口位于开头a,然后是其余的大类.
Bal*_*a R 11
我担心没有java api.JVM对它不管理的窗口一无所知.您可能必须使用JNI并调用此函数
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
Run Code Online (Sandbox Code Playgroud)
PS.GetWindowText如果您需要获取窗口标题,则可能需要使用此功能.
这篇文章有JNI示例,可能对您有所帮助.
正如Hovercraft Full Of Eels所说,JNA是你最好的选择.与JNI不同,您不必为其编译任何C代码.
要获取进程名称:
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ)C代码可以在这里找到.
| 归档时间: |
|
| 查看次数: |
15384 次 |
| 最近记录: |