打印所有用户界面元素
use uiautomation::Result;
use uiautomation::UIAutomation;
use uiautomation::UIElement;
use uiautomation::UITreeWalker;
fn main() {
let automation = UIAutomation::new().unwrap();
let walker = automation.get_control_view_walker().unwrap();
let root = automation.get_root_element().unwrap();
print_element(&walker, &root, 0).unwrap();
}
fn print_element(walker: &UITreeWalker, element: &UIElement, level: usize) -> Result<()> {
for _ in 0..level {
print!(" ")
}
println!("{} - {}", element.get_classname()?, element.get_name()?);
if let Ok(child) = walker.get_first_child(&element) {
print_element(walker, &child, level + 1)?;
let mut next = child;
while let Ok(sibling) = walker.get_next_sibling(&next) {
print_element(walker, &sibling, level + 1)?;
next = sibling;
}
}
Ok(())
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
这段 Rust 代码使用 uiautomation
包来遍历并打印当前桌面上所有用户界面(UI)元素的层级结构。它以树状格式,逐级打印出每个UI控件的类名(Classname)和名称(Name)。
uiautomation
是一个用于 Windows UI 自动化操作的 Rust 封装库。 它允许程序化地访问桌面应用程序的UI元素,这对于自动化测试和辅助技术(如屏幕阅读器)非常有用。
代码的核心逻辑是递归地遍历UI元素树。这个树的根节点是整个桌面,分支是窗口,叶子节点是窗口里的按钮、文本框等各种控件。
# 代码分步讲解
# main
函数:初始化与启动遍历
fn main() {
// 1. 初始化 UIAutomation 库
let automation = UIAutomation::new().unwrap();
// 2. 获取一个 "Tree Walker" 对象
let walker = automation.get_control_view_walker().unwrap();
// 3. 获取桌面作为根 UI 元素
let root = automation.get_root_element().unwrap();
// 4. 从根元素开始,调用打印函数
print_element(&walker, &root, 0).unwrap();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
UIAutomation::new().unwrap()
: 创建并初始化一个UIAutomation
客户端实例,这是与 Windows UI 自动化框架交互的入口点。automation.get_control_view_walker().unwrap()
: 获取一个UITreeWalker
对象。TreeWalker
是一个用来在UI元素树中导航(例如,寻找父、子或兄弟元素)的工具。get_control_view_walker
特指获取一个只包含“控件”视图的遍历器,它会过滤掉非控件的纯布局元素,让遍历结果更清晰。automation.get_root_element().unwrap()
: 获取整个UI树的根元素,这通常代表了整个桌面。print_element(&walker, &root, 0).unwrap()
: 调用print_element
函数,开始遍历过程。传入了遍历器、根元素和初始层级0
。
# print_element
函数:递归遍历和打印
fn print_element(walker: &UITreeWalker, element: &UIElement, level: usize) -> Result<()> {
// 根据层级打印缩进
for _ in 0..level {
print!(" ")
}
// 打印当前元素的类名和名称
println!("{} - {}", element.get_classname()?, element.get_name()?);
// 尝试获取第一个子元素
if let Ok(child) = walker.get_first_child(&element) {
// 递归打印子元素
print_element(walker, &child, level + 1)?;
let mut next = child;
// 循环获取并打印所有兄弟元素
while let Ok(sibling) = walker.get_next_sibling(&next) {
print_element(walker, &sibling, level + 1)?;
next = sibling;
}
}
Ok(())
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
这个函数是实现UI树遍历的核心,它采用的是深度优先搜索的策略。
打印当前元素信息:
- 函数首先根据
level
(当前在树中的深度)打印一定数量的空格,形成层级缩进效果。 - 然后,它调用
element.get_classname()?
和element.get_name()?
来获取当前UI元素的类名和名称,并将其打印到控制台。类名通常是控件的类型(如 "Button", "Edit"),而名称是其显示的文本或可访问性标签(如 "确定", "用户名")。
- 函数首先根据
遍历子元素:
- 它使用
walker.get_first_child(&element)
尝试找到当前元素的第一个子元素。
- 它使用
递归调用:
- 如果找到了第一个子元素 (
child
),函数会以level + 1
的深度递归调用print_element
自身来处理这个子元素及其所有后代。
- 如果找到了第一个子元素 (
遍历兄弟元素:
- 在处理完第一个子元素及其所有后代之后,代码会进入一个
while
循环。 - 在这个循环中,它使用
walker.get_next_sibling(&next)
来依次获取下一个兄弟元素。 - 每找到一个兄弟元素,它就会再次以相同的
level + 1
深度递归调用print_element
,直到当前层级的所有兄弟元素都被访问完毕。
- 在处理完第一个子元素及其所有后代之后,代码会进入一个
# 总结
总而言之,这段代码的功能是:
- 连接到 Windows UI 自动化系统。
- 从桌面根元素开始。
- 递归地访问屏幕上每一个窗口和控件。
- 以层级分明的缩进格式,打印出每个控件的类名和名称。
运行这段代码,你会在命令行中看到一个详细的、代表当前整个桌面UI结构的树状列表。
上次更新: 2025/08/19, 08:47:47