ascript 1.3.27__py3-none-win_amd64.whl

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.
Files changed (177) hide show
  1. ascript/__init__.py +8 -0
  2. ascript/hooks/__init__.py +0 -0
  3. ascript/hooks/hook-ascript.py +2 -0
  4. ascript/windows/__init__.py +29 -0
  5. ascript/windows/daos/__init__.py +0 -0
  6. ascript/windows/daos/screen.py +143 -0
  7. ascript/windows/hardware/__init__.py +5 -0
  8. ascript/windows/hardware/keyboard.py +279 -0
  9. ascript/windows/hardware/logitech_driver.py +179 -0
  10. ascript/windows/hardware/mouse.py +308 -0
  11. ascript/windows/license/__init__.py +16 -0
  12. ascript/windows/license/achttp.cp310-win_amd64.pyd +0 -0
  13. ascript/windows/license/achttp.cp311-win_amd64.pyd +0 -0
  14. ascript/windows/license/achttp.cp312-win_amd64.pyd +0 -0
  15. ascript/windows/license/achttp.cp313-win_amd64.pyd +0 -0
  16. ascript/windows/license/achttp.cp314-win_amd64.pyd +0 -0
  17. ascript/windows/license/achttp.cp38-win_amd64.pyd +0 -0
  18. ascript/windows/license/achttp.cp39-win_amd64.pyd +0 -0
  19. ascript/windows/media/__init__.py +0 -0
  20. ascript/windows/resources/__init__.py +0 -0
  21. ascript/windows/resources/libs/logitech/x64/LogitechGkeyEnginesWrapper.dll +0 -0
  22. ascript/windows/resources/libs/logitech/x86/LogitechGkeyEnginesWrapper.dll +0 -0
  23. ascript/windows/resources/templates/__init__.py +0 -0
  24. ascript/windows/resources/templates/__init__py.win.template +51 -0
  25. ascript/windows/resources/templates/build.as.win.template +14 -0
  26. ascript/windows/resources/templates/build.py +71 -0
  27. ascript/windows/resources/templates/logo_windows.ico +0 -0
  28. ascript/windows/resources/templates/windows/main.py +50 -0
  29. ascript/windows/resources/templates/windows/pyproject.toml +44 -0
  30. ascript/windows/resources/templates/windows/res/img/logo.ico +0 -0
  31. ascript/windows/screen/__init__.py +13 -0
  32. ascript/windows/screen/as_cv.py +382 -0
  33. ascript/windows/screen/canny.py +128 -0
  34. ascript/windows/screen/code_scanner.py +72 -0
  35. ascript/windows/screen/color_algorithms.py +277 -0
  36. ascript/windows/screen/find_colors.py +251 -0
  37. ascript/windows/screen/find_images.py +217 -0
  38. ascript/windows/screen/ocr/__init__.py +4 -0
  39. ascript/windows/screen/ocr/ocr.py +223 -0
  40. ascript/windows/screen/ocr/rapidocr_hook.py +301 -0
  41. ascript/windows/screen/ocrx.py +169 -0
  42. ascript/windows/screen/screen_core.py +139 -0
  43. ascript/windows/store/__init__.py +21 -0
  44. ascript/windows/system/__init__.py +8 -0
  45. ascript/windows/system/device.py +355 -0
  46. ascript/windows/system/easy_print.py +115 -0
  47. ascript/windows/system/env.py +492 -0
  48. ascript/windows/system/exception/__init__.py +1 -0
  49. ascript/windows/system/key_value.py +145 -0
  50. ascript/windows/system/pip.py +175 -0
  51. ascript/windows/system/r.py +165 -0
  52. ascript/windows/system/runtime.py +62 -0
  53. ascript/windows/tools/__init__.py +27 -0
  54. ascript/windows/tools/__main__.py +21 -0
  55. ascript/windows/tools/action.json +33 -0
  56. ascript/windows/tools/action.py +168 -0
  57. ascript/windows/tools/colors_tool.py +391 -0
  58. ascript/windows/tools/config.py +26 -0
  59. ascript/windows/tools/dumptool.py +18 -0
  60. ascript/windows/tools/eel_api.py +495 -0
  61. ascript/windows/tools/gpplug/__init__.py +0 -0
  62. ascript/windows/tools/gpplug/plug.py +70 -0
  63. ascript/windows/tools/mouse_catch.py +168 -0
  64. ascript/windows/tools/plug_manager.py +38 -0
  65. ascript/windows/tools/tool_api.py +906 -0
  66. ascript/windows/tools/tool_window.py +56 -0
  67. ascript/windows/tools/uia_worker.py +365 -0
  68. ascript/windows/tools/web/app_store_window.html +481 -0
  69. ascript/windows/tools/web/colors.html +532 -0
  70. ascript/windows/tools/web/css/screen.css +1342 -0
  71. ascript/windows/tools/web/css/viewtree.css +357 -0
  72. ascript/windows/tools/web/flot_control.html +195 -0
  73. ascript/windows/tools/web/img/ico/favicon.png +0 -0
  74. ascript/windows/tools/web/img/ico/paintpalette.png +0 -0
  75. ascript/windows/tools/web/img/svg/find_colors.svg +1 -0
  76. ascript/windows/tools/web/img/svg/find_images.svg +1 -0
  77. ascript/windows/tools/web/img/svg/illustration-6.svg +89 -0
  78. ascript/windows/tools/web/img/svg/img_default.svg +1 -0
  79. ascript/windows/tools/web/img/svg/ocr.svg +1 -0
  80. ascript/windows/tools/web/js/screen/colors.js +466 -0
  81. ascript/windows/tools/web/js/screen/gp_plug.js +108 -0
  82. ascript/windows/tools/web/js/screen/image_mouse.js +464 -0
  83. ascript/windows/tools/web/js/screen/img_view.js +558 -0
  84. ascript/windows/tools/web/js/screen/plug.js +246 -0
  85. ascript/windows/tools/web/js/screen/screen.js +690 -0
  86. ascript/windows/tools/web/js/screen/screen_api.js +778 -0
  87. ascript/windows/tools/web/js/screen/screen_maker.js +10 -0
  88. ascript/windows/tools/web/js/utils/map.js +73 -0
  89. ascript/windows/tools/web/js/utils/upload.js +157 -0
  90. ascript/windows/tools/web/js/viewtree/niv_js.js +27 -0
  91. ascript/windows/tools/web/js/viewtree/vtree.js +1510 -0
  92. ascript/windows/tools/web/libs/bootstrap/css/bootstrap.min.css +6 -0
  93. ascript/windows/tools/web/libs/bootstrap/js/bootstrap.bundle.min.js +7 -0
  94. ascript/windows/tools/web/libs/bootstrap-icons/0-circle.svg +4 -0
  95. ascript/windows/tools/web/libs/bootstrap-icons/0-square.svg +4 -0
  96. ascript/windows/tools/web/libs/bootstrap-icons/font/bootstrap-icons.css +2078 -0
  97. ascript/windows/tools/web/libs/bootstrap-icons/font/bootstrap-icons.json +2052 -0
  98. ascript/windows/tools/web/libs/bootstrap-icons/font/bootstrap-icons.min.css +5 -0
  99. ascript/windows/tools/web/libs/bootstrap-icons/font/bootstrap-icons.scss +2090 -0
  100. ascript/windows/tools/web/libs/bootstrap-icons/font/fonts/bootstrap-icons.woff +0 -0
  101. ascript/windows/tools/web/libs/bootstrap-icons/font/fonts/bootstrap-icons.woff2 +0 -0
  102. ascript/windows/tools/web/libs/feather-icons/dist/feather.min.js +13 -0
  103. ascript/windows/tools/web/libs/feather-icons/dist/icons.json +1 -0
  104. ascript/windows/tools/web/libs/jquery/core.js +399 -0
  105. ascript/windows/tools/web/libs/jquery/jquery.js +10598 -0
  106. ascript/windows/tools/web/libs/jquery/jquery.min.js +4 -0
  107. ascript/windows/tools/web/libs/jquery/jquery.min.js.zip +0 -0
  108. ascript/windows/tools/web/libs/jquery/jquery.slim.js +8495 -0
  109. ascript/windows/tools/web/libs/jquery/jquery.slim.min.js +2 -0
  110. ascript/windows/tools/web/libs/jquery-menu/jquery.contextMenu.js +2134 -0
  111. ascript/windows/tools/web/libs/jquery-menu/jquery.contextMenu.min.css +16 -0
  112. ascript/windows/tools/web/libs/jquery-zTree/css/zTreeStyle.css +97 -0
  113. ascript/windows/tools/web/libs/jquery-zTree/img/diy/1_close.png +0 -0
  114. ascript/windows/tools/web/libs/jquery-zTree/img/diy/1_open.png +0 -0
  115. ascript/windows/tools/web/libs/jquery-zTree/img/diy/2.png +0 -0
  116. ascript/windows/tools/web/libs/jquery-zTree/img/diy/3.png +0 -0
  117. ascript/windows/tools/web/libs/jquery-zTree/img/diy/4.png +0 -0
  118. ascript/windows/tools/web/libs/jquery-zTree/img/diy/5.png +0 -0
  119. ascript/windows/tools/web/libs/jquery-zTree/img/diy/6.png +0 -0
  120. ascript/windows/tools/web/libs/jquery-zTree/img/diy/7.png +0 -0
  121. ascript/windows/tools/web/libs/jquery-zTree/img/diy/8.png +0 -0
  122. ascript/windows/tools/web/libs/jquery-zTree/img/diy/9.png +0 -0
  123. ascript/windows/tools/web/libs/jquery-zTree/img/line_conn.gif +0 -0
  124. ascript/windows/tools/web/libs/jquery-zTree/img/loading.gif +0 -0
  125. ascript/windows/tools/web/libs/jquery-zTree/img/tree-node-btn.png +0 -0
  126. ascript/windows/tools/web/libs/jquery-zTree/img/zTreeStandard.gif +0 -0
  127. ascript/windows/tools/web/libs/jquery-zTree/img/zTreeStandard.png +0 -0
  128. ascript/windows/tools/web/libs/jquery-zTree/js/jquery.ztree.all.min.js +3 -0
  129. ascript/windows/tools/web/libs/treeview/css/jquery.treeview.css +79 -0
  130. ascript/windows/tools/web/libs/treeview/img/file.png +0 -0
  131. ascript/windows/tools/web/libs/treeview/img/ico_loading.png +0 -0
  132. ascript/windows/tools/web/libs/treeview/img/icon4.png +0 -0
  133. ascript/windows/tools/web/libs/treeview/img/icon5.png +0 -0
  134. ascript/windows/tools/web/libs/treeview/img/icon6.png +0 -0
  135. ascript/windows/tools/web/libs/treeview/img/py.png +0 -0
  136. ascript/windows/tools/web/libs/treeview/img/treeview-black-line.gif +0 -0
  137. ascript/windows/tools/web/libs/treeview/img/treeview-black.gif +0 -0
  138. ascript/windows/tools/web/libs/treeview/img/treeview-default-line.gif +0 -0
  139. ascript/windows/tools/web/libs/treeview/img/treeview-default.gif +0 -0
  140. ascript/windows/tools/web/libs/treeview/img/treeview-famfamfam-line.gif +0 -0
  141. ascript/windows/tools/web/libs/treeview/img/treeview-famfamfam.gif +0 -0
  142. ascript/windows/tools/web/libs/treeview/img/treeview-gray-line.gif +0 -0
  143. ascript/windows/tools/web/libs/treeview/img/treeview-gray.gif +0 -0
  144. ascript/windows/tools/web/libs/treeview/img/treeview-red-line.gif +0 -0
  145. ascript/windows/tools/web/libs/treeview/img/treeview-red.gif +0 -0
  146. ascript/windows/tools/web/libs/treeview/js/jquery.treeview.edit.js +37 -0
  147. ascript/windows/tools/web/libs/treeview/js/jquery.treeview.js +250 -0
  148. ascript/windows/tools/web/license_window.html +255 -0
  149. ascript/windows/tools/web/plugs/a.html +653 -0
  150. ascript/windows/tools/web/plugs/demo.html +52 -0
  151. ascript/windows/tools/web/plugs/find_colors.html +629 -0
  152. ascript/windows/tools/web/plugs/find_images.html +699 -0
  153. ascript/windows/tools/web/plugs/rapidocr.html +954 -0
  154. ascript/windows/tools/web/vtree.html +496 -0
  155. ascript/windows/tools/webview/assets/index-HymBPl-I.css +1 -0
  156. ascript/windows/tools/webview/assets/index-PqA_m8tL.js +17 -0
  157. ascript/windows/tools/webview/index.html +13 -0
  158. ascript/windows/ui/__init__.py +6 -0
  159. ascript/windows/ui/app_store_window.py +272 -0
  160. ascript/windows/ui/draw_window.py +231 -0
  161. ascript/windows/ui/flot_test.py +297 -0
  162. ascript/windows/ui/flot_window.py +488 -0
  163. ascript/windows/ui/license_window.py +111 -0
  164. ascript/windows/ui/web_window.py +466 -0
  165. ascript/windows/utils/__init__.py +0 -0
  166. ascript/windows/utils/node_utils.py +20 -0
  167. ascript/windows/utils/screen_utils.py +280 -0
  168. ascript/windows/window/Selector.py +1015 -0
  169. ascript/windows/window/Window.py +747 -0
  170. ascript/windows/window/__init__.py +5 -0
  171. ascript/windows/window/launcher.py +213 -0
  172. ascript/windows/window/uia_runtime.py +26 -0
  173. ascript-1.3.27.dist-info/METADATA +41 -0
  174. ascript-1.3.27.dist-info/RECORD +177 -0
  175. ascript-1.3.27.dist-info/WHEEL +5 -0
  176. ascript-1.3.27.dist-info/entry_points.txt +2 -0
  177. ascript-1.3.27.dist-info/top_level.txt +1 -0
@@ -0,0 +1,297 @@
1
+ import webview
2
+ import os
3
+ import threading
4
+ import pystray
5
+ import base64
6
+ import ctypes
7
+ import time
8
+ from PIL import Image
9
+ from typing import Optional, Callable
10
+
11
+ # --- 1. 环境补丁:拦截 AccessibilityObject 导致的递归报错 ---
12
+ os.environ['WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS'] = '--disable-features=AccessibilityObjectModel --disable-gpu'
13
+
14
+ # --- 2. Windows 窗口样式常量 ---
15
+ GWL_EXSTYLE = -20
16
+ WS_EX_TOOLWINDOW = 0x00000080 # 工具窗口样式(不在任务栏显示)
17
+ WS_EX_APPWINDOW = 0x00040000 # 应用程序窗口样式(我们要移除它)
18
+
19
+ # ---------------- HTML & CSS (满铺直角 + 悬浮交互) ----------------
20
+ HTML_CONTENT = """
21
+ <!DOCTYPE html>
22
+ <html>
23
+ <head>
24
+ <style>
25
+ * { box-sizing: border-box; }
26
+ html, body {
27
+ margin: 0; padding: 0; width: 100%; height: 100%;
28
+ overflow: hidden; background-color: #1a1a1a;
29
+ display: flex; align-items: center; user-select: none;
30
+ }
31
+ .full-bar {
32
+ width: 100%; height: 100%;
33
+ display: flex; align-items: center;
34
+ padding: 0 8px; border: 1px solid #333;
35
+ cursor: move; position: relative;
36
+ }
37
+ /* 唱片容器 */
38
+ .disk-box {
39
+ width: 36px; height: 36px;
40
+ flex-shrink: 0; position: relative;
41
+ background: #000; border-radius: 50%;
42
+ overflow: hidden; border: 1px solid #444;
43
+ }
44
+ #disk { width: 100%; height: 100%; object-fit: cover; transition: transform 0.6s ease-out; }
45
+ /* 悬浮覆盖层:播放/停止按钮 */
46
+ .disk-overlay {
47
+ position: absolute; top: 0; left: 0; width: 100%; height: 100%;
48
+ background: rgba(0,0,0,0.6); display: flex; align-items: center; justify-content: center;
49
+ opacity: 0; transition: opacity 0.2s; cursor: pointer;
50
+ -webkit-app-region: no-drag;
51
+ }
52
+ .disk-box:hover .disk-overlay { opacity: 1; }
53
+ .btn-icon { width: 20px; height: 20px; fill: white; }
54
+ /* 状态文本 */
55
+ .info {
56
+ color: #eeeeee; font-size: 12px; font-family: "微软雅黑", sans-serif;
57
+ margin-left: 10px; font-weight: bold; flex-grow: 1;
58
+ }
59
+ /* 隐藏按钮 */
60
+ .hide-btn {
61
+ width: 24px; height: 24px; display: flex; align-items: center; justify-content: center;
62
+ border-radius: 4px; color: #666; cursor: pointer;
63
+ transition: all 0.2s; -webkit-app-region: no-drag;
64
+ opacity: 0;
65
+ }
66
+ .full-bar:hover .hide-btn { opacity: 1; }
67
+ .hide-btn:hover { background: #444; color: white; }
68
+ /* 指示灯 */
69
+ .led { width: 4px; height: 20px; background: #333; margin-left: 8px; }
70
+ .is-active .led { background: #00ff88; box-shadow: -2px 0 8px rgba(0, 255, 136, 0.4); }
71
+ </style>
72
+ </head>
73
+ <body onmousedown="handleMouseDown(event)">
74
+ <div class="full-bar" id="mainBar">
75
+ <div class="disk-box">
76
+ <img id="disk" src="data:image/png;base64,{base64_data}">
77
+ <div class="disk-overlay" onclick="toggleStatus(event)">
78
+ <svg id="playIcon" class="btn-icon" viewBox="0 0 24 24"><path d="M8 5v14l11-7z"/></svg>
79
+ <svg id="stopIcon" class="btn-icon" viewBox="0 0 24 24" style="display:none;"><path d="M6 6h12v12H6z"/></svg>
80
+ </div>
81
+ </div>
82
+ <div class="info" id="statusText">READY</div>
83
+ <div class="hide-btn" onclick="hideToTray(event)" title="隐藏到托盘">
84
+ <svg class="btn-icon" style="width:16px; height:16px;" viewBox="0 0 24 24"><path d="M19 13H5v-2h14v2z"/></svg>
85
+ </div>
86
+ <div class="led" id="ledIndicator"></div>
87
+ </div>
88
+ <script>
89
+ let running = false;
90
+ let currentAngle = 0;
91
+ let animationId = null;
92
+ const disk = document.getElementById('disk');
93
+ const mainBar = document.getElementById('mainBar');
94
+ const statusText = document.getElementById('statusText');
95
+
96
+ function rotateStep() {
97
+ if (!running) return;
98
+ currentAngle = (currentAngle + 4) % 360;
99
+ disk.style.transform = `rotate(${currentAngle}deg)`;
100
+ animationId = requestAnimationFrame(rotateStep);
101
+ }
102
+
103
+ function toggleStatus(e) {
104
+ e.stopPropagation();
105
+ running = !running;
106
+ const play = document.getElementById('playIcon');
107
+ const stop = document.getElementById('stopIcon');
108
+ if (running) {
109
+ mainBar.classList.add('is-active');
110
+ statusText.innerText = 'RUNNING';
111
+ statusText.style.color = '#00ff88';
112
+ play.style.display = 'none';
113
+ stop.style.display = 'block';
114
+ disk.style.transition = 'none';
115
+ rotateStep();
116
+ } else {
117
+ mainBar.classList.remove('is-active');
118
+ statusText.innerText = 'STOPPED';
119
+ statusText.style.color = '#eeeeee';
120
+ play.style.display = 'block';
121
+ stop.style.display = 'none';
122
+ cancelAnimationFrame(animationId);
123
+ disk.style.transition = 'transform 0.6s ease-out';
124
+ disk.style.transform = 'rotate(0deg)';
125
+ currentAngle = 0;
126
+ }
127
+ window.pywebview.api.on_toggle(running);
128
+ }
129
+
130
+ function hideToTray(e) {
131
+ e.stopPropagation();
132
+ window.pywebview.api.hide_window();
133
+ }
134
+
135
+ function handleMouseDown(e) {
136
+ if (e.target.id === 'mainBar' || e.target.id === 'statusText') {
137
+ window.pywebview.api.start_drag();
138
+ }
139
+ }
140
+ </script>
141
+ </body>
142
+ </html>
143
+ """
144
+
145
+
146
+ class Api:
147
+ """WebView 窗口的 JavaScript API 桥接类。
148
+
149
+ 提供前端 JS 可调用的 Python 方法,包括状态切换回调、窗口拖拽和隐藏功能。
150
+ """
151
+
152
+ def __init__(self):
153
+ """初始化 API 桥接对象。"""
154
+ self.status_callback = None
155
+ self.window = None
156
+
157
+ def on_toggle(self, status):
158
+ """处理播放/停止状态切换事件。
159
+
160
+ Args:
161
+ status: 当前运行状态,True 表示运行中,False 表示已停止。
162
+ """
163
+ if self.status_callback:
164
+ self.status_callback(status)
165
+
166
+ def start_drag(self):
167
+ """启动窗口拖拽操作。"""
168
+ if self.window: self.window.move_window()
169
+
170
+ def hide_window(self):
171
+ """隐藏窗口到系统托盘。"""
172
+ if self.window: self.window.hide()
173
+
174
+
175
+ class RecordPlayer:
176
+ """唱片机风格的浮动控制面板。
177
+
178
+ 提供一个无边框、置顶的迷你窗口,带有唱片旋转动画效果,
179
+ 支持播放/停止控制、系统托盘集成和窗口拖拽。
180
+ """
181
+
182
+ def __init__(self, icon_path: str):
183
+ """初始化唱片机控制面板。
184
+
185
+ Args:
186
+ icon_path: 图标文件路径,用于窗口内唱片图片和系统托盘图标。
187
+ """
188
+ # 支持根目录初始化 [cite: 2026-01-20]
189
+ self.icon_path = os.path.abspath(icon_path)
190
+ self.api = Api()
191
+ self.tray = None
192
+
193
+ def listen(self, callback: Callable[[bool], None]):
194
+ """注册状态变化的监听回调。
195
+
196
+ Args:
197
+ callback: 回调函数,接收一个 bool 参数表示当前运行状态。
198
+ """
199
+ self.api.status_callback = callback
200
+
201
+ def _get_base64(self):
202
+ """读取图标文件并转换为 Base64 编码字符串。
203
+
204
+ Returns:
205
+ str: 图标文件的 Base64 编码字符串。
206
+ """
207
+ with open(self.icon_path, "rb") as f:
208
+ return base64.b64encode(f.read()).decode('utf-8')
209
+
210
+ def _fix_taskbar(self):
211
+ """通过 Win32 API 从任务栏移除窗口图标。
212
+
213
+ 循环查找窗口句柄,找到后修改扩展样式为工具窗口,
214
+ 移除 AppWindow 属性以隐藏任务栏图标。
215
+ """
216
+ while True:
217
+ # 循环查找直到窗口句柄被创建
218
+ hwnd = ctypes.windll.user32.FindWindowW(None, 'ControlPanel')
219
+ if hwnd:
220
+ style = ctypes.windll.user32.GetWindowLongW(hwnd, GWL_EXSTYLE)
221
+ # 关键:设置为工具窗口并移除 AppWindow 属性
222
+ new_style = (style | WS_EX_TOOLWINDOW) & ~WS_EX_APPWINDOW
223
+ ctypes.windll.user32.SetWindowLongW(hwnd, GWL_EXSTYLE, new_style)
224
+ # 刷新窗口,SWP_FRAMECHANGED = 0x0020
225
+ ctypes.windll.user32.SetWindowPos(hwnd, 0, 0, 0, 0, 0, 0x0020 | 0x0002 | 0x0001 | 0x0004)
226
+ break
227
+ time.sleep(0.1)
228
+
229
+ def _show_window(self, icon=None, item=None):
230
+ """显示主窗口。
231
+
232
+ Args:
233
+ icon: 系统托盘图标对象(由 pystray 回调传入,可选)。
234
+ item: 菜单项对象(由 pystray 回调传入,可选)。
235
+ """
236
+ if self.api.window:
237
+ self.api.window.show()
238
+
239
+ def _quit_app(self, icon, item):
240
+ """退出应用程序。
241
+
242
+ 停止系统托盘图标并强制终止进程。
243
+
244
+ Args:
245
+ icon: 系统托盘图标对象。
246
+ item: 菜单项对象。
247
+ """
248
+ icon.stop()
249
+ os._exit(0)
250
+
251
+ def _setup_tray(self):
252
+ """初始化并启动系统托盘图标。
253
+
254
+ 创建包含"显示控制栏"和"彻底退出"菜单项的系统托盘图标。
255
+ """
256
+ image = Image.open(self.icon_path)
257
+ menu = pystray.Menu(
258
+ pystray.MenuItem("显示控制栏", self._show_window, default=True),
259
+ pystray.MenuItem("彻底退出", self._quit_app)
260
+ )
261
+ self.tray = pystray.Icon("ControlWidget", image, "脚本控制中心", menu)
262
+ self.tray.on_activate = self._show_window
263
+ self.tray.run()
264
+
265
+ def run(self):
266
+ """启动唱片机控制面板。
267
+
268
+ 创建无边框置顶 WebView 窗口,启动系统托盘和任务栏隐藏补丁,
269
+ 并进入 WebView 事件循环。此方法会阻塞当前线程。
270
+ """
271
+ b64_data = self._get_base64()
272
+ full_html = HTML_CONTENT.replace("{base64_data}", b64_data)
273
+
274
+ self.api.window = webview.create_window(
275
+ 'ControlPanel', # 标题需与 _fix_taskbar 一致
276
+ html=full_html,
277
+ js_api=self.api,
278
+ width=180, height=52,
279
+ frameless=True,
280
+ on_top=True,
281
+ resizable=False,
282
+ background_color='#1a1a1a'
283
+ )
284
+
285
+ # 启动托盘
286
+ threading.Thread(target=self._setup_tray, daemon=True).start()
287
+ # 启动任务栏消除补丁线程
288
+ threading.Thread(target=self._fix_taskbar, daemon=True).start()
289
+
290
+ webview.start(gui='edgechromium', debug=False)
291
+
292
+
293
+ if __name__ == "__main__":
294
+ # 确保你的根目录有 logo.png
295
+ player = RecordPlayer("logo.png")
296
+ player.listen(lambda s: print(f"【外部监听到状态】: {s}"))
297
+ player.run()