跳转到内容

元素选择器

元素选择器让脚本可以说清楚“我要找哪个界面元素”。它的写法接近 CSS:从元素类型开始,再按标题、状态或层级逐步缩小范围。

const buttons = root.queryElements('Button[title="Save"]');

大多数情况下,可以先在元素菜单模式选中目标,在 复制 子菜单中选择 复制选择器。把结果粘贴进脚本后,再根据实际使用情况稍作简化。

Cursor Crane 生成的选择器会尽量准确地指向当前元素,但界面中的标题、列表内容和网页文本常常会变化。复制后建议先运行一次,再删去不稳定的部分,只留下真正有区分度的条件。

例如,下面的选择器很精确:

Window[title="Project Alpha"] Group Toolbar Button[title="Run"]

如果项目名经常变化,而工具栏中的 Run 按钮已经足够明确,可以改成:

Toolbar Button[title="Run"]
目标写法示例
按元素类型找ButtonTextFieldListButton
按标题找[title="..."]Button[title="Save"]
按标识符找#idButton#save-button
按状态找:enabled:focusedTextField:focused
找任意元素**[visible=true]

元素类型通常直接写常见名称即可,例如 ButtonTextFieldStaticTextWindowListRowTableScrollArea。如果不确定类型,从复制结果开始最可靠。

空格表示“在里面任意位置”,> 表示“直接在里面”,逗号表示“匹配其中任意一个”:

Window Button
Window > Button
Button[title="Save"], Button[title="Cancel"]
  • Window Button 会寻找窗口里任意层级的按钮。
  • Window > Button 只寻找窗口的直接子按钮。
  • 最后一行同时寻找保存和取消按钮。

属性条件支持完全匹配、开头匹配、结尾匹配和包含:

写法含义示例
=完全相同Button[title="Save"]
^=以文字开头StaticText[value^="Error"]
$=以文字结尾TextField[title$="name"]
*=包含文字Button[label*="Continue"]

常用属性有 titlelabelvalueenabledvisiblefocused。文字里有空格时,请用单引号或双引号包起来。

Button[enabled=true]
TextField[focused=true]
StaticText[value*="Completed"]
写法含义
:first取第一个匹配结果。
:nth(n)取第 n 个匹配结果,从 1 开始。
:enabled / :disabled只保留可用或不可用的元素。
:visible / :hidden只保留可见或隐藏的元素。
:focused只保留当前获得焦点的元素。
List Row:nth(2) Button:first

这会找到列表中的第二行,再取得那一行里的第一个按钮。

queryElements() 会遍历 children,适合完整地搜索一个窗口。元素层级很大时,这个过程可能造成明显阻塞。对于长列表、表格和滚动区域,queryVisibleElement() 更适合“只看用户此刻看得到的内容”:

const visibleButtons = root.queryVisibleElement('Button:enabled', 50);

这样脚本就不会把注意力放在滚动到很远位置的项目上。两个查询方法都可以传入第二个参数,限制最多返回多少个结果。

先找到窗口,再从窗口开始查询。内置 example.element-query.js 已经演示了完整流程:

const application = ctx.elementInspector.getElementByPid(window.application.pid);
const root = application?.getWindows().find(
element => element.windowId === window.windowId
);
const matches = root?.queryVisibleElement('Button[enabled=true]', 50) ?? [];

查询元素需要在 meta.permissions 中加入 "accessibilityAPI"。找到元素后,你可以高亮它、移动到它,或触发它支持的操作。详见脚本 API