模拟桌面操作API

在CukeTest的leanpro.common库中提供了一套模拟鼠标、键盘和屏幕操作的对象:

由于操作是通过模拟实现的,因此可以全平台上使用。

用途

CukeTest中,有针对控件直接操作的对象识别高级API,有些时候,仍旧需要通过键盘和鼠标的一些组合操作完成自动化。因此CukeTest提供了一套模拟鼠标和键盘操作的对象:MouseKeyboard。它们能处理鼠标移动的目标位置没有控件,或对象操作API完成不了的功能。例如某些应用中的菜单是隐藏在屏幕边缘的,需要鼠标移至屏幕边缘才会展开,这个时候就需要使用直接的鼠标和键盘操作。

使得操作鼠标和键盘的自动化脚本可以写作:

JavaScript
Python
const { Keyboard, Mouse } = require('leanpro.common');
Mouse.move(1920,1080);

Keyboard.keyDown("control");
Keyboard.keyTap("a");
Keyboard.keyUp("control");
from leanproAuto import Keyboard, Mouse
Mouse.move(1920,1080)
Keyboard.keyDown("control")
Keyboard.keyTap("a")
Keyboard.keyUp("control")

另外,由于Mouse的移动、点击操作都建立在屏幕坐标系上,因此CukeTest另外提供了操作屏幕的对象Screen,不仅可以获取屏幕属性(分辨率等),还可以进行截屏操作。

JavaScript
Python
Screen.capture();
Screen.capture()

注意,这些方法都是同步方法,不需要使用await

鼠标自动化对象: Mouse

用于实现鼠标移动,以及各个鼠标按钮的点击、按下/释放的自动化对象。比如某些应用中的界面是隐藏在屏幕边缘的,需要鼠标移至屏幕边缘才会出现,那么这种场景就不好用控件操作来实现了。而Mouse对象正是为了解决这类问题而推出的。

类型文件定义

JavaScript
Python
export class Mouse {
    static move(x: number, y: number): void;    
    static moveSmooth(x: number, y: number, seconds?: number): void;
    static drag(x: number, y: number, seconds?: number): void;
    static setDelay(delay: number): void;
    static position(): Point;
    static click(button: MouseKey): void;
    static doubleClick(button: MouseKey): void;
    static keyDown(button: MouseKey): void;
    static keyUp(button: MouseKey): void;
    static wheel(vertical: number, horizontal: number): void;
}

enum MouseKey {
    LButton = 1,
    RButton = 2,
    MButton = 4,
    Ctrl = 8,
    Shift = 16,
    Alt = 32
}

interface Point {
    x: number,
    y: number
}
class Mouse():
	def move(x: int, y: int) -> None
	def moveSmooth(x: int, y: int, seconds: Optional[int]=None) -> None
	def setDelay(delay: int) -> None
	def drag(x: int, y: int, seconds: Optional[int]=None) -> None
	def position() -> TypedDict
	def click(button: Optional[int]=None) -> None
	def doubleClick(button: Optional[int]=None) -> None
	def keyDown(button: Optional[int]=None) -> None
	def keyUp(button: Optional[int]=None) -> None
	def wheel(vertical: int, horizontal: Optional[int]=None) -> None

class Point():
	x: int
	y: int

API介绍

move(x, y): void

鼠标移动到目标位置,移动前会释放鼠标按键。

  • x: number类型,桌面坐标的水平像素;
  • y: number类型,桌面坐标的垂直像素;
  • 返回值: 不返回任何值的同步方法。

moveSmooth(x: number, y: number, seconds?: number): void

平滑移动鼠标到目标位置,移动行为更接近人工操作.

  • x: number类型,桌面坐标的水平像素;
  • y: number类型,桌面坐标的垂直像素;
  • seconds: (可选)number类型,动作完成的耗时,值越小动作越快。
  • 返回值: 不返回任何值的同步方法。

drag(x: number, y: number, seconds?: number): void

鼠标移动到目标位置,配合keyDown()keyUp()完成拖拽操作。

  • x: number类型,桌面坐标的水平像素;
  • y: number类型,桌面坐标的垂直像素;
  • seconds: (可选)number类型,动作完成的耗时,值越小动作越快。
  • 返回值: 不返回任何值的同步方法。

参考拖拽控件的方式选择

setDelay(delay: number): void

所有的鼠标操作之间的都有10ms的等待时间,也可以使用此方法修改等待时间,单位为毫秒。

  • delay: number类型,间隔时间,单位为毫秒。
  • 返回值: 不返回任何值的同步方法。

position(): Point

获取鼠标位置。

  • 返回值: Point类型。形如{x:100, y:100}

click(button: MouseKey): void

完成一次鼠标点击。

  • button: MouseKey类型,可以查看类型文件定义,为枚举型,传入MouseKey.LButton1效果一样。
  • 返回值: 不返回任何值的同步方法。

使用 单击鼠标左键操作传入数字1

JavaScript
Python
await Mouse.click(1);
Mouse.click(1)
单击鼠标右键操作传入数字2

JavaScript
Python
await Mouse.click(2);
Mouse.click(2)
单击鼠标中键操作传入数字4

JavaScript
Python
await Mouse.click(4);
Mouse.click(4)

doubleClick(button: MouseKey): void

完成一次鼠标双击。

  • button: MouseKey类型,可以查看类型文件定义,为枚举型,传入MouseKey.LButton1效果一样。
  • 返回值: 不返回任何值的同步方法。

使用方法可参考上面的click()

keyDown(button: MouseKey): void

按下鼠标按键,通常用于实现拖拽操作。

  • button: MouseKey类型,可以查看类型文件定义,为枚举型,传入MouseKey.LButton1效果一样。
  • 返回值: 不返回任何值的同步方法。

keyUp(button: MouseKey): void

释放鼠标按键,通常用于实现拖拽操作。

  • button: MouseKey类型,可以查看类型文件定义,为枚举型,传入MouseKey.LButton1效果一样。
  • 返回值: 不返回任何值的同步方法。

将鼠标移动至指定坐标位置按住鼠标一定时间后松开。

JavaScript
Python
await Mouse.move(128,400)
await Mouse.keyDown()
await Util.delay(5000)
await Mouse.keyUp()
Mouse.move(128,400)
Mouse.keyDown()
Util.delay(5000)
Mouse.keyUp()

wheel(vertical: number, horizontal: number): void

滚动鼠标滚轮,不仅可以进行常规的垂直滚动,还可以进行水平滚动。

  • vertical: number类型,垂直滚动的值,向上滚动为正,向下滚动为负。
  • horizontal: number类型,水平滚动的值,向左滚动为正,向右滚动为负。
  • 返回值: 不返回任何值的同步方法。

wheel()方法的精度比较高,因此在调用时可以适当的将参数取大一点,好观察到现象。

拖拽操作的脚本

实现拖拽操作的脚本如下:

JavaScript
Python
mouse.move(0, 0);
mouse.keyDown(MouseKey.LButton);
mouse.drag(100, 100);
mouse.keyUp(1);
mouse.move(0, 0)
mouse.keyDown(MouseKey.LButton)
mouse.drag(100, 100)
mouse.keyUp(1)

键盘自动化对象: Keyboard

与模拟鼠标相对应的就是模拟键盘操作了,与键盘相关的操作属于Keyboard对象。

类型文件定义

JavaScript
Python
export class Keyboard {
    static Keys: Keys,
    static keyTap(key: string): void;
    static unicodeTap(keyCode: number): void;
    static keyDown(key: string): void;
    static keyUp(key: string): void;
    static setDelay(milliseconds: number): void;
    // static typeString(str: string, cpm?: number): void; // deprecated
    static pressKeys(keys: string, options?: PressKeysOptions | number): Promise<void>;
    static disableIme();
}
class Keyboard():
	def keyTap(key: str) -> None
	def unicodeTap(keyCode: int) -> None
	def keyDown(key: str) -> None
	def keyUp(key: str) -> None
	def setDelay(milliseconds: int) -> None
	def typeString(str: str, cpm: Optional[int]=None) -> None
	def pressKeys(keys: str, cpm: Optional[int]=None) -> None
	def disableIme() -> None

API介绍

keyTap(key): void

按下一个键。

  • key: string类型,目标键的键值,可以参考Keys
  • 返回值: 不返回任何值的同步方法。

unicodeTap(key): void

按下一个键,键值由Unicode指定。在JavaScript中,可调用字符串的charCodeAt获得键值。例如下面的代码可以将字符串输出,等效于调用typeString的效果:

JavaScript
'您好,中国(China)'.split('').map(k => Keyboard.unicodeTap(k.charCodeAt(0)));

  • key: string类型,目标键的键值,可以参考Keys
  • 返回值: 不返回任何值的同步方法。

keyDown(key): void

按住一个键。

  • key: string类型,目标键的键值,可以参考Keys
  • 返回值: 不返回任何值的同步方法。

keyUp(key): void

释放一个键。

  • key: string类型,目标键的键值,可以参考Keys
  • 返回值: 不返回任何值的同步方法。

setDelay(delay): void

控制每个键盘操作的间隔,默认为10ms。

  • delay: number类型,间隔时间,单位为毫秒。
  • 返回值: 不返回任何值的同步方法。

typeString(str, cpm): Promise<void>

已弃用,建议使用pressKeys(str, {textOnly: true})代替。

输入一串字符。

  • str: string类型,需要输入的字符串。
  • cpm(可选): number类型,"Character Per Minute",即每分钟中输入的字符,控制输入字符从速度。 如果有些被测应用在快速输入字符时无法及时处理导致显示不正常,可通过设置较低的cpm解决,例如cpm = 60;
  • 返回值: 不返回任何值的异步方法。

pressKeys(keys, options?): Promise<void>

输入按键或字符串,输入前会聚焦目标控件。传入字符串时,字符串中的一些特殊字符(^+~%{}())会被当作控制键(Shift键、CTRL键等)来执行,而不会输入相应的符号,具体可以参考附录: 输入键对应表。如果希望输入纯文本,无视这些控制键符号,则可以使用{textOnly: true}选项,这样调用:pressKeys(str, {textOnly: true})

  • keys: string类型,要输入的按键、组合键或是字符串,最大支持1024个字符。
  • options: (可选)控制输入模式的一些可选参数。
    • textOnly: 仅输入字符串,并将控制字符也当作文本进行输入。效果等同于调用Keyboard.typeString()
    • cpm: 即每分钟输入字符数,用于控制文本输入速度。自动化操作时建议cpm值设置在200以上。由于方法的内部实现,以及各个系统、应用对文本输入的处理不相同,实际输入速度不一定能达到设置的cpm。 当options为数字时相当于cpm参数。
  • 返回值: 不返回任何值的异步方法。 更多相关说明或样例,请参照模拟按键输入pressKeys方法

disableIme(): void

禁用当前聚焦应用的输入法,即切换到中文键盘。这样在调用其他输入键盘操作的方法,如typeString或pressKeys时,不会受输入法的干扰。

  • 返回值: 不返回任何值的异步方法。 注意:输入法是跟应用相关的。如果启动了一个新的被测应用,可能需要再次调用disableIme()。

Keys

Keys是一个枚举对象,枚举了所有的按键,用于keyTapkeyDownkeyUp方法的参数。按键名和描述见下表。

对于字母键和数字键是直接使用同名的字符即可,因此没在下表列出。比如按下字母键b和数字键5直接传入参数"b""5"即可。

Windows徽标键: 作为Windows键盘特有的一个控制键,与Mac的cmd键一样,都可以使用"command"的按键名来使用。

按键名 描述 备注
backspace 退格键
delete 删除键
enter 回车键
tab Tab键
escape Esc键
up 上方向键
down 下方向键
right 右方向键
left 左方向键
home Home键
end End键
pageup Page Up键
pagedown Page Down键
f1 F1键
f2 F2键
f3 F3键
f4 F4键
f5 F5键
f6 F6键
f7 F7键
f8 F8键
f9 F9键
f10 F10键
f11 F11键
f12 F12键
command CMD键或Windows键(取决系统)
alt Alt键
control Ctrl键
shift Shift键
right_shift 右Shift键
space 空格键
printscreen 打印屏幕键 不支持Mac
insert 插入键 不支持Mac
audio_mute 静音键
audio_vol_down 音量减小键
audio_vol_up 音量增大键
audio_play 播放键
audio_stop 停止键
audio_pause 暂停键
audio_prev 上一首键
audio_next 下一首键
audio_rewind 倒带键 只有Linux有效
audio_forward 快进键 只有Linux有效
audio_repeat 重复播放键 只有Linux有效
audio_random 随机播放键 只有Linux有效
numpad_0 数字键盘0
numpad_1 数字键盘1
numpad_2 数字键盘2
numpad_3 数字键盘3
numpad_4 数字键盘4
numpad_5 数字键盘5
numpad_6 数字键盘6
numpad_7 数字键盘7
numpad_8 数字键盘8
numpad_9 数字键盘9
numpad_+ 数字键盘+
numpad_- 数字键盘-
numpad_* 数字键盘*
numpad_/ 数字键盘/
numpad_. 数字键盘.
lights_mon_up 提高显示器亮度 Windows不支持
lights_mon_down 降低显示器亮度 Windows不支持
lights_kbd_toggle 开/关键盘背灯 Windows不支持
lights_kbd_up 提高键盘背灯亮度 Windows不支持
lights_kbd_down 降低键盘背灯亮度 Windows不支持

keys的用法

Keys枚举类常用于特殊按键,有两种用法。比如在需要同时按下Ctrl键与A键执行全选操作时,可以这样写:

JavaScript
Python
const { Keyboard } = require('leanpro.common');
Keyboard.keyDown('control')
Keyboard.keyTap('a');
Keyboard.keyUp('control')
from leanproAuto import Keyboard
Keyboard.keyDown('control')
Keyboard.keyTap('a')
Keyboard.keyUp('control')

由于keyTapkeyDownkeyUp方法默认只接收单个字符(如'a'),如果接收到字符串(如'control'),则会自动使用Keys枚举类,等效于引入Keys枚举类,如下:

JavaScript
const { Keyboard, Keys } = require('leanpro.common');
Keyboard.keyDown(Keys.control)
Keyboard.keyTap('a');
Keyboard.keyUp(Keys.control)

如果希望直接输入字符串,应该使用pressKeys(str, {textOnly: true})

组合键操作

如果需要在操作过程中按住某个键,比如按住Ctrl键并拖拽、按住Shift并点击这类的操作,借由keyDown()keyUp()方法可以灵活地实现:

JavaScript
Python
const { Keyboard } = require('leanpro.common');
Keyboard.keyDown('shift')
// 在此处放入控制键按下期间的操作脚本
// ...
Keyboard.keyUp('shift')
from leanproAuto import Keyboard
Keyboard.keyDown('shift')
# 在此处放入控制键按下期间的操作脚本
# ...
Keyboard.keyUp('shift')

屏幕自动化对象: Screen

屏幕自动化对象Screen,用于获取屏幕属性,以及操作屏幕。

类型文件定义

类型文件定义如下:

JavaScript
Python
export class Screen {
    static screenRect(moniter?: number): Rect
    static all(moniter?: number): Rect[]
    static colorAt(x: number, y: number): string;
    static capture(rect?: Rect): Buffer;
    static captureToFile(filePath: string, rect?: Rect): void;
    static takeScreenshot(filePath: string, monitor?: number): string | void;
    static highlight(rect: Rect, duration?: number);

    // deprecated 弃用
    static screenSize(): {width: number, height: number};
}
class Screen():
	def all() -> "List[Rect]"
	def screenRect(monitor: Optional[int]=None) -> "Rect"
	def screenSize() -> TypedDict
	def colorAt(x: int, y: int) -> str
	def capture(rect: Optional[Rect]=None) -> "bytearray"
	def captureToFile(filePath: str, rect: Optional[Rect]=None) -> None
	def takeScreenshot(filePath: str, monitor: Optional[int]=None) -> Union[str, None]
    def highlight(rect: Rect, duration: Optional[int]=None) -> "any"

class ScreenSize():
    width: int
    height: int

API介绍

screenRect(monitor?:number): Rect

用于获取指定监视器(或者默认取所有屏幕合并后的)的边界信息。

  • monitor: (可选)要获取边界信息的监视器的编号。不传参数或传-1,会获取所有屏幕合并后的尺寸,数值上等于Screen.capture方法获取到截图的尺寸。传0返回第一个显示屏,1返回第二个,以此类推。
  • 返回值: Rect对象,表示指定监视器的边界信息。Rect 对象包含以下属性:
    • x: 屏幕左上角的水平坐标。
    • y: 屏幕左上角的垂直坐标。
    • width: 屏幕的宽度,单位为像素。
    • height: 屏幕的高度,单位为像素。

使用示例

以下示例展示了如何使用 Screen.screenRect 方法获取指定监视器的边界信息:

JavaScript
Python
const { Screen } = require('leanpro.common');
// 获取主屏幕的边界信息
const mainScreenRect = Screen.screenRect();
console.log('Main Screen Rect:', mainScreenRect);

// 获取编号为1的监视器的边界信息
const monitor1Rect = Screen.screenRect(1);
console.log('Monitor 1 Rect:', monitor1Rect);
from leanproAuto import Screen
# 获取主屏幕的边界信息
main_screen_rect = Screen.screenRect()
print('Main Screen Rect:', main_screen_rect)

# 获取编号为1的监视器的边界信息
monitor1_rect = Screen.screenRect(1)
print('Monitor 1 Rect:', monitor1_rect)

在这个例子中,我们首先获取主屏幕的边界信息,然后获取编号为1的监视器的边界信息,然后将这些信息打印出来。

all(): Rect[]

用于获取所有屏幕的边界信息。这对于多屏幕环境尤其有用,可以通过此方法获取每个屏幕的位置和尺寸。

  • 返回值: Rect对象组成的数组,其中每个 Rect 对象表示一个屏幕的边界信息。

使用示例

以下示例展示了如何使用 Screen.all 方法获取所有屏幕的边界信息:

JavaScript
Python
const { Screen } = require('leanpro.common');
const screens = Screen.all();

screens.forEach((screen, i) => {
    console.log(`Screen ${i}:`, screen);
});
from leanproAuto import Screen
screens = Screen.all()

for i, screen in enumerate(screens):
    print(f"Screen {i}: {screen}")

在这个例子中,我们首先使用 Screen.all 方法来获取所有屏幕的信息,然后遍历结果并打印出每个屏幕的边界信息。

screenSize(): {width: number, height: number}

不建议使用,可以用screenRect代替。

用于获取当前屏幕的尺寸,即屏幕的宽度和高度。它不需要任何参数。

  • 返回值: {width: number, height: number},这两个属性分别表示屏幕的宽度和高度,以像素为单位。

colorAt(x: number, y: number): string

用于获取屏幕上特定点的颜色。通过输入特定的 x 和 y 坐标,您可以获取该点的颜色值。返回值为一串十六进制格式的RGB颜色代码字符串,形如"FFFFFF"

  • x: number类型,定义所需获取颜色点的水平坐标。x的起点在屏幕的最左边。
  • y: number类型,定义所需获取颜色点的垂直坐标。y的起点在屏幕的最顶部。
  • 返回值: string类型,一串十六进制格式的RGB颜色代码字符串。

使用示例

以下示例展示了如何使用 Screen.colorAt 方法来获取屏幕上某个特定点的颜色:

JavaScript
Python
const { Screen } = require('leanpro.common');
const x = 500;
const y = 300;
const color = Screen.colorAt(x, y);

console.log(`Color at (${x}, ${y}): ${color}`);
from leanproAuto import Screen
x = 500
y = 300
color = Screen.colorAt(x, y)

print(f"Color at ({x}, {y}): {color}")

在这个例子中,我们首先定义了所需点的 x 和 y 坐标,然后使用 Screen.colorAt 方法来获取这个点的颜色。最后,我们打印出这个颜色值。

capture(rect?: Rect): Buffer

用于捕获屏幕上的特定矩形区域的截图。如果没有指定矩形区域,那么此方法将捕获整个屏幕的截图。

  • rect: (可选)Rect类型,这是一个包含 xywidth,和 height 属性的对象,用来定义要截图的矩形区域的位置和尺寸。xy 属性定义了矩形的左上角在屏幕上的坐标,而 widthheight 定义了矩形的宽度和高度。如果此参数未提供,那么方法将捕获整个屏幕的截图。具体定义详见Rect类型介绍
  • 返回值: Buffer类型。其中包含了捕获的截图数据,这个 Buffer 对象可以被用来将截图数据保存为文件,或者用于其他需要使用图像数据的场景。例如用于报告附件,或者使用Image.from()方法构造Image对象。

使用示例

以下示例展示了如何使用 Screen.capture 方法来捕获一个特定的屏幕区域的截图,并将其保存为文件:

JavaScript
Python
const { Screen } = require('leanpro.common');
const fs = require('fs');
const rect = {"x":555,"y":358,"width":126,"height":34};
const buffer = Screen.capture(rect);

fs.writeFileSync('screenshot.png', buffer);
from leanproAuto import Screen
rect = {"x":555, "y":358, "width":126, "height":34}
buffer = Screen.capture(rect)

with open('screenshot--2.png', 'wb') as f:
    f.write(buffer)

在这个例子中,我们首先定义了矩形区域的坐标和尺寸,然后使用 Screen.capture 方法来捕获截图,最后使用 fs.writeFileSync 方法将截图数据保存为一个 PNG 文件。

captureToFile(filePath: string, rect?: Rect): void

用于捕获屏幕截图并将其保存到指定文件路径的函数。用户可以选择截取整个屏幕或者截取屏幕上的特定区域。filePath为路径以及文件名。如果指定了rect参数,则会只截取指定方框的截图。

  • filePath: string类型,这是一个字符串,表示截图保存的文件路径。文件路径应包含文件名和扩展名。支持的文件格式包括 .jpg, .png, .bmp 等。
  • rect: (可选)Rect类型,这是一个包含 xywidth,和 height 属性的对象,用来定义要截取的矩形区域的位置和尺寸。xy 属性定义了矩形的左上角在屏幕上的坐标,而 widthheight 定义了矩形的宽度和高度。如果这个参数没有提供,那么会捕获整个屏幕的截图。具体定义详见Rect类型介绍
  • 返回值: 此方法没有返回值。

使用示例

以下示例展示了如何使用 Screen.captureToFile 方法来截取整个屏幕的截图并保存到指定的文件路径:

JavaScript
Python
const { Screen } = require('leanpro.common');
Screen.captureToFile("C:/Users/Username/Desktop/screenshot.png");
from leanproAuto import Screen
Screen.captureToFile("C:/Users/Username/Desktop/screenshot.png")

以下示例展示了如何使用 Screen.captureToFile 方法来截取屏幕上特定区域的截图并保存到指定的文件路径:

JavaScript
Python
const { Screen } = require('leanpro.common');
Screen.captureToFile("C:/Users/Username/Desktop/screenshot.png", {"x":555,"y":358,"width":126,"height":34});
from leanproAuto import Screen
Screen.captureToFile("C:/Users/Username/Desktop/screenshot.png", {"x":555,"y":358,"width":126,"height":34})

在这个例子中,矩形区域的左上角坐标是 (555,358),矩形的宽度是 126 像素,高度是 34 像素。

highlight(rect: Rect, duration?: number)

用于高亮显示屏幕上指定矩形区域的函数。这个功能在标识和追踪特定屏幕区域时特别有用,如在测试过程中,它可以直观地显示出正在测试或分析的区域。

  • rect: Rect类型。这是一个包含 xywidth,和 height 属性的对象,用来定义要高亮的矩形区域的位置和尺寸。xy 属性定义了矩形的左上角在屏幕上的坐标,而 widthheight 定义了矩形的宽度和高度。具体定义详见Rect类型介绍

  • duration: (可选)number类型。这是一个代表高亮显示持续时间的数字,单位是毫秒。如果这个参数没有提供,那么高亮显示将持续到下一个 highlight 调用,或者到测试结束。

  • 返回值: 此方法没有返回值。

使用示例

以下示例展示了如何使用 Screen.highlight 方法来高亮显示一个特定的屏幕区域:

JavaScript
Python
const { Screen } = require('leanpro.common');
Screen.highlight({"x":555,"y":358,"width":126,"height":34});
from leanproAuto import Screen
Screen.highlight({"x":555,"y":358,"width":126,"height":34})
在这个例子中,矩形区域的左上角坐标是 (555,358),矩形的宽度是 126 像素,高度是 34 像素。

takeScreenshot(filePath: string, monitor?: number): string

由原先的Util.takeScreenshot方法合并而来,获取屏幕截屏。详见takeScreenshot()方法介绍

不推荐使用。

results matching ""

    No results matching ""