![](/img/trans.png)
[英]How to use Java timezone id in a Windows (non-Java) application?
[英]Get titles of Non-Java Windows in Java
Window.getWindows();
沒有得到所有開放的 windows,只有 java。 有沒有辦法獲取操作系統已打開的所有windows。 我正在制作一個 java 任務欄。
沒有使用核心 Java 的解決方案,但可以使用 JNI 或更簡單的 JNA 來解決問題。 如評論中所述,沒有任何解決方案(據我所知)是獨立於平台的。
例如,這個演示程序使用 JNA 枚舉 Windows 平台中所有帶有標題的窗口,但也會包括非頂級窗口甚至不可見的窗口:
import java.util.ArrayList;
import java.util.List;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.win32.StdCallLibrary;
public class EnumAllWindowNames {
static interface User32 extends StdCallLibrary {
User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class);
interface WNDENUMPROC extends StdCallCallback {
boolean callback(Pointer hWnd, Pointer arg);
}
boolean EnumWindows(WNDENUMPROC lpEnumFunc, Pointer userData);
int GetWindowTextA(Pointer hWnd, byte[] lpString, int nMaxCount);
Pointer GetWindow(Pointer hWnd, int uCmd);
}
public static List<String> getAllWindowNames() {
final List<String> windowNames = new ArrayList<String>();
final User32 user32 = User32.INSTANCE;
user32 .EnumWindows(new User32.WNDENUMPROC() {
@Override
public boolean callback(Pointer hWnd, Pointer arg) {
byte[] windowText = new byte[512];
user32.GetWindowTextA(hWnd, windowText, 512);
String wText = Native.toString(windowText).trim();
if (!wText.isEmpty()) {
windowNames.add(wText);
}
return true;
}
}, null);
return windowNames;
}
public static void main(String[] args) {
List<String> winNameList = getAllWindowNames();
for (String winName : winNameList) {
System.out.println(winName);
}
}
}
除了@Hovercraft Full Of Eels ,如果您還有標題為不可讀字符的窗口並得到“?” 為這些字符打印,嘗試:
見下文:
String wText = Native.toString(windowText, "windows-1254").trim();
可能的編碼而不是“windows-1254(這對土耳其字符很有效)”:
您現在可以調用本機 Windows API,使用 Foreign Memory API 和由兼容的jextract生成的代碼綁定,通過純 Java 代碼讀取非 Java windows 的標題。
此示例適用於 JDK19 版本中的預覽代碼,相當於 Hovercraft Full Of Eels 答案:
/**
* Run with Windows JDK19 and preview enabled:
* jdk-19\bin\java --enable-native-access=ALL-UNNAMED --enable-preview -cp your.jar EnumWindowsDemo
*/
public class EnumWindowsDemo {
// Wide to Java String
private static String toJavaString(MemorySegment wide, int len) {
final CharBuffer cb = wide.asByteBuffer().order(ByteOrder.nativeOrder()).asCharBuffer();
return cb.limit(len).toString();
}
public static void main(String[] args) {
// TODO: You could use someParam to detect specific hWnd inside the callback
long someParam = 0x1234;
final int isRunning = User32_h.TRUE();
final int maxChars = 1024;
System.out.format("EnumWindows Panama 19 Demo Java %s%n", System.getProperty("java.runtime.version"));
HashMap<Long,String> windowNames = new HashMap<>();
try(MemorySession arena = MemorySession.openConfined()) {
// JDK20 try(Arena arena = Arena.openConfined()) {
MemorySegment lpString = arena.allocateArray(JAVA_CHAR, maxChars);
// Windows callback WNDENUMPROC(MemorySegment hwnd, long lParam)
WNDENUMPROC callback = (hWnd, lParam) -> {
int used = User32_h.GetWindowTextW(hWnd, lpString, maxChars);
if (used > 0) {
String text = toJavaString(lpString, used);
System.out.format("hWnd:%x lParam:%x => `%s`%n", hWnd.toRawLongValue(), lParam, text);
// JDK20: System.out.format("hWnd:%x lParam:%x => `%s`%n", hWnd.address(), lParam, text);
if (used >= maxChars) {
System.out.format("*** Oops: increase maxChars > %d, or call GetWindowTextLength first ***%n", used);
}
windowNames.put(hWnd.toRawLongValue(), text);
// JDK20: windowNames.put(hWnd.address(), text);
}
return isRunning;
};
final MemorySegment ewProc = WNDENUMPROC.allocate(callback, arena);
// JDK20: final MemorySegment ewProc = WNDENUMPROC.allocate(callback, arena.scope());
// Note that someParam is passed to the callback as lParam value
int rc = User32_h.EnumWindows(ewProc, someParam);
System.out.format("EnumWindows rc:%s%n", rc == 0 ? "FAIL":"OK");
if (rc == 0) {
throw new RuntimeException("EnumWindows failed rc="+rc);
}
}
System.out.format("Found windowNames: %s%n", windowNames.toString());
}
}
獨立的 jextract 用於生成調用本機代碼的綁定。 您需要創建一個 header User32.h
引用合適的 Windows API 標頭:
echo #include ^<shlobj_core.h^> > User32.h
運行 jextract 為一組合適的 Windows API 生成綁定:
set JEXTRACT_ARGS=--source -luser32 User32.h -t somepackage --output java
set JEXTRACT_SYMBOLS=--include-macro TRUE --include-function EnumWindows --include-function GetWindowTextW --include-function GetWindowTextLengthW --include-typedef WNDENUMPROC
jextract %JEXTRACT_ARGS% %JEXTRACT_SYMBOLS%
您還可以將符號保存到文件中以便於編輯,並通過將上%JEXTRACT_SYMBOLS%
的使用替換為@your.symbols
來重新生成。
也可以看看:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.