autoxkit 2.4.4__tar.gz → 2.4.8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {autoxkit-2.4.4 → autoxkit-2.4.8}/PKG-INFO +1 -7
- {autoxkit-2.4.4 → autoxkit-2.4.8}/README.md +0 -6
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit/hook/event.py +4 -2
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit/hook/hook_listener.py +4 -24
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit/mousekey/mouse.py +15 -3
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit/window/window_match.py +18 -8
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit.egg-info/PKG-INFO +1 -7
- {autoxkit-2.4.4 → autoxkit-2.4.8}/pyproject.toml +1 -1
- {autoxkit-2.4.4 → autoxkit-2.4.8}/LICENSE.txt +0 -0
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit/__init__.py +0 -0
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit/android/__init__.py +0 -0
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit/android/adb.py +0 -0
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit/android/binary.py +0 -0
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit/android/client.py +0 -0
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit/android/control.py +0 -0
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit/android/control_backup.py +0 -0
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit/android/models.py +0 -0
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit/android/streams.py +0 -0
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit/constants.py +0 -0
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit/hook/__init__.py +0 -0
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit/hook/hotkey_listener.py +0 -0
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit/match/__init__.py +0 -0
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit/match/match.py +0 -0
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit/mousekey/__init__.py +0 -0
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit/mousekey/input.py +0 -0
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit/mousekey/keyboard.py +0 -0
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit/utils.py +0 -0
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit/window/__init__.py +0 -0
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit/window/window.py +0 -0
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit/window/window_action.py +0 -0
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit.egg-info/SOURCES.txt +0 -0
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit.egg-info/dependency_links.txt +0 -0
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit.egg-info/requires.txt +0 -0
- {autoxkit-2.4.4 → autoxkit-2.4.8}/autoxkit.egg-info/top_level.txt +0 -0
- {autoxkit-2.4.4 → autoxkit-2.4.8}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: autoxkit
|
|
3
|
-
Version: 2.4.
|
|
3
|
+
Version: 2.4.8
|
|
4
4
|
Summary: Python library for Windows automation and Android device screen casting and control
|
|
5
5
|
Author-email: YorickFin <1582456060@qq.com>
|
|
6
6
|
License: GPL-3.0-or-later
|
|
@@ -91,17 +91,11 @@ def mouse_up(event: MouseEvent):
|
|
|
91
91
|
return False
|
|
92
92
|
|
|
93
93
|
|
|
94
|
-
def mouse_move(event: MouseEvent):
|
|
95
|
-
print(event.action, event.button, event.position)
|
|
96
|
-
return False
|
|
97
|
-
|
|
98
|
-
|
|
99
94
|
hook_listener = HookListener()
|
|
100
95
|
hook_listener.add_handler('keydown', key_down)
|
|
101
96
|
hook_listener.add_handler('keyup', key_up)
|
|
102
97
|
hook_listener.add_handler('mousedown', mouse_down)
|
|
103
98
|
hook_listener.add_handler('mouseup', mouse_up)
|
|
104
|
-
hook_listener.add_handler('mousemove', mouse_move)
|
|
105
99
|
hook_listener.start()
|
|
106
100
|
|
|
107
101
|
print("当前鼠标位置:", hook_listener.get_mouse_position())
|
|
@@ -68,17 +68,11 @@ def mouse_up(event: MouseEvent):
|
|
|
68
68
|
return False
|
|
69
69
|
|
|
70
70
|
|
|
71
|
-
def mouse_move(event: MouseEvent):
|
|
72
|
-
print(event.action, event.button, event.position)
|
|
73
|
-
return False
|
|
74
|
-
|
|
75
|
-
|
|
76
71
|
hook_listener = HookListener()
|
|
77
72
|
hook_listener.add_handler('keydown', key_down)
|
|
78
73
|
hook_listener.add_handler('keyup', key_up)
|
|
79
74
|
hook_listener.add_handler('mousedown', mouse_down)
|
|
80
75
|
hook_listener.add_handler('mouseup', mouse_up)
|
|
81
|
-
hook_listener.add_handler('mousemove', mouse_move)
|
|
82
76
|
hook_listener.start()
|
|
83
77
|
|
|
84
78
|
print("当前鼠标位置:", hook_listener.get_mouse_position())
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
from ..constants import Hex_Key_Code
|
|
2
2
|
|
|
3
|
+
# 预构建 vkCode → name 反向字典
|
|
4
|
+
_VK_TO_NAME = {v: k for k, v in Hex_Key_Code.items()}
|
|
5
|
+
|
|
3
6
|
class KeyEvent:
|
|
4
7
|
"""
|
|
5
8
|
键盘事件
|
|
@@ -14,8 +17,7 @@ class KeyEvent:
|
|
|
14
17
|
def __init__(self, action, vk_code):
|
|
15
18
|
self.action = action
|
|
16
19
|
self.key_code = vk_code
|
|
17
|
-
|
|
18
|
-
self.key_name = name if name else str(vk_code)
|
|
20
|
+
self.key_name = _VK_TO_NAME.get(vk_code, str(vk_code))
|
|
19
21
|
|
|
20
22
|
class MouseEvent:
|
|
21
23
|
"""
|
|
@@ -8,9 +8,6 @@ from ..constants import Hex_Hook_Code
|
|
|
8
8
|
|
|
9
9
|
HHC = Hex_Hook_Code
|
|
10
10
|
|
|
11
|
-
# 消息泵空闲轮询间隔(秒),无消息时休眠此时间以释放 CPU
|
|
12
|
-
MSG_POLL_INTERVAL = 0.001
|
|
13
|
-
|
|
14
11
|
# ---------- 结构体定义 ----------
|
|
15
12
|
class KBDLLHOOKSTRUCT(Structure):
|
|
16
13
|
_fields_ = [
|
|
@@ -80,7 +77,6 @@ class HookListener:
|
|
|
80
77
|
self._on_keyup = []
|
|
81
78
|
self._on_mousedown = []
|
|
82
79
|
self._on_mouseup = []
|
|
83
|
-
self._on_mousemove = []
|
|
84
80
|
|
|
85
81
|
# 钩子与线程状态
|
|
86
82
|
self._thread = None
|
|
@@ -115,8 +111,6 @@ class HookListener:
|
|
|
115
111
|
self._on_mousedown.append(func)
|
|
116
112
|
elif event_type == "mouseup":
|
|
117
113
|
self._on_mouseup.append(func)
|
|
118
|
-
elif event_type == "mousemove":
|
|
119
|
-
self._on_mousemove.append(func)
|
|
120
114
|
else:
|
|
121
115
|
raise ValueError("unknown event_type: " + str(event_type))
|
|
122
116
|
|
|
@@ -140,8 +134,6 @@ class HookListener:
|
|
|
140
134
|
target = self._on_mousedown
|
|
141
135
|
elif event_type == "mouseup":
|
|
142
136
|
target = self._on_mouseup
|
|
143
|
-
elif event_type == "mousemove":
|
|
144
|
-
target = self._on_mousemove
|
|
145
137
|
else:
|
|
146
138
|
raise ValueError("unknown event_type: " + str(event_type))
|
|
147
139
|
try:
|
|
@@ -201,17 +193,7 @@ class HookListener:
|
|
|
201
193
|
ms = ctypes.cast(lParam, POINTER(MSLLHOOKSTRUCT)).contents
|
|
202
194
|
x, y = ms.pt.x, ms.pt.y
|
|
203
195
|
|
|
204
|
-
if wParam
|
|
205
|
-
event = MouseEvent("MouseMove", None, x, y)
|
|
206
|
-
for cb in self._on_mousemove:
|
|
207
|
-
try:
|
|
208
|
-
result = cb(event)
|
|
209
|
-
if result is True:
|
|
210
|
-
return 1 # 截断事件传播
|
|
211
|
-
except Exception as e:
|
|
212
|
-
print(f"[hook_listener] Exception in mousemove callback: {e}", file=__import__('sys').stderr)
|
|
213
|
-
|
|
214
|
-
elif wParam in (HHC["MLeftDown"], HHC["MRightDown"], HHC["MiddleDown"], HHC["XDown"]):
|
|
196
|
+
if wParam in (HHC["MLeftDown"], HHC["MRightDown"], HHC["MiddleDown"], HHC["XDown"]):
|
|
215
197
|
button = self._get_mouse_button(wParam, ms.mouseData)
|
|
216
198
|
event = MouseEvent("MouseDown", button, x, y)
|
|
217
199
|
for cb in self._on_mousedown:
|
|
@@ -315,7 +297,7 @@ class HookListener:
|
|
|
315
297
|
self._stop_event.set()
|
|
316
298
|
# 发送 WM_QUIT 消息唤醒 GetMessageW 阻塞
|
|
317
299
|
if self._thread and self._thread.is_alive():
|
|
318
|
-
user32.PostThreadMessageW(self._thread.ident, 0x0012, 0, 0)
|
|
300
|
+
user32.PostThreadMessageW(self._thread.ident, 0x0012, 0, 0) # WM_QUIT
|
|
319
301
|
self._thread.join(timeout=1.0)
|
|
320
302
|
# 尝试取消钩子(若尚未取消)
|
|
321
303
|
if self.keyboard_hook:
|
|
@@ -346,11 +328,9 @@ class HookListener:
|
|
|
346
328
|
self._stop_event.set()
|
|
347
329
|
return
|
|
348
330
|
|
|
331
|
+
# 消息泵循环:ctypes 调用 GetMessageW 期间会释放 GIL
|
|
349
332
|
msg = wintypes.MSG()
|
|
350
|
-
while
|
|
351
|
-
ret = user32.GetMessageW(byref(msg), 0, 0, 0)
|
|
352
|
-
if ret <= 0:
|
|
353
|
-
break
|
|
333
|
+
while user32.GetMessageW(byref(msg), None, 0, 0) > 0:
|
|
354
334
|
user32.TranslateMessage(byref(msg))
|
|
355
335
|
user32.DispatchMessageW(byref(msg))
|
|
356
336
|
|
|
@@ -10,8 +10,9 @@ SendInput = user32.SendInput
|
|
|
10
10
|
|
|
11
11
|
class Mouse:
|
|
12
12
|
|
|
13
|
-
def __init__(self):
|
|
13
|
+
def __init__(self, compat=False):
|
|
14
14
|
"""初始化鼠标控制器"""
|
|
15
|
+
self.compat = compat
|
|
15
16
|
self.mouse_point = tuple()
|
|
16
17
|
self.screen_width = user32.GetSystemMetrics(0)
|
|
17
18
|
self.screen_height = user32.GetSystemMetrics(1)
|
|
@@ -23,14 +24,25 @@ class Mouse:
|
|
|
23
24
|
4: [HMC["XDown"], HMC["XUp"], HMC["MSide2"]],
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
def
|
|
27
|
-
"""
|
|
27
|
+
def _mouse_action_compat(self, flags, x=0, y=0, data=0):
|
|
28
|
+
"""执行鼠标动作的底层函数(兼容模式,使用 mouse_event API)"""
|
|
29
|
+
user32.mouse_event(flags, x, y, data, 0)
|
|
30
|
+
|
|
31
|
+
def _mouse_action_input(self, flags, x=0, y=0, data=0):
|
|
32
|
+
"""执行鼠标动作的底层函数(SendInput 模式)"""
|
|
28
33
|
extra = ctypes.c_ulong(0)
|
|
29
34
|
ii_ = Input_I()
|
|
30
35
|
ii_.mi = MouseInput(x, y, data, flags, 0, ctypes.pointer(extra))
|
|
31
36
|
input_struct = Input(ctypes.c_ulong(0), ii_)
|
|
32
37
|
SendInput(1, ctypes.pointer(input_struct), ctypes.sizeof(input_struct))
|
|
33
38
|
|
|
39
|
+
def _mouse_action(self, flags, x=0, y=0, data=0):
|
|
40
|
+
"""执行鼠标动作的底层函数"""
|
|
41
|
+
if self.compat:
|
|
42
|
+
self._mouse_action_compat(flags, x, y, data)
|
|
43
|
+
else:
|
|
44
|
+
self._mouse_action_input(flags, x, y, data)
|
|
45
|
+
|
|
34
46
|
def _verify_mouse_point(self, x: int=None, y: int=None):
|
|
35
47
|
"""验证鼠标坐标是否在屏幕范围内"""
|
|
36
48
|
if x is None or y is None:
|
|
@@ -169,8 +169,13 @@ class WindowMatch:
|
|
|
169
169
|
bmi.bmiHeader.biClrUsed = 0
|
|
170
170
|
bmi.bmiHeader.biClrImportant = 0
|
|
171
171
|
|
|
172
|
-
#
|
|
173
|
-
|
|
172
|
+
# GDI 要求位图每行字节数(stride)必须是 4 的倍数(DWORD 对齐)
|
|
173
|
+
# 若直接用 width * height * 3,当 width * 3 不是 4 的倍数时,
|
|
174
|
+
# 每行末尾会被 GDI 填充字节,导致 reshape 后行数据错位、图像倾斜。
|
|
175
|
+
stride = ((width * 3 + 3) // 4) * 4
|
|
176
|
+
|
|
177
|
+
# 分配内存(按 stride 对齐)
|
|
178
|
+
buffer_size = stride * height
|
|
174
179
|
buffer = ctypes.create_string_buffer(buffer_size)
|
|
175
180
|
|
|
176
181
|
# 获取位图数据
|
|
@@ -178,8 +183,9 @@ class WindowMatch:
|
|
|
178
183
|
hdc_mem, hbitmap, 0, height, buffer, ctypes.byref(bmi), 0
|
|
179
184
|
)
|
|
180
185
|
|
|
181
|
-
# 转换为numpy
|
|
182
|
-
img_array = np.frombuffer(buffer, dtype=np.uint8).reshape(height,
|
|
186
|
+
# 转换为numpy数组:先按 stride 展开,再丢弃每行末尾的填充字节
|
|
187
|
+
img_array = np.frombuffer(buffer, dtype=np.uint8).reshape(height, stride)
|
|
188
|
+
img_array = img_array[:, :width * 3].reshape(height, width, 3)
|
|
183
189
|
|
|
184
190
|
# 转为RGB格式数组
|
|
185
191
|
img_array = self.data_header.image_to_numpy(img_array, to_rgb=True)
|
|
@@ -266,8 +272,11 @@ class WindowMatch:
|
|
|
266
272
|
bmi.bmiHeader.biClrUsed = 0
|
|
267
273
|
bmi.bmiHeader.biClrImportant = 0
|
|
268
274
|
|
|
269
|
-
#
|
|
270
|
-
|
|
275
|
+
# GDI 要求位图每行字节数(stride)必须是 4 的倍数(DWORD 对齐)
|
|
276
|
+
stride = ((window_width * 3 + 3) // 4) * 4
|
|
277
|
+
|
|
278
|
+
# 分配内存(按 stride 对齐)
|
|
279
|
+
buffer_size = stride * window_height
|
|
271
280
|
buffer = ctypes.create_string_buffer(buffer_size)
|
|
272
281
|
|
|
273
282
|
# 获取位图数据
|
|
@@ -275,8 +284,9 @@ class WindowMatch:
|
|
|
275
284
|
hdc_mem, hbitmap, 0, window_height, buffer, ctypes.byref(bmi), 0
|
|
276
285
|
)
|
|
277
286
|
|
|
278
|
-
# 转换为numpy
|
|
279
|
-
img_array = np.frombuffer(buffer, dtype=np.uint8).reshape(window_height,
|
|
287
|
+
# 转换为numpy数组:先按 stride 展开,再丢弃每行末尾的填充字节
|
|
288
|
+
img_array = np.frombuffer(buffer, dtype=np.uint8).reshape(window_height, stride)
|
|
289
|
+
img_array = img_array[:, :window_width * 3].reshape(window_height, window_width, 3)
|
|
280
290
|
|
|
281
291
|
# 转为RGB格式数组
|
|
282
292
|
img_array = self.data_header.image_to_numpy(img_array, to_rgb=True)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: autoxkit
|
|
3
|
-
Version: 2.4.
|
|
3
|
+
Version: 2.4.8
|
|
4
4
|
Summary: Python library for Windows automation and Android device screen casting and control
|
|
5
5
|
Author-email: YorickFin <1582456060@qq.com>
|
|
6
6
|
License: GPL-3.0-or-later
|
|
@@ -91,17 +91,11 @@ def mouse_up(event: MouseEvent):
|
|
|
91
91
|
return False
|
|
92
92
|
|
|
93
93
|
|
|
94
|
-
def mouse_move(event: MouseEvent):
|
|
95
|
-
print(event.action, event.button, event.position)
|
|
96
|
-
return False
|
|
97
|
-
|
|
98
|
-
|
|
99
94
|
hook_listener = HookListener()
|
|
100
95
|
hook_listener.add_handler('keydown', key_down)
|
|
101
96
|
hook_listener.add_handler('keyup', key_up)
|
|
102
97
|
hook_listener.add_handler('mousedown', mouse_down)
|
|
103
98
|
hook_listener.add_handler('mouseup', mouse_up)
|
|
104
|
-
hook_listener.add_handler('mousemove', mouse_move)
|
|
105
99
|
hook_listener.start()
|
|
106
100
|
|
|
107
101
|
print("当前鼠标位置:", hook_listener.get_mouse_position())
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "autoxkit"
|
|
7
|
-
version = "2.4.
|
|
7
|
+
version = "2.4.8"
|
|
8
8
|
description = "Python library for Windows automation and Android device screen casting and control"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|