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.
- ascript/__init__.py +8 -0
- ascript/hooks/__init__.py +0 -0
- ascript/hooks/hook-ascript.py +2 -0
- ascript/windows/__init__.py +29 -0
- ascript/windows/daos/__init__.py +0 -0
- ascript/windows/daos/screen.py +143 -0
- ascript/windows/hardware/__init__.py +5 -0
- ascript/windows/hardware/keyboard.py +279 -0
- ascript/windows/hardware/logitech_driver.py +179 -0
- ascript/windows/hardware/mouse.py +308 -0
- ascript/windows/license/__init__.py +16 -0
- ascript/windows/license/achttp.cp310-win_amd64.pyd +0 -0
- ascript/windows/license/achttp.cp311-win_amd64.pyd +0 -0
- ascript/windows/license/achttp.cp312-win_amd64.pyd +0 -0
- ascript/windows/license/achttp.cp313-win_amd64.pyd +0 -0
- ascript/windows/license/achttp.cp314-win_amd64.pyd +0 -0
- ascript/windows/license/achttp.cp38-win_amd64.pyd +0 -0
- ascript/windows/license/achttp.cp39-win_amd64.pyd +0 -0
- ascript/windows/media/__init__.py +0 -0
- ascript/windows/resources/__init__.py +0 -0
- ascript/windows/resources/libs/logitech/x64/LogitechGkeyEnginesWrapper.dll +0 -0
- ascript/windows/resources/libs/logitech/x86/LogitechGkeyEnginesWrapper.dll +0 -0
- ascript/windows/resources/templates/__init__.py +0 -0
- ascript/windows/resources/templates/__init__py.win.template +51 -0
- ascript/windows/resources/templates/build.as.win.template +14 -0
- ascript/windows/resources/templates/build.py +71 -0
- ascript/windows/resources/templates/logo_windows.ico +0 -0
- ascript/windows/resources/templates/windows/main.py +50 -0
- ascript/windows/resources/templates/windows/pyproject.toml +44 -0
- ascript/windows/resources/templates/windows/res/img/logo.ico +0 -0
- ascript/windows/screen/__init__.py +13 -0
- ascript/windows/screen/as_cv.py +382 -0
- ascript/windows/screen/canny.py +128 -0
- ascript/windows/screen/code_scanner.py +72 -0
- ascript/windows/screen/color_algorithms.py +277 -0
- ascript/windows/screen/find_colors.py +251 -0
- ascript/windows/screen/find_images.py +217 -0
- ascript/windows/screen/ocr/__init__.py +4 -0
- ascript/windows/screen/ocr/ocr.py +223 -0
- ascript/windows/screen/ocr/rapidocr_hook.py +301 -0
- ascript/windows/screen/ocrx.py +169 -0
- ascript/windows/screen/screen_core.py +139 -0
- ascript/windows/store/__init__.py +21 -0
- ascript/windows/system/__init__.py +8 -0
- ascript/windows/system/device.py +355 -0
- ascript/windows/system/easy_print.py +115 -0
- ascript/windows/system/env.py +492 -0
- ascript/windows/system/exception/__init__.py +1 -0
- ascript/windows/system/key_value.py +145 -0
- ascript/windows/system/pip.py +175 -0
- ascript/windows/system/r.py +165 -0
- ascript/windows/system/runtime.py +62 -0
- ascript/windows/tools/__init__.py +27 -0
- ascript/windows/tools/__main__.py +21 -0
- ascript/windows/tools/action.json +33 -0
- ascript/windows/tools/action.py +168 -0
- ascript/windows/tools/colors_tool.py +391 -0
- ascript/windows/tools/config.py +26 -0
- ascript/windows/tools/dumptool.py +18 -0
- ascript/windows/tools/eel_api.py +495 -0
- ascript/windows/tools/gpplug/__init__.py +0 -0
- ascript/windows/tools/gpplug/plug.py +70 -0
- ascript/windows/tools/mouse_catch.py +168 -0
- ascript/windows/tools/plug_manager.py +38 -0
- ascript/windows/tools/tool_api.py +906 -0
- ascript/windows/tools/tool_window.py +56 -0
- ascript/windows/tools/uia_worker.py +365 -0
- ascript/windows/tools/web/app_store_window.html +481 -0
- ascript/windows/tools/web/colors.html +532 -0
- ascript/windows/tools/web/css/screen.css +1342 -0
- ascript/windows/tools/web/css/viewtree.css +357 -0
- ascript/windows/tools/web/flot_control.html +195 -0
- ascript/windows/tools/web/img/ico/favicon.png +0 -0
- ascript/windows/tools/web/img/ico/paintpalette.png +0 -0
- ascript/windows/tools/web/img/svg/find_colors.svg +1 -0
- ascript/windows/tools/web/img/svg/find_images.svg +1 -0
- ascript/windows/tools/web/img/svg/illustration-6.svg +89 -0
- ascript/windows/tools/web/img/svg/img_default.svg +1 -0
- ascript/windows/tools/web/img/svg/ocr.svg +1 -0
- ascript/windows/tools/web/js/screen/colors.js +466 -0
- ascript/windows/tools/web/js/screen/gp_plug.js +108 -0
- ascript/windows/tools/web/js/screen/image_mouse.js +464 -0
- ascript/windows/tools/web/js/screen/img_view.js +558 -0
- ascript/windows/tools/web/js/screen/plug.js +246 -0
- ascript/windows/tools/web/js/screen/screen.js +690 -0
- ascript/windows/tools/web/js/screen/screen_api.js +778 -0
- ascript/windows/tools/web/js/screen/screen_maker.js +10 -0
- ascript/windows/tools/web/js/utils/map.js +73 -0
- ascript/windows/tools/web/js/utils/upload.js +157 -0
- ascript/windows/tools/web/js/viewtree/niv_js.js +27 -0
- ascript/windows/tools/web/js/viewtree/vtree.js +1510 -0
- ascript/windows/tools/web/libs/bootstrap/css/bootstrap.min.css +6 -0
- ascript/windows/tools/web/libs/bootstrap/js/bootstrap.bundle.min.js +7 -0
- ascript/windows/tools/web/libs/bootstrap-icons/0-circle.svg +4 -0
- ascript/windows/tools/web/libs/bootstrap-icons/0-square.svg +4 -0
- ascript/windows/tools/web/libs/bootstrap-icons/font/bootstrap-icons.css +2078 -0
- ascript/windows/tools/web/libs/bootstrap-icons/font/bootstrap-icons.json +2052 -0
- ascript/windows/tools/web/libs/bootstrap-icons/font/bootstrap-icons.min.css +5 -0
- ascript/windows/tools/web/libs/bootstrap-icons/font/bootstrap-icons.scss +2090 -0
- ascript/windows/tools/web/libs/bootstrap-icons/font/fonts/bootstrap-icons.woff +0 -0
- ascript/windows/tools/web/libs/bootstrap-icons/font/fonts/bootstrap-icons.woff2 +0 -0
- ascript/windows/tools/web/libs/feather-icons/dist/feather.min.js +13 -0
- ascript/windows/tools/web/libs/feather-icons/dist/icons.json +1 -0
- ascript/windows/tools/web/libs/jquery/core.js +399 -0
- ascript/windows/tools/web/libs/jquery/jquery.js +10598 -0
- ascript/windows/tools/web/libs/jquery/jquery.min.js +4 -0
- ascript/windows/tools/web/libs/jquery/jquery.min.js.zip +0 -0
- ascript/windows/tools/web/libs/jquery/jquery.slim.js +8495 -0
- ascript/windows/tools/web/libs/jquery/jquery.slim.min.js +2 -0
- ascript/windows/tools/web/libs/jquery-menu/jquery.contextMenu.js +2134 -0
- ascript/windows/tools/web/libs/jquery-menu/jquery.contextMenu.min.css +16 -0
- ascript/windows/tools/web/libs/jquery-zTree/css/zTreeStyle.css +97 -0
- ascript/windows/tools/web/libs/jquery-zTree/img/diy/1_close.png +0 -0
- ascript/windows/tools/web/libs/jquery-zTree/img/diy/1_open.png +0 -0
- ascript/windows/tools/web/libs/jquery-zTree/img/diy/2.png +0 -0
- ascript/windows/tools/web/libs/jquery-zTree/img/diy/3.png +0 -0
- ascript/windows/tools/web/libs/jquery-zTree/img/diy/4.png +0 -0
- ascript/windows/tools/web/libs/jquery-zTree/img/diy/5.png +0 -0
- ascript/windows/tools/web/libs/jquery-zTree/img/diy/6.png +0 -0
- ascript/windows/tools/web/libs/jquery-zTree/img/diy/7.png +0 -0
- ascript/windows/tools/web/libs/jquery-zTree/img/diy/8.png +0 -0
- ascript/windows/tools/web/libs/jquery-zTree/img/diy/9.png +0 -0
- ascript/windows/tools/web/libs/jquery-zTree/img/line_conn.gif +0 -0
- ascript/windows/tools/web/libs/jquery-zTree/img/loading.gif +0 -0
- ascript/windows/tools/web/libs/jquery-zTree/img/tree-node-btn.png +0 -0
- ascript/windows/tools/web/libs/jquery-zTree/img/zTreeStandard.gif +0 -0
- ascript/windows/tools/web/libs/jquery-zTree/img/zTreeStandard.png +0 -0
- ascript/windows/tools/web/libs/jquery-zTree/js/jquery.ztree.all.min.js +3 -0
- ascript/windows/tools/web/libs/treeview/css/jquery.treeview.css +79 -0
- ascript/windows/tools/web/libs/treeview/img/file.png +0 -0
- ascript/windows/tools/web/libs/treeview/img/ico_loading.png +0 -0
- ascript/windows/tools/web/libs/treeview/img/icon4.png +0 -0
- ascript/windows/tools/web/libs/treeview/img/icon5.png +0 -0
- ascript/windows/tools/web/libs/treeview/img/icon6.png +0 -0
- ascript/windows/tools/web/libs/treeview/img/py.png +0 -0
- ascript/windows/tools/web/libs/treeview/img/treeview-black-line.gif +0 -0
- ascript/windows/tools/web/libs/treeview/img/treeview-black.gif +0 -0
- ascript/windows/tools/web/libs/treeview/img/treeview-default-line.gif +0 -0
- ascript/windows/tools/web/libs/treeview/img/treeview-default.gif +0 -0
- ascript/windows/tools/web/libs/treeview/img/treeview-famfamfam-line.gif +0 -0
- ascript/windows/tools/web/libs/treeview/img/treeview-famfamfam.gif +0 -0
- ascript/windows/tools/web/libs/treeview/img/treeview-gray-line.gif +0 -0
- ascript/windows/tools/web/libs/treeview/img/treeview-gray.gif +0 -0
- ascript/windows/tools/web/libs/treeview/img/treeview-red-line.gif +0 -0
- ascript/windows/tools/web/libs/treeview/img/treeview-red.gif +0 -0
- ascript/windows/tools/web/libs/treeview/js/jquery.treeview.edit.js +37 -0
- ascript/windows/tools/web/libs/treeview/js/jquery.treeview.js +250 -0
- ascript/windows/tools/web/license_window.html +255 -0
- ascript/windows/tools/web/plugs/a.html +653 -0
- ascript/windows/tools/web/plugs/demo.html +52 -0
- ascript/windows/tools/web/plugs/find_colors.html +629 -0
- ascript/windows/tools/web/plugs/find_images.html +699 -0
- ascript/windows/tools/web/plugs/rapidocr.html +954 -0
- ascript/windows/tools/web/vtree.html +496 -0
- ascript/windows/tools/webview/assets/index-HymBPl-I.css +1 -0
- ascript/windows/tools/webview/assets/index-PqA_m8tL.js +17 -0
- ascript/windows/tools/webview/index.html +13 -0
- ascript/windows/ui/__init__.py +6 -0
- ascript/windows/ui/app_store_window.py +272 -0
- ascript/windows/ui/draw_window.py +231 -0
- ascript/windows/ui/flot_test.py +297 -0
- ascript/windows/ui/flot_window.py +488 -0
- ascript/windows/ui/license_window.py +111 -0
- ascript/windows/ui/web_window.py +466 -0
- ascript/windows/utils/__init__.py +0 -0
- ascript/windows/utils/node_utils.py +20 -0
- ascript/windows/utils/screen_utils.py +280 -0
- ascript/windows/window/Selector.py +1015 -0
- ascript/windows/window/Window.py +747 -0
- ascript/windows/window/__init__.py +5 -0
- ascript/windows/window/launcher.py +213 -0
- ascript/windows/window/uia_runtime.py +26 -0
- ascript-1.3.27.dist-info/METADATA +41 -0
- ascript-1.3.27.dist-info/RECORD +177 -0
- ascript-1.3.27.dist-info/WHEEL +5 -0
- ascript-1.3.27.dist-info/entry_points.txt +2 -0
- 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()
|