- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
(一定要使用相关技术重新标记:我不知道它们是哪些:)
稍后我可能会提出更详细的问题,关于具体细节,但现在我正试图掌握“大局”:我正在寻找一种方法来枚举 Windows 上的“真实可见窗口”。我所说的“真正可见的窗口”就是指:用户称之为“窗口”的东西。我需要一种方法来按 Z 顺序获取所有这些可见窗口的列表。
请注意,我确实确实需要这样做。我已经在 OS X 上完成了(这真的很令人头疼,特别是如果你想支持 OS X 10.4,因为 OS X 没有方便的 Windows API),现在我需要在 Windows 下完成。
这是一个例子,假设屏幕上有三个可见窗口,像这样:
+------------------------------------------+
| |
| +=============+ |
| | | |
| | A +--------------------------+
| | | |
| C | | B |
| | +--------------------------+
| | | |
+-----------| |----------------+
| |
+-------------+
然后我需要取回这样的列表:
windows B is at (210,40)
windows A is at (120,20)
windows C is at (0,0)
那么如果用户(或操作系统)将窗口 A 带到前面,它变成:
+------------------------------------------+
| |
| +=============+ |
| | | |
| | A |---------------------+
| | | |
| C | | B |
| | |---------------------+
| | | |
+-----------| |----------------+
| |
+-------------+
我得到(理想情况下)一个回调给我这个:
windows A is at (120,20)
windows B is at (210,40)
windows C is at (0,0)
在 OS X 下执行此操作需要使用非常奇怪的 hack(例如强制用户打开 “为辅助设备启用访问权限”!)但我已经在 OS X 下完成了它工作(在 OS X 下,每次发生一些窗口更改时我都没有设法得到回调,所以我正在轮询,但我让它工作)。
现在我想在 Windows 下执行此操作(我确实这样做,对此毫无疑问),我有几个问题:
这可以做到吗?
是否有详细记录的 Windows API(并按照其规范工作)允许这样做?
每次窗口更改时注册回调是否容易? (如果它被调整大小、移动、移到后面/前面或弹出一个新窗口等)
问题是什么?
我知道这个问题并不具体,这就是为什么我试图尽可能清楚地描述我的问题(包括你可以投票赞成的漂亮的 ASCII 艺术):现在我正在查看“大图”。我想知道在Windows下做这样的事情涉及到什么。
额外问题:假设您需要编写一个小的 .exe 将窗口名称/位置/大小写入临时文件,每次屏幕上出现窗口变化时,这样的程序需要多长时间大致使用您选择的语言,您需要写多长时间?
(再一次,我试图从“大局”了解这里的工作原理)
最佳答案
要枚举顶级窗口,您应该使用 EnumWindows而不是 GetTopWindow/GetNextWindow,因为 EnumWindows 返回窗口状态的一致 View 。当窗口在迭代期间更改 z 顺序时,您可能会使用 GetTopWindow/GetNextWindow 获得不一致的信息(例如报告已删除窗口)或无限循环。
EnumWindows 使用回调。在每次调用回调时,您都会获得一个窗口句柄。可以通过将句柄传递给 GetWindowRect 来获取窗口的屏幕坐标。 .您的回调以 z 顺序构建窗口位置列表。
您可以使用轮询,并重复构建窗口列表。或者,您设置一个 CBTHook 来接收窗口更改的通知。并非所有 CBT 通知都会导致顶级窗口的顺序、位置或可见性发生变化,因此明智的做法是重新运行 EnmWindows 以按 z 顺序构建新的窗口位置列表,并将其与之前的列表进行比较,然后再进一步处理列表,这样只有在发生真正的变化时才会进行进一步的处理。
请注意,使用 Hook 时,您不能混合使用 32 位和 64 位。如果您正在运行 32 位应用程序,那么您将收到来自 32 位进程的通知。同样适用于 64 位。因此,如果您想在 64 位机器上监控整个系统,似乎需要运行两个应用程序。我的推理来自阅读这篇文章:
SetWindowsHookEx can be used to inject a DLL into another process. A 32-bit DLL cannot be injected into a 64-bit process, and a 64-bit DLL cannot be injected into a 32-bit process. If an application requires the use of hooks in other processes, it is required that a 32-bit application call SetWindowsHookEx to inject a 32-bit DLL into 32-bit processes, and a 64-bit application call SetWindowsHookEx to inject a 64-bit DLL into 64-bit processes. The 32-bit and 64-bit DLLs must have different names. (From the SetWindowsHookEx api page.)
当您在 Java 中实现此功能时,您可能需要查看 JNA - 它使对 native 库的编写访问变得更加简单(在 java 中调用代码)并且不再需要您自己的 native JNI DLL。
编辑:您问它有多少代码以及编写多长时间。这是java中的代码
import com.sun.jna.Native;
import com.sun.jna.Structure;
import com.sun.jna.win32.StdCallLibrary;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Main {
public static void main(String[] args) {
Main m = new Main();
final List<WindowInfo> inflList = new ArrayList<WindowInfo>();
final List<Integer> order = new ArrayList<Integer>();
int top = User32.instance.GetTopWindow(0);
while (top != 0) {
order.add(top);
top = User32.instance.GetWindow(top, User32.GW_HWNDNEXT);
}
User32.instance.EnumWindows(new WndEnumProc() {
public boolean callback(int hWnd, int lParam) {
if (User32.instance.IsWindowVisible(hWnd)) {
RECT r = new RECT();
User32.instance.GetWindowRect(hWnd, r);
if (r.left > -32000) { // If it's not minimized
byte[] buffer = new byte[1024];
User32.instance.GetWindowTextA(hWnd, buffer, buffer.length);
String title = Native.toString(buffer);
inflList.add(new WindowInfo(hWnd, r, title));
}
}
return true;
}
}, 0);
Collections.sort(inflList, new Comparator<WindowInfo>() {
public int compare(WindowInfo o1, WindowInfo o2) {
return order.indexOf(o1.hwnd)-order.indexOf(o2.hwnd);
}
});
for (WindowInfo w : inflList) {
System.out.println(w);
}
}
public static interface WndEnumProc extends StdCallLibrary.StdCallCallback {
boolean callback(int hWnd, int lParam);
}
public static interface User32 extends StdCallLibrary {
final User32 instance = (User32) Native.loadLibrary ("user32", User32.class);
final int GW_HWNDNEXT = 2;
boolean EnumWindows(WndEnumProc wndenumproc, int lParam);
boolean IsWindowVisible(int hWnd);
int GetWindowRect(int hWnd, RECT r);
void GetWindowTextA(int hWnd, byte[] buffer, int buflen);
int GetTopWindow(int hWnd);
int GetWindow(int hWnd, int flag);
}
public static class RECT extends Structure {
public int left, top, right, bottom;
}
public static class WindowInfo {
public final int hwnd;
public final RECT rect;
public final String title;
public WindowInfo(int hwnd, RECT rect, String title) {
this.hwnd = hwnd;
this.rect = rect;
this.title = title;
}
public String toString() {
return String.format("(%d,%d)-(%d,%d) : \"%s\"",
rect.left, rect.top,
rect.right, rect.bottom,
title);
}
}
}
我已经制作了大部分相关的类和接口(interface)内部类,以保持示例紧凑和可粘贴,以便立即编译。在实际实现中,它们将是常规的顶级类。命令行应用程序打印出可见窗口及其位置。我在 32 位 jvm 和 64 位上运行它,并且得到了相同的结果。
EDIT2:更新代码以包含 z 顺序。它确实使用 GetNextWindow。在生产应用程序中,您可能应该为下一个和上一个值调用两次 GetNextWindow,并检查它们是否一致并且是有效的窗口句柄。
关于java - Windows:如何获取所有可见窗口的列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3188484/
我正在编写一个具有以下签名的 Java 方法。 void Logger(Method method, Object[] args); 如果一个方法(例如 ABC() )调用此方法 Logger,它应该
我是 Java 新手。 我的问题是我的 Java 程序找不到我试图用作的图像文件一个 JButton。 (目前这段代码什么也没做,因为我只是得到了想要的外观第一的)。这是我的主课 代码: packag
好的,今天我在接受采访,我已经编写 Java 代码多年了。采访中说“Java 垃圾收集是一个棘手的问题,我有几个 friend 一直在努力弄清楚。你在这方面做得怎么样?”。她是想骗我吗?还是我的一生都
我的 friend 给了我一个谜语让我解开。它是这样的: There are 100 people. Each one of them, in his turn, does the following
如果我将使用 Java 5 代码的应用程序编译成字节码,生成的 .class 文件是否能够在 Java 1.4 下运行? 如果后者可以工作并且我正在尝试在我的 Java 1.4 应用程序中使用 Jav
有关于why Java doesn't support unsigned types的问题以及一些关于处理无符号类型的问题。我做了一些搜索,似乎 Scala 也不支持无符号数据类型。限制是Java和S
我只是想知道在一个 java 版本中生成的字节码是否可以在其他 java 版本上运行 最佳答案 通常,字节码无需修改即可在 较新 版本的 Java 上运行。它不会在旧版本上运行,除非您使用特殊参数 (
我有一个关于在命令提示符下执行 java 程序的基本问题。 在某些机器上我们需要指定 -cp 。 (类路径)同时执行java程序 (test为java文件名与.class文件存在于同一目录下) jav
我已经阅读 StackOverflow 有一段时间了,现在我才鼓起勇气提出问题。我今年 20 岁,目前在我的家乡(罗马尼亚克卢日-纳波卡)就读 IT 大学。足以介绍:D。 基本上,我有一家提供簿记应用
我有 public JSONObject parseXML(String xml) { JSONObject jsonObject = XML.toJSONObject(xml); r
我已经在 Java 中实现了带有动态类型的简单解释语言。不幸的是我遇到了以下问题。测试时如下代码: def main() { def ks = Map[[1, 2]].keySet()
一直提示输入 1 到 10 的数字 - 结果应将 st、rd、th 和 nd 添加到数字中。编写一个程序,提示用户输入 1 到 10 之间的任意整数,然后以序数形式显示该整数并附加后缀。 public
我有这个 DownloadFile.java 并按预期下载该文件: import java.io.*; import java.net.URL; public class DownloadFile {
我想在 GUI 上添加延迟。我放置了 2 个 for 循环,然后重新绘制了一个标签,但这 2 个 for 循环一个接一个地执行,并且标签被重新绘制到最后一个。 我能做什么? for(int i=0;
我正在对对象 Student 的列表项进行一些测试,但是我更喜欢在 java 类对象中创建硬编码列表,然后从那里提取数据,而不是连接到数据库并在结果集中选择记录。然而,自从我这样做以来已经很长时间了,
我知道对象创建分为三个部分: 声明 实例化 初始化 classA{} classB extends classA{} classA obj = new classB(1,1); 实例化 它必须使用
我有兴趣使用 GPRS 构建车辆跟踪系统。但是,我有一些问题要问以前做过此操作的人: GPRS 是最好的技术吗?人们意识到任何问题吗? 我计划使用 Java/Java EE - 有更好的技术吗? 如果
我可以通过递归方法反转数组,例如:数组={1,2,3,4,5} 数组结果={5,4,3,2,1}但我的结果是相同的数组,我不知道为什么,请帮助我。 public class Recursion { p
有这样的标准方式吗? 包括 Java源代码-测试代码- Ant 或 Maven联合单元持续集成(可能是巡航控制)ClearCase 版本控制工具部署到应用服务器 最后我希望有一个自动构建和集成环境。
我什至不知道这是否可能,我非常怀疑它是否可能,但如果可以,您能告诉我怎么做吗?我只是想知道如何从打印机打印一些文本。 有什么想法吗? 最佳答案 这里有更简单的事情。 import javax.swin
我是一名优秀的程序员,十分优秀!