优化更新

This commit is contained in:
2026-09-23 16:51:40 +08:00
parent cd4ffbfa90
commit 68e8eb91a7
15 changed files with 1858 additions and 193 deletions
+335 -110
View File
@@ -21,7 +21,6 @@ from PyQt6.QtWidgets import (
QLineEdit,
QLabel,
QMessageBox,
QGridLayout,
QFrame,
)
from PyQt6.QtCore import (
@@ -178,8 +177,6 @@ class WeatherBox(QWidget):
lay.addWidget(self._left_widget)
lay.addWidget(self._right_widget)
self._last_tooltip: str | None = None
def set_theme_colors(self, color_fg: str):
self._temp_label.setStyleSheet(
f"font-weight:900; font-size:28px; color:{color_fg}; background:transparent; padding:0px; margin:0px;"
@@ -264,7 +261,6 @@ class WeatherBox(QWidget):
self._weather_name_label.setText("获取中…")
self._location_label.setText("")
self._wind_label.setText("")
self._last_tooltip = None
def _make_tray_icon():
@@ -410,16 +406,32 @@ class PanelWindow(QWidget):
self._weather_fetching = False
self._time_base_utc_ts: float = 0.0
self._time_mono_base: float = 0.0
# 默认按中国时区(大概率与你的 IP 定位一致);后续会在天气接口返回后修正
self._tz_offset_sec: int = 8 * 3600
# 默认取本机系统时区;天气接口仅用于定位参考,不再反向改写时区
try:
self._tz_offset_sec: int = int(
datetime.datetime.now().astimezone().utcoffset().total_seconds()
)
except Exception:
self._tz_offset_sec = 8 * 3600
self._time_timer = QTimer(self)
self._time_timer.setInterval(1000)
self._time_timer.timeout.connect(self._refresh_time_label)
self._updater = Updater(self)
self._dock_state = "none"
self._is_collapsed = False
self._is_hiding = False
self._temp_disable_collapse = False
self._dock_timer = QTimer(self)
self._dock_timer.setInterval(200)
self._dock_timer.timeout.connect(self._on_dock_timer_timeout)
self._dock_timer.start()
def showEvent(self, event):
super().showEvent(event)
self._apply_win32_blur(theme.name() == "dark")
if not self._screen_hooked:
wh = self.windowHandle()
if wh is not None:
@@ -478,17 +490,8 @@ class PanelWindow(QWidget):
return
self.weather_box.update_weather(data)
self._weather_fetching = False
# 用 weather 接口返回的 adcode(由 IP 自动定位)推断时区偏移
# 目前你的接口数据基本为中国区(你给的示例 adcode=320706),中国全时区统一为 UTC+8
try:
adcode = data.get("adcode", "")
ad_str = str(adcode).strip()
if ad_str.isdigit() and len(ad_str) == 6:
self._tz_offset_sec = 8 * 3600
else:
self._tz_offset_sec = 0
except Exception:
self._tz_offset_sec = 8 * 3600
# 时区不再依赖天气接口(接口失败时旧逻辑会把时区清零,导致时间差 8 小时),
# 统一使用初始化时的系统时区。
if self._time_base_utc_ts > 0:
self._refresh_time_label()
@@ -511,7 +514,7 @@ class PanelWindow(QWidget):
delta_sec = _time.monotonic() - self._time_mono_base
utc_now = self._time_base_utc_ts + delta_sec
local_now = utc_now + self._tz_offset_sec
dt = datetime.datetime.utcfromtimestamp(local_now)
dt = datetime.datetime.fromtimestamp(local_now, tz=datetime.timezone.utc)
self.time_label.setText(dt.strftime("%H:%M:%S"))
self.time_date_label.setText(dt.strftime("%Y-%m-%d"))
@@ -573,6 +576,7 @@ class PanelWindow(QWidget):
("管理员运行 PowerShell", "fa5b.windows", self._open_admin_powershell),
("打开默认浏览器", "fa5s.globe", self._open_default_browser),
("解除占用", "fa5s.unlock", self._open_unlocker),
("硬件温度", "fa5s.thermometer-half", self._open_temperature),
]
def _build_ui(self):
@@ -674,6 +678,7 @@ class PanelWindow(QWidget):
self.weather_refresh_btn = QPushButton("刷新")
self.weather_refresh_btn.setFixedSize(24, 24)
self.weather_refresh_btn.setText("")
_install_themed_tooltip(self.weather_refresh_btn, "刷新天气")
self.weather_refresh_btn.setStyleSheet(
"border:none; background:transparent; border-radius:6px;"
)
@@ -718,8 +723,14 @@ class PanelWindow(QWidget):
search_row.setSpacing(6)
self.search_box = QLineEdit()
self.search_box.setPlaceholderText("🔍 搜索程序...")
self.search_box.setPlaceholderText("搜索程序...")
self.search_box.setClearButtonEnabled(True)
self.search_box.textChanged.connect(self._on_search)
# 前置搜索图标(随主题在 _apply_theme 中重新着色)
self._search_action = self.search_box.addAction(
qta.icon("fa5s.search", color="#888"),
QLineEdit.ActionPosition.LeadingPosition,
)
self.add_group_btn = QPushButton("添加分组")
self.add_group_btn.setFixedHeight(32)
@@ -823,12 +834,13 @@ class PanelWindow(QWidget):
ic = "#cccccc" if is_dark else "#555555"
self._apply_tooltip_theme(t, is_dark)
self._apply_win32_blur(is_dark)
self.container.setStyleSheet(
f"""
QWidget#container {{
background: {t['panel_bg']};
border-radius: 10px;
border-radius: 12px;
border: 1px solid {t['panel_border']};
}}
"""
@@ -859,6 +871,19 @@ class PanelWindow(QWidget):
"""
self.add_group_btn.setStyleSheet(txt_btn_style)
self.add_folder_btn.setStyleSheet(txt_btn_style)
# 文字按钮前置图标(随主题着色)
try:
self.add_group_btn.setIcon(qta.icon("fa5s.plus", color=ic))
self.add_group_btn.setIconSize(QSize(11, 11))
self.add_folder_btn.setIcon(qta.icon("fa5s.folder-plus", color=ic))
self.add_folder_btn.setIconSize(QSize(11, 11))
except Exception:
pass
# 搜索图标随主题着色
try:
self._search_action.setIcon(qta.icon("fa5s.search", color=ic))
except Exception:
pass
self.scroll.setStyleSheet(
f"""
QScrollArea {{ border:none; background:transparent; }}
@@ -874,6 +899,13 @@ class PanelWindow(QWidget):
self.pin_btn.setIconSize(QSize(13, 13))
self._min_btn.setIcon(qta.icon("fa5s.minus", color=ic))
self._min_btn.setIconSize(QSize(13, 13))
# 标题栏按钮悬停反馈
title_btn_style = (
f"QPushButton {{ border:none; background:transparent; border-radius:5px; }}"
f"QPushButton:hover {{ background:{t['header_hover']}; }}"
)
self.pin_btn.setStyleSheet(title_btn_style)
self._min_btn.setStyleSheet(title_btn_style)
self.app_title.setStyleSheet(
f"font-size:13px; font-weight:bold; background:transparent; color:{t['search_color']};"
)
@@ -883,7 +915,8 @@ class PanelWindow(QWidget):
self.weather_box.set_theme_colors(t["search_color"])
if hasattr(self, "weather_refresh_btn"):
self.weather_refresh_btn.setStyleSheet(
"border:none; background:transparent; border-radius:6px;"
f"QPushButton {{ border:none; background:transparent; border-radius:6px; }}"
f"QPushButton:hover {{ background:{t['header_hover']}; }}"
)
# 刷新按钮图标跟随主题颜色
try:
@@ -912,7 +945,7 @@ class PanelWindow(QWidget):
QWidget#quick_bar {{
background: {bar_side_bg};
border: 1px solid {t['panel_border']};
border-radius: 10px;
border-radius: 12px;
}}
QPushButton {{ border:none; background:transparent; border-radius:4px; }}
QPushButton:hover {{ background:{t['header_hover']}; }}
@@ -931,7 +964,7 @@ class PanelWindow(QWidget):
f"""
QWidget#bottom_bar {{
background: {bar_bg2};
border-radius: 0 0 10px 10px;
border-radius: 0 0 12px 12px;
border-top: 1px solid {t['panel_border']};
}}
QPushButton {{ border:none; background:transparent; border-radius:4px; }}
@@ -951,6 +984,10 @@ class PanelWindow(QWidget):
self.quit_btn.setIcon(qta.icon("fa5s.sign-out-alt", color=ic))
self.quit_btn.setIconSize(QSize(14, 14))
# 托盘菜单跟随主题
if getattr(self, "_tray_menu", None) is not None:
self._tray_menu.setStyleSheet(self._bottom_menu_stylesheet())
for i in range(self.groups_layout.count() - 1):
item = self.groups_layout.itemAt(i)
if item and item.widget():
@@ -1036,6 +1073,21 @@ class PanelWindow(QWidget):
dlg = UnlockDialog(self)
dlg.exec()
def _open_temperature(self):
try:
from ui.temperature import TemperatureWindow
except Exception as e:
dialog_style.warning(self, "无法打开硬件温度", f"加载模块失败:{e}")
return
# 非模态独立窗口:可与其它功能窗口同时打开、自由切换
win = getattr(self, "_temperature_win", None)
if win is None:
win = TemperatureWindow(self)
self._temperature_win = win
win.show()
win.raise_()
win.activateWindow()
def _open_wechat_multi(self):
from ui.wechat_multi import WechatMultiDialog
dlg = WechatMultiDialog(self)
@@ -1050,6 +1102,12 @@ class PanelWindow(QWidget):
self._settings_win._apply_theme()
except Exception:
pass
# 温度窗口同样跟随主题
if hasattr(self, "_temperature_win") and self._temperature_win.isVisible():
try:
self._temperature_win._apply_theme()
except Exception:
pass
def _show_settings(self):
from ui.settings_window import SettingsWindow
@@ -1249,6 +1307,7 @@ class PanelWindow(QWidget):
if was_visible:
self.setGeometry(geo)
self.show()
self._apply_win32_blur(theme.name() == "dark")
ball = getattr(self, "_ball_ref", None)
if ball is not None:
ball.set_stays_on_top(on_top)
@@ -1256,6 +1315,10 @@ class PanelWindow(QWidget):
def _toggle_pin(self):
self._pinned = not self._pinned
self._sync_pin_dependent_ui()
if self._pinned:
if getattr(self, "_is_collapsed", False):
self._expand_panel()
self._dock_state = "none"
def _on_min_click(self):
"""图钉开启时收缩内容区,否则最小化到悬浮球"""
@@ -1296,6 +1359,8 @@ class PanelWindow(QWidget):
def _save_geometry(self):
"""把当前位置和尺寸写入数据库"""
if getattr(self, "_is_collapsed", False):
return
g = self.geometry()
database.set_setting("panel_x", str(g.x()))
database.set_setting("panel_y", str(g.y()))
@@ -1306,6 +1371,7 @@ class PanelWindow(QWidget):
self._persist_h = g.height()
database.set_setting("panel_w", str(g.width()))
database.set_setting("panel_h", str(g.height()))
self._check_dock_state()
def _restore_geometry(self):
"""从数据库恢复上次的位置、尺寸和透明度"""
@@ -1332,6 +1398,7 @@ class PanelWindow(QWidget):
self.setWindowOpacity(max(30, min(100, opacity)) / 100)
except (ValueError, TypeError):
pass
self._check_dock_state()
def _on_search(self, keyword):
for i in range(self.groups_layout.count() - 1):
@@ -1341,6 +1408,61 @@ class PanelWindow(QWidget):
# ── 显示/隐藏 ────────────────────────────────────────
def show_near(self, ball_pos: QPoint, ball_size: int):
self._is_hiding = False
if getattr(self, "_dock_state", "none") != "none":
self._is_collapsed = False
self._temp_disable_collapse = True
# 从窗口当前位置的屏幕中获取大小,恢复到边缘贴靠展开位置
screen_obj = QApplication.screenAt(self.pos())
if screen_obj is None:
screen_obj = QApplication.primaryScreen()
screen = screen_obj.availableGeometry()
x, y, w, h = self.x(), self.y(), self.width(), self.height()
# 计算展开时的最终坐标
if self._dock_state == "top":
y = screen.top()
elif self._dock_state == "left":
x = screen.left()
elif self._dock_state == "right":
x = screen.right() - w
# 进场滑出偏移方向
offset_x, offset_y = x, y
if self._dock_state == "top":
offset_y = y - 30
elif self._dock_state == "left":
offset_x = x - 30
elif self._dock_state == "right":
offset_x = x + 30
self.move(offset_x, offset_y)
self.setWindowOpacity(0)
self.show()
self.raise_()
if hasattr(self, "_ball_ref"):
self._ball_ref.hide()
if self._anim:
self._anim.stop()
self._anim = QPropertyAnimation(self, b"windowOpacity")
self._anim.setDuration(ANIM_MS)
self._anim.setStartValue(0.0)
self._anim.setEndValue(1.0)
self._anim.start()
self._anim2 = QPropertyAnimation(self, b"pos")
self._anim2.setDuration(ANIM_MS)
self._anim2.setEasingCurve(QEasingCurve.Type.OutCubic)
self._anim2.setStartValue(QPoint(offset_x, offset_y))
self._anim2.setEndValue(QPoint(x, y))
self._anim2.finished.connect(self._save_geometry)
self._anim2.start()
return
# 根据球所在屏幕来定位 panel,避免跑到主屏幕
screen_obj = QApplication.screenAt(ball_pos)
if screen_obj is None:
@@ -1354,6 +1476,8 @@ class PanelWindow(QWidget):
x = bx + ball_size + 8
y = max(screen.top(), min(by + ball_size // 2 - ph // 2, screen.bottom() - ph))
self._is_collapsed = False
self._temp_disable_collapse = True
self.move(x, y + 30)
self.setWindowOpacity(0)
self.show()
@@ -1379,15 +1503,24 @@ class PanelWindow(QWidget):
self._anim2.start()
def hide_panel(self):
self._is_hiding = True
if self._anim:
self._anim.stop()
self._anim = QPropertyAnimation(self, b"windowOpacity")
self._anim.setDuration(ANIM_MS)
self._anim.setStartValue(1.0)
self._anim.setEndValue(0.0)
self._anim.finished.connect(self.hide)
def _on_hide_finished():
self.hide()
self._is_hiding = False
self._anim.finished.connect(_on_hide_finished)
self._anim.start()
def is_really_visible(self) -> bool:
return self.isVisible() and not getattr(self, "_is_hiding", False)
def minimize_to_ball(self):
self.hide_panel()
if hasattr(self, "_ball_ref"):
@@ -1518,6 +1651,8 @@ class PanelWindow(QWidget):
self._do_resize(gp)
return True
if event.buttons() & Qt.MouseButton.LeftButton and self._win_drag_pos:
self._dock_state = "none"
self._is_collapsed = False
self.move(gp - self._win_drag_pos)
return True
# 悬停时更新光标
@@ -1528,6 +1663,7 @@ class PanelWindow(QWidget):
self._resize_edge = None
self._win_drag_pos = None
self._update_cursor(event.globalPosition().toPoint())
self._check_dock_state()
self._save_geometry()
return super().eventFilter(obj, event)
@@ -1538,6 +1674,8 @@ class PanelWindow(QWidget):
self._do_resize(event.globalPosition().toPoint())
return
if event.buttons() & Qt.MouseButton.LeftButton and self._win_drag_pos:
self._dock_state = "none"
self._is_collapsed = False
self.move(event.globalPosition().toPoint() - self._win_drag_pos)
return
self._update_cursor(event.globalPosition().toPoint())
@@ -1563,6 +1701,7 @@ class PanelWindow(QWidget):
self._resize_edge = None
self._win_drag_pos = None
self._update_cursor(event.globalPosition().toPoint())
self._check_dock_state()
self._save_geometry() # 拖动/resize 结束后保存位置和尺寸
def dragEnterEvent(self, event):
@@ -1574,8 +1713,26 @@ class PanelWindow(QWidget):
QTimer.singleShot(200, self._check_focus_lost)
def _check_focus_lost(self):
if not self.isActiveWindow() and not self._pinned:
self.hide_panel()
if self._pinned or not self.isVisible():
return
if self.isActiveWindow():
return
# 焦点转移到了本面板弹出的对话框/子窗口(添加分组、设置、右键菜单等)时不隐藏
active = QApplication.activeWindow()
if active is not None and active is not self:
p = active.parentWidget()
while p is not None:
if p is self:
return
p = p.parentWidget()
if QApplication.activePopupWidget() is not None:
return
if getattr(self, "_dock_state", "none") != "none":
self._temp_disable_collapse = False
if not self._is_collapsed:
self._collapse_panel()
return
self.hide_panel()
# ── 托盘 ─────────────────────────────────────────────
def _setup_tray(self):
@@ -1584,15 +1741,7 @@ class PanelWindow(QWidget):
self.tray.setToolTip("桌面文件整理")
menu = QMenu()
menu.setStyleSheet(
"""
QMenu { background:#2b2b2b; color:#eee; border:1px solid #555;
padding:4px; border-radius:6px; }
QMenu::item { padding:6px 20px; border-radius:4px; }
QMenu::item:selected { background:#3a3a3a; }
QMenu::separator { height:1px; background:#444; margin:4px 8px; }
"""
)
menu.setStyleSheet(self._bottom_menu_stylesheet())
for tooltip, _icon, callback in self._get_quick_actions():
menu.addAction(tooltip).triggered.connect(callback)
menu.addSeparator()
@@ -1600,6 +1749,7 @@ class PanelWindow(QWidget):
menu.addAction("❌ 退出本程序").triggered.connect(QApplication.quit)
self.tray.setContextMenu(menu)
self._tray_menu = menu # 主题切换时同步样式
self.tray.activated.connect(self._on_tray_activated)
self.tray.show()
@@ -1613,93 +1763,167 @@ class PanelWindow(QWidget):
elif hasattr(self, "_ball_ref"):
self.show_near(self._ball_ref.pos(), self._ball_ref.width())
def _toggle_autostart(self):
self._autostart_enabled = not self._autostart_enabled
_set_autostart(self._autostart_enabled)
self._autostart_act.setText(
f"🚀 开机自启: {'开' if self._autostart_enabled else '关'}"
)
# ── 边缘吸附与收起 ─────────────────────────────────────
def _check_dock_state(self):
if self._pinned:
self._dock_state = "none"
return
screen = QApplication.screenAt(self.geometry().center())
if not screen:
screen = QApplication.primaryScreen()
screen_geom = screen.geometry()
class SettingsPopup(QWidget):
"""设置弹出面板:透明度调节等"""
x, y, w, h = self.x(), self.y(), self.width(), self.height()
threshold = 20
def __init__(self, panel: "PanelWindow"):
super().__init__(panel, Qt.WindowType.Popup)
self._panel = panel
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
self.setWindowFlags(Qt.WindowType.Popup | Qt.WindowType.FramelessWindowHint)
self._build()
# 检测顶部吸附
if abs(y - screen_geom.top()) <= threshold:
self._dock_state = "top"
self.move(x, screen_geom.top())
# 检测左侧吸附
elif abs(x - screen_geom.left()) <= threshold:
self._dock_state = "left"
self.move(screen_geom.left(), y)
# 检测右侧吸附
elif abs((x + w) - screen_geom.right()) <= threshold:
self._dock_state = "right"
self.move(screen_geom.right() - w, y)
else:
self._dock_state = "none"
def _build(self):
from PyQt6.QtWidgets import QSlider, QLabel, QVBoxLayout, QHBoxLayout
def _on_dock_timer_timeout(self):
if not self.isVisible() or self._dock_state == "none" or self._pinned or self._win_drag_pos or self._resizing:
return
t = theme.current()
is_dark = theme.name() == "dark"
cursor_pos = QCursor.pos()
geom = self.geometry()
is_hovered = geom.contains(cursor_pos)
self.setStyleSheet(
f"""
QWidget {{
background: {t['panel_bg']};
border: 1px solid {t['panel_border']};
border-radius: 8px;
color: {t['search_color']};
}}
QSlider::groove:horizontal {{
height: 4px;
background: {t['scrollbar']};
border-radius: 2px;
}}
QSlider::handle:horizontal {{
width: 14px; height: 14px;
margin: -5px 0;
background: #4a9eff;
border-radius: 7px;
}}
QSlider::sub-page:horizontal {{
background: #4a9eff;
border-radius: 2px;
}}
"""
)
if not is_hovered:
screen = QApplication.screenAt(cursor_pos)
if screen:
screen_geom = screen.geometry()
tolerance = 3
if self._dock_state == "top" and cursor_pos.y() <= screen_geom.top() + tolerance:
if geom.left() <= cursor_pos.x() <= geom.right():
is_hovered = True
elif self._dock_state == "left" and cursor_pos.x() <= screen_geom.left() + tolerance:
if geom.top() <= cursor_pos.y() <= geom.bottom():
is_hovered = True
elif self._dock_state == "right" and cursor_pos.x() >= screen_geom.right() - tolerance:
if geom.top() <= cursor_pos.y() <= geom.bottom():
is_hovered = True
layout = QVBoxLayout(self)
layout.setContentsMargins(14, 12, 14, 12)
layout.setSpacing(10)
if is_hovered:
self._temp_disable_collapse = False
if self._is_collapsed:
self._expand_panel()
else:
if not self._is_collapsed and not getattr(self, "_temp_disable_collapse", False):
self._collapse_panel()
# 透明度
row = QHBoxLayout()
row.setSpacing(10)
lbl = QLabel("透明度")
lbl.setStyleSheet(
f"color:{t['search_color']}; font-size:12px; background:transparent; border:none;"
)
lbl.setFixedWidth(42)
def _collapse_panel(self):
if self._is_collapsed:
return
self._is_collapsed = True
self._opacity_slider = QSlider(Qt.Orientation.Horizontal)
self._opacity_slider.setRange(30, 100)
saved_opacity = int(database.get_setting("panel_opacity", "100"))
self._opacity_slider.setValue(saved_opacity)
self._opacity_slider.setFixedWidth(140)
self._opacity_slider.valueChanged.connect(self._on_opacity)
screen = QApplication.screenAt(self.geometry().center())
if not screen:
screen = QApplication.primaryScreen()
screen_geom = screen.geometry()
self._opacity_val = QLabel(f"{self._opacity_slider.value()}%")
self._opacity_val.setStyleSheet(
f"color:{t['search_color']}; font-size:11px; background:transparent; border:none;"
)
self._opacity_val.setFixedWidth(34)
x, y, w, h = self.x(), self.y(), self.width(), self.height()
target_x, target_y = x, y
sliver = 3 # 边缘缩进后露出的像素宽度
row.addWidget(lbl)
row.addWidget(self._opacity_slider)
row.addWidget(self._opacity_val)
layout.addLayout(row)
if self._dock_state == "top":
target_y = screen_geom.top() - h + sliver
elif self._dock_state == "left":
target_x = screen_geom.left() - w + sliver
elif self._dock_state == "right":
target_x = screen_geom.right() - sliver
self.adjustSize()
self._animate_to(target_x, target_y)
def _on_opacity(self, val: int):
self._panel.setWindowOpacity(val / 100)
self._opacity_val.setText(f"{val}%")
database.set_setting("panel_opacity", str(val))
def _expand_panel(self):
if not self._is_collapsed:
return
self._is_collapsed = False
screen = QApplication.screenAt(self.geometry().center())
if not screen:
screen = QApplication.primaryScreen()
screen_geom = screen.geometry()
x, y, w, h = self.x(), self.y(), self.width(), self.height()
target_x, target_y = x, y
if self._dock_state == "top":
target_y = screen_geom.top()
elif self._dock_state == "left":
target_x = screen_geom.left()
elif self._dock_state == "right":
target_x = screen_geom.right() - w
self._animate_to(target_x, target_y)
def _animate_to(self, x, y):
if hasattr(self, "_dock_anim") and self._dock_anim:
self._dock_anim.stop()
self._dock_anim = QPropertyAnimation(self, b"pos")
self._dock_anim.setDuration(200)
self._dock_anim.setEasingCurve(QEasingCurve.Type.OutCubic)
self._dock_anim.setStartValue(self.pos())
self._dock_anim.setEndValue(QPoint(x, y))
if not self._is_collapsed:
self._dock_anim.finished.connect(self.raise_)
self._dock_anim.start()
def _apply_win32_blur(self, is_dark: bool):
if sys.platform != "win32":
return
try:
import ctypes
from ctypes import windll, sizeof, byref, c_int, Structure
class ACCENT_POLICY(Structure):
_fields_ = [
("AccentState", c_int),
("AccentFlags", c_int),
("GradientColor", c_int),
("AnimationId", c_int)
]
class WINDOWCOMPOSITIONATTRIBDATA(Structure):
_fields_ = [
("Attribute", c_int),
("Data", ctypes.c_void_p),
("SizeOfData", ctypes.c_int)
]
hwnd = int(self.winId())
accent = ACCENT_POLICY()
accent.AccentState = 4 # ACCENT_ENABLE_ACRYLICBLURBEHIND
if is_dark:
# 磨砂黑色:深灰色半透明
accent.GradientColor = 0x90202020
else:
# 磨砂白色:白色半透明
accent.GradientColor = 0x90F5F5F5
accent.AccentFlags = 2
data = WINDOWCOMPOSITIONATTRIBDATA()
data.Attribute = 19 # WCA_ACCENT_POLICY
data.Data = ctypes.cast(byref(accent), ctypes.c_void_p)
data.SizeOfData = sizeof(accent)
windll.user32.SetWindowCompositionAttribute(hwnd, byref(data))
except Exception as e:
print("Failed to apply win32 composition blur:", e)
def _set_autostart(enable: bool):
@@ -1715,7 +1939,8 @@ def _set_autostart(enable: bool):
app_name = "DesktopOrganizer"
if enable:
exe = (
f'"{sys.executable}" "{os.path.abspath("main.py")}"'
# 用 __file__ 定位入口,避免从其它工作目录启动时写入错误路径
f'"{sys.executable}" "{os.path.abspath(os.path.join(os.path.dirname(os.path.dirname(__file__)), "main.py"))}"'
if not getattr(sys, "frozen", False)
else f'"{sys.executable}"'
)