From 6fa110aa093a61d3c21dced9b5dbb8a2467d3abf Mon Sep 17 00:00:00 2001 From: LZY <2217445143@qq.com> Date: Thu, 5 Feb 2026 22:08:24 +0800 Subject: [PATCH 1/9] =?UTF-8?q?=E5=A4=87=E4=BB=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...3\345\214\205\345\221\275\344\273\244.txt" | 2 +- "\350\257\225\351\252\214.py" | 40 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 "\350\257\225\351\252\214.py" diff --git "a/\346\211\223\345\214\205\345\221\275\344\273\244.txt" "b/\346\211\223\345\214\205\345\221\275\344\273\244.txt" index f0f6e05..9da8c6f 100644 --- "a/\346\211\223\345\214\205\345\221\275\344\273\244.txt" +++ "b/\346\211\223\345\214\205\345\221\275\344\273\244.txt" @@ -1 +1 @@ -pyinstaller --name "桌面切换器" --windowed --onefile --icon "C:\Users\lqvsy\桌面\工作\logo.jpg" "C:\Users\lqvsy\桌面\工作\Windows-optimization\桌面切换\main.py" +pyinstaller --name "桌面切换器" --windowed --onefile --icon "C:\Users\lqvsy\桌面\2_工作\logo.jpg" "C:\Users\lqvsy\桌面\2_工作\Windows-optimization\桌面切换\main.py" diff --git "a/\350\257\225\351\252\214.py" "b/\350\257\225\351\252\214.py" new file mode 100644 index 0000000..57d7304 --- /dev/null +++ "b/\350\257\225\351\252\214.py" @@ -0,0 +1,40 @@ +import ctypes +from ctypes import wintypes +import time + +user32 = ctypes.windll.user32 + +# ---------------- 获取鼠标下的窗口 ---------------- +def get_hwnd_under_mouse(): + pt = wintypes.POINT() + user32.GetCursorPos(ctypes.byref(pt)) + return user32.WindowFromPoint(pt) + +# ---------------- 获取窗口类名 ---------------- +def get_class_name(hwnd): + if not hwnd: + return "" + buf = ctypes.create_unicode_buffer(256) + user32.GetClassNameW(hwnd, buf, 256) + return buf.value + +# ---------------- 判断鼠标是否在任务栏 ---------------- +def is_mouse_over_taskbar(): + hwnd = get_hwnd_under_mouse() + while hwnd: + class_name = get_class_name(hwnd) + if class_name == "Shell_TrayWnd": # 任务栏 + return True + hwnd = user32.GetParent(hwnd) + return False + +# ---------------- 循环检测 ---------------- +try: + while True: + if is_mouse_over_taskbar(): + print("鼠标在任务栏上") + else: + print("鼠标不在任务栏上") + time.sleep(0.2) +except KeyboardInterrupt: + print("退出") -- Gitee From d72cccd382803a2e43246bc32f270eaeb0c74467 Mon Sep 17 00:00:00 2001 From: LZY <2217445143@qq.com> Date: Fri, 6 Feb 2026 14:04:50 +0800 Subject: [PATCH 2/9] =?UTF-8?q?cli=E5=B7=A5=E5=85=B7=E5=BC=80=E5=8F=91?= =?UTF-8?q?=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main_gui.py" | 150 ++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 "\346\241\214\351\235\242\345\210\207\346\215\242/main_gui.py" diff --git "a/\346\241\214\351\235\242\345\210\207\346\215\242/main_gui.py" "b/\346\241\214\351\235\242\345\210\207\346\215\242/main_gui.py" new file mode 100644 index 0000000..a773bdb --- /dev/null +++ "b/\346\241\214\351\235\242\345\210\207\346\215\242/main_gui.py" @@ -0,0 +1,150 @@ +import sys +from functools import partial + +from PySide6.QtWidgets import ( + QApplication, QWidget, QHBoxLayout, + QPushButton, QFrame, QVBoxLayout, QMessageBox +) +from PySide6.QtCore import Qt, QPoint +from PySide6.QtGui import QCursor + +from desktop_dirs import get_dirs, find_index_matching_current_dir +from switch_desktop import switch_desktop_path + + +class DesktopWidget(QWidget): + def __init__(self, entries): + super().__init__() + + # 不进任务栏 / 不进 Win+Tab + self.setWindowFlags(Qt.FramelessWindowHint | Qt.Tool) + self.setAttribute(Qt.WA_TranslucentBackground) + + self.entries = entries + self.buttons = [] + + main_layout = QVBoxLayout(self) + main_layout.setContentsMargins(0, 0, 0, 0) + + # 背景 + self.background = QWidget() + self.background.setStyleSheet(""" + background-color: rgba(50, 50, 50, 220); + border-radius: 15px; + """) + main_layout.addWidget(self.background) + + layout = QHBoxLayout(self.background) + layout.setContentsMargins(5, 5, 5, 5) + layout.setSpacing(5) + + # 左侧拖动条 + self.drag_frame = QFrame() + self.drag_frame.setFixedWidth(25) + self.drag_frame.setStyleSheet(""" + background-color: rgba(80, 80, 80, 200); + border-radius: 10px; + """) + self.drag_frame.setCursor(QCursor(Qt.SizeAllCursor)) + layout.addWidget(self.drag_frame) + + button_height = 35 + + # 添加按钮 + for entry in entries: + btn = QPushButton(entry["name"]) + btn.setFixedHeight(button_height) + btn.setCheckable(True) + btn.setStyleSheet(""" + QPushButton { + background-color: rgba(80, 80, 80, 220); + color: white; + border-radius: 10px; + border: none; + font-size: 14px; + padding-left: 10px; + padding-right: 10px; + } + QPushButton:hover { + background-color: rgba(100, 100, 100, 220); + } + QPushButton:checked { + background-color: rgba(60, 160, 90, 230); + } + """) + layout.addWidget(btn) + self.buttons.append(btn) + btn.clicked.connect(partial(self.on_button_clicked, entry["path"], btn)) + + # 初始位置 + self.move(300, 10) + + # 拖动状态 + self._drag_active = False + self._drag_position = QPoint() + + # ---------------- 点击按钮 ---------------- + def on_button_clicked(self, path: str, btn: QPushButton): + success = switch_desktop_path(path) + + if not success: + # 切换失败,恢复状态 + btn.setChecked(False) + return + + # 切换成功,保持当前按钮选中,其他按钮取消 + for b in self.buttons: + b.setChecked(b is btn) + + # ---------------- 拖动 ---------------- + def mousePressEvent(self, event): + if ( + event.button() == Qt.LeftButton + and event.position().x() <= self.drag_frame.width() + ): + self._drag_active = True + self._drag_position = event.globalPosition().toPoint() - self.frameGeometry().topLeft() + event.accept() + + def mouseMoveEvent(self, event): + if self._drag_active: + screen = QApplication.primaryScreen().availableGeometry() + pos = event.globalPosition().toPoint() - self._drag_position + + # 限制在屏幕内 + x = max(screen.left(), min(pos.x(), screen.right() - self.width())) + y = max(screen.top(), min(pos.y(), screen.bottom() - self.height())) + + self.move(x, y) + event.accept() + + def mouseReleaseEvent(self, event): + self._drag_active = False + + +# ---------------------------- 程序入口 ---------------------------- +if __name__ == "__main__": + app = QApplication(sys.argv) + + entries = get_dirs() + + # 桌面没有任何可用目录 → 弹窗提示 + 退出 + if not entries: + QMessageBox.information( + None, + "提示", + "请在 用户\\桌面 目录创建你要分类的文件夹,也可以是快捷方式" + ) + sys.exit(0) + + widget = DesktopWidget(entries) + + # 获取当前桌面对应按钮索引 + index = find_index_matching_current_dir(entries) + if index is not None and 0 <= index < len(widget.buttons): + # 初始高亮 + widget.buttons[index].setChecked(True) + # 否则不高亮,但组件仍显示 + + widget.show() + sys.exit(app.exec()) -- Gitee From bc8e615f15c4d87fcf86e683dcdd6a47a9c507fe Mon Sep 17 00:00:00 2001 From: LZY <2217445143@qq.com> Date: Fri, 6 Feb 2026 14:05:31 +0800 Subject: [PATCH 3/9] =?UTF-8?q?=E6=B7=BB=E5=8A=A0cli=E5=B7=A5=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../key_simulator.py" | 22 +++ .../main.py" | 16 ++ .../taskbar_mouse.py" | 92 ++++++++++ .../main.py" | 159 ++---------------- "\350\257\225\351\252\214.py" | 40 ----- 5 files changed, 144 insertions(+), 185 deletions(-) create mode 100644 "\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/key_simulator.py" create mode 100644 "\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/main.py" create mode 100644 "\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/taskbar_mouse.py" delete mode 100644 "\350\257\225\351\252\214.py" diff --git "a/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/key_simulator.py" "b/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/key_simulator.py" new file mode 100644 index 0000000..4ccc267 --- /dev/null +++ "b/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/key_simulator.py" @@ -0,0 +1,22 @@ +from pynput.keyboard import Controller, Key +import time + +keyboard = Controller() + +def simulate_ctrl_alt_tab_left(): + """ + 模拟按下 Ctrl+Alt+Tab,一次性触发窗口切换界面 + """ + keyboard.press(Key.ctrl) # 按下 Ctrl + keyboard.press(Key.alt) # 按下 Alt + keyboard.press(Key.tab) # 按下 Tab + # ---------------- 松开所有键 ---------------- + keyboard.release(Key.tab) + keyboard.release(Key.alt) + keyboard.release(Key.ctrl) + +# ---------------- 示例 / 测试 ---------------- +if __name__ == "__main__": + print("运行示例:模拟 Ctrl+Alt+Tab") + simulate_ctrl_alt_tab_left() + print("模拟完成") diff --git "a/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/main.py" "b/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/main.py" new file mode 100644 index 0000000..b0d59dc --- /dev/null +++ "b/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/main.py" @@ -0,0 +1,16 @@ +from taskbar_mouse import TaskbarMonitor +from key_simulator import simulate_alt_tab_left + + +def stop_task(): + print("鼠标离开任务栏 → 停止函数") + +monitor = TaskbarMonitor(start_task, stop_task) +monitor.start() + +# 主线程可以干其他事情 +try: + while True: + time.sleep(0.5) +except KeyboardInterrupt: + monitor.stop() diff --git "a/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/taskbar_mouse.py" "b/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/taskbar_mouse.py" new file mode 100644 index 0000000..5687291 --- /dev/null +++ "b/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/taskbar_mouse.py" @@ -0,0 +1,92 @@ +import ctypes +from ctypes import wintypes +import time +from threading import Thread, Event + +user32 = ctypes.windll.user32 + +# ---------------- 判断鼠标是否在任务栏 ---------------- +def get_hwnd_under_mouse(): + pt = wintypes.POINT() + user32.GetCursorPos(ctypes.byref(pt)) + return user32.WindowFromPoint(pt) + +def get_class_name(hwnd): + if not hwnd: + return "" + buf = ctypes.create_unicode_buffer(256) + user32.GetClassNameW(hwnd, buf, 256) + return buf.value + +def is_mouse_over_taskbar(): + """ + 判断鼠标是否在任务栏的可见区域 + Returns: + bool: True 在任务栏, False 不在 + """ + hwnd = get_hwnd_under_mouse() + while hwnd: + class_name = get_class_name(hwnd) + if class_name == "Shell_TrayWnd": + rect = wintypes.RECT() + user32.GetWindowRect(hwnd, ctypes.byref(rect)) + if not user32.IsWindowVisible(hwnd): + return False + pt = wintypes.POINT() + user32.GetCursorPos(ctypes.byref(pt)) + return rect.left <= pt.x <= rect.right and rect.top <= pt.y <= rect.bottom + hwnd = user32.GetParent(hwnd) + return False + +# ---------------- 任务栏监控类 ---------------- +class TaskbarMonitor: + def __init__(self, on_enter, on_exit, interval=0.1): + """ + 初始化任务栏监控 + Args: + on_enter (callable): 鼠标进入任务栏时调用函数,接收一个 stop_event 参数 + on_exit (callable): 鼠标离开任务栏时调用函数 + interval (float): 检测间隔,单位秒 + """ + self.on_enter = on_enter + self.on_exit = on_exit + self.interval = interval + self._over = False + self._worker_thread = None + self._stop_event = Event() + self._running = False + + def _run_worker(self): + self.on_enter(self._stop_event) + + def start(self): + """启动任务栏监控""" + self._running = True + self._monitor_thread = Thread(target=self._monitor_loop, daemon=True) + self._monitor_thread.start() + + def _monitor_loop(self): + try: + while self._running: + now_over = is_mouse_over_taskbar() + if now_over and not self._over: + self._over = True + self._stop_event.clear() + self._worker_thread = Thread(target=self._run_worker, daemon=True) + self._worker_thread.start() + elif not now_over and self._over: + self._over = False + self._stop_event.set() + if self._worker_thread: + self._worker_thread.join() + self.on_exit() + time.sleep(self.interval) + except KeyboardInterrupt: + self.stop() + + def stop(self): + """停止任务栏监控""" + self._running = False + self._stop_event.set() + if self._worker_thread: + self._worker_thread.join() diff --git "a/\346\241\214\351\235\242\345\210\207\346\215\242/main.py" "b/\346\241\214\351\235\242\345\210\207\346\215\242/main.py" index a773bdb..fc52ab2 100644 --- "a/\346\241\214\351\235\242\345\210\207\346\215\242/main.py" +++ "b/\346\241\214\351\235\242\345\210\207\346\215\242/main.py" @@ -1,150 +1,19 @@ -import sys -from functools import partial +import switch_desktop +import argparse -from PySide6.QtWidgets import ( - QApplication, QWidget, QHBoxLayout, - QPushButton, QFrame, QVBoxLayout, QMessageBox -) -from PySide6.QtCore import Qt, QPoint -from PySide6.QtGui import QCursor +def main(): + parser = argparse.ArgumentParser(description="接收一个路径参数并切换桌面") + parser.add_argument("path", help="输入的路径") + args = parser.parse_args() -from desktop_dirs import get_dirs, find_index_matching_current_dir -from switch_desktop import switch_desktop_path + # 直接打印参数 + print(args.path) + # 切换桌面 + if switch_desktop.switch_desktop_path(args.path): + print("✅ 桌面切换完成并刷新") + else: + print("❌ 桌面切换失败") -class DesktopWidget(QWidget): - def __init__(self, entries): - super().__init__() - - # 不进任务栏 / 不进 Win+Tab - self.setWindowFlags(Qt.FramelessWindowHint | Qt.Tool) - self.setAttribute(Qt.WA_TranslucentBackground) - - self.entries = entries - self.buttons = [] - - main_layout = QVBoxLayout(self) - main_layout.setContentsMargins(0, 0, 0, 0) - - # 背景 - self.background = QWidget() - self.background.setStyleSheet(""" - background-color: rgba(50, 50, 50, 220); - border-radius: 15px; - """) - main_layout.addWidget(self.background) - - layout = QHBoxLayout(self.background) - layout.setContentsMargins(5, 5, 5, 5) - layout.setSpacing(5) - - # 左侧拖动条 - self.drag_frame = QFrame() - self.drag_frame.setFixedWidth(25) - self.drag_frame.setStyleSheet(""" - background-color: rgba(80, 80, 80, 200); - border-radius: 10px; - """) - self.drag_frame.setCursor(QCursor(Qt.SizeAllCursor)) - layout.addWidget(self.drag_frame) - - button_height = 35 - - # 添加按钮 - for entry in entries: - btn = QPushButton(entry["name"]) - btn.setFixedHeight(button_height) - btn.setCheckable(True) - btn.setStyleSheet(""" - QPushButton { - background-color: rgba(80, 80, 80, 220); - color: white; - border-radius: 10px; - border: none; - font-size: 14px; - padding-left: 10px; - padding-right: 10px; - } - QPushButton:hover { - background-color: rgba(100, 100, 100, 220); - } - QPushButton:checked { - background-color: rgba(60, 160, 90, 230); - } - """) - layout.addWidget(btn) - self.buttons.append(btn) - btn.clicked.connect(partial(self.on_button_clicked, entry["path"], btn)) - - # 初始位置 - self.move(300, 10) - - # 拖动状态 - self._drag_active = False - self._drag_position = QPoint() - - # ---------------- 点击按钮 ---------------- - def on_button_clicked(self, path: str, btn: QPushButton): - success = switch_desktop_path(path) - - if not success: - # 切换失败,恢复状态 - btn.setChecked(False) - return - - # 切换成功,保持当前按钮选中,其他按钮取消 - for b in self.buttons: - b.setChecked(b is btn) - - # ---------------- 拖动 ---------------- - def mousePressEvent(self, event): - if ( - event.button() == Qt.LeftButton - and event.position().x() <= self.drag_frame.width() - ): - self._drag_active = True - self._drag_position = event.globalPosition().toPoint() - self.frameGeometry().topLeft() - event.accept() - - def mouseMoveEvent(self, event): - if self._drag_active: - screen = QApplication.primaryScreen().availableGeometry() - pos = event.globalPosition().toPoint() - self._drag_position - - # 限制在屏幕内 - x = max(screen.left(), min(pos.x(), screen.right() - self.width())) - y = max(screen.top(), min(pos.y(), screen.bottom() - self.height())) - - self.move(x, y) - event.accept() - - def mouseReleaseEvent(self, event): - self._drag_active = False - - -# ---------------------------- 程序入口 ---------------------------- if __name__ == "__main__": - app = QApplication(sys.argv) - - entries = get_dirs() - - # 桌面没有任何可用目录 → 弹窗提示 + 退出 - if not entries: - QMessageBox.information( - None, - "提示", - "请在 用户\\桌面 目录创建你要分类的文件夹,也可以是快捷方式" - ) - sys.exit(0) - - widget = DesktopWidget(entries) - - # 获取当前桌面对应按钮索引 - index = find_index_matching_current_dir(entries) - if index is not None and 0 <= index < len(widget.buttons): - # 初始高亮 - widget.buttons[index].setChecked(True) - # 否则不高亮,但组件仍显示 - - widget.show() - sys.exit(app.exec()) + main() diff --git "a/\350\257\225\351\252\214.py" "b/\350\257\225\351\252\214.py" deleted file mode 100644 index 57d7304..0000000 --- "a/\350\257\225\351\252\214.py" +++ /dev/null @@ -1,40 +0,0 @@ -import ctypes -from ctypes import wintypes -import time - -user32 = ctypes.windll.user32 - -# ---------------- 获取鼠标下的窗口 ---------------- -def get_hwnd_under_mouse(): - pt = wintypes.POINT() - user32.GetCursorPos(ctypes.byref(pt)) - return user32.WindowFromPoint(pt) - -# ---------------- 获取窗口类名 ---------------- -def get_class_name(hwnd): - if not hwnd: - return "" - buf = ctypes.create_unicode_buffer(256) - user32.GetClassNameW(hwnd, buf, 256) - return buf.value - -# ---------------- 判断鼠标是否在任务栏 ---------------- -def is_mouse_over_taskbar(): - hwnd = get_hwnd_under_mouse() - while hwnd: - class_name = get_class_name(hwnd) - if class_name == "Shell_TrayWnd": # 任务栏 - return True - hwnd = user32.GetParent(hwnd) - return False - -# ---------------- 循环检测 ---------------- -try: - while True: - if is_mouse_over_taskbar(): - print("鼠标在任务栏上") - else: - print("鼠标不在任务栏上") - time.sleep(0.2) -except KeyboardInterrupt: - print("退出") -- Gitee From 8f75f95d953a4e135ce1195244769dec2124b1b3 Mon Sep 17 00:00:00 2001 From: LZY <2217445143@qq.com> Date: Fri, 6 Feb 2026 16:13:13 +0800 Subject: [PATCH 4/9] =?UTF-8?q?=E5=A4=87=E4=BB=BD=E4=B8=80=E4=B8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../detection_taskbar.py" | 49 ++++++++++ .../key_simulator.py" | 22 ----- .../main.py" | 17 +--- .../task_switch.py" | 81 ++++++++++++++++ .../taskbar_mouse.py" | 92 ------------------- ...3\345\214\205\345\221\275\344\273\244.txt" | 2 +- 6 files changed, 132 insertions(+), 131 deletions(-) create mode 100644 "\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/detection_taskbar.py" delete mode 100644 "\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/key_simulator.py" create mode 100644 "\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/task_switch.py" delete mode 100644 "\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/taskbar_mouse.py" diff --git "a/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/detection_taskbar.py" "b/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/detection_taskbar.py" new file mode 100644 index 0000000..a09354a --- /dev/null +++ "b/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/detection_taskbar.py" @@ -0,0 +1,49 @@ +import ctypes +from ctypes import wintypes + +user32 = ctypes.windll.user32 + +# ----------------------------- +# 获取鼠标下窗口句柄 +# ----------------------------- +def get_hwnd_under_mouse(): + pt = wintypes.POINT() + user32.GetCursorPos(ctypes.byref(pt)) + return user32.WindowFromPoint(pt) + +# ----------------------------- +# 获取窗口类名 +# ----------------------------- +def get_class_name(hwnd): + if not hwnd: + return "" + buf = ctypes.create_unicode_buffer(256) + user32.GetClassNameW(hwnd, buf, 256) + return buf.value + +# ----------------------------- +# 检测鼠标是否在任务栏 +# ----------------------------- +def is_mouse_over_taskbar(): + hwnd = get_hwnd_under_mouse() + while hwnd: + if get_class_name(hwnd) == "Shell_TrayWnd": + return True # 鼠标下窗口是任务栏或任务栏子控件 + hwnd = user32.GetParent(hwnd) + return False + +# ----------------------------- +# 主循环示例 +# ----------------------------- +if __name__ == "__main__": + import time + + try: + while True: + if is_mouse_over_taskbar(): + print("鼠标在任务栏") + else: + print("鼠标不在任务栏") + time.sleep(0.2) # 每 0.2 秒检测一次 + except KeyboardInterrupt: + print("退出检测") diff --git "a/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/key_simulator.py" "b/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/key_simulator.py" deleted file mode 100644 index 4ccc267..0000000 --- "a/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/key_simulator.py" +++ /dev/null @@ -1,22 +0,0 @@ -from pynput.keyboard import Controller, Key -import time - -keyboard = Controller() - -def simulate_ctrl_alt_tab_left(): - """ - 模拟按下 Ctrl+Alt+Tab,一次性触发窗口切换界面 - """ - keyboard.press(Key.ctrl) # 按下 Ctrl - keyboard.press(Key.alt) # 按下 Alt - keyboard.press(Key.tab) # 按下 Tab - # ---------------- 松开所有键 ---------------- - keyboard.release(Key.tab) - keyboard.release(Key.alt) - keyboard.release(Key.ctrl) - -# ---------------- 示例 / 测试 ---------------- -if __name__ == "__main__": - print("运行示例:模拟 Ctrl+Alt+Tab") - simulate_ctrl_alt_tab_left() - print("模拟完成") diff --git "a/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/main.py" "b/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/main.py" index b0d59dc..fc80254 100644 --- "a/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/main.py" +++ "b/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/main.py" @@ -1,16 +1 @@ -from taskbar_mouse import TaskbarMonitor -from key_simulator import simulate_alt_tab_left - - -def stop_task(): - print("鼠标离开任务栏 → 停止函数") - -monitor = TaskbarMonitor(start_task, stop_task) -monitor.start() - -# 主线程可以干其他事情 -try: - while True: - time.sleep(0.5) -except KeyboardInterrupt: - monitor.stop() +pass \ No newline at end of file diff --git "a/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/task_switch.py" "b/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/task_switch.py" new file mode 100644 index 0000000..8b60a51 --- /dev/null +++ "b/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/task_switch.py" @@ -0,0 +1,81 @@ +import win32gui +from pynput.keyboard import Controller, Key + +# ----------------------------- +# 全局键盘控制器 +# ----------------------------- +kb = Controller() + +# ----------------------------- +# 检测 Alt+Tab(任务切换)窗口是否存在 +# ----------------------------- +def is_task_switch_active(): + """检查任务切换界面是否存在""" + found = False + def enum_cb(hwnd, _): + nonlocal found + if win32gui.IsWindowVisible(hwnd): + if win32gui.GetClassName(hwnd) == "XamlExplorerHostIslandWindow" and win32gui.GetWindowText(hwnd) == "任务切换": + found = True + win32gui.EnumWindows(enum_cb, None) + return found + +# ----------------------------- +# 按 ESC 关闭任务切换 +# ----------------------------- +def exit_task_switch(): + """如果任务切换界面存在,则按 ESC 关闭""" + if is_task_switch_active(): + kb.press(Key.esc) + kb.release(Key.esc) + +# ----------------------------- +# 模拟 Ctrl+Alt+Tab 触发任务切换 +# ----------------------------- +def trigger_task_switch(): + """模拟一次性按下 Ctrl+Alt+Tab 触发任务切换界面""" + kb.press(Key.ctrl) + kb.press(Key.alt) + kb.press(Key.tab) + kb.release(Key.tab) + kb.release(Key.alt) + kb.release(Key.ctrl) + + +# ----------------------------- +# 模拟按下键盘左箭头 +# ----------------------------- +def left_arrow(): + kb.press(Key.left) # 按下左箭头 + kb.release(Key.left) # 松开左箭头 + +# ----------------------------- +# 模拟按下键盘右箭头 +# ----------------------------- +def right_arrow(): + kb.press(Key.right) # 按下右箭头 + kb.release(Key.right) # 松开右箭头 + + + +# ----------------------------- +# 示例调用 +# ----------------------------- +if __name__ == "__main__": + print("模拟 Ctrl+Alt+Tab → 触发任务切换") + trigger_task_switch() + + # 给系统一点时间显示任务切换界面 + import time + time.sleep(1) + + print("模拟按下左箭头") + left_arrow() + time.sleep(1) + print("模拟按下右箭头") + right_arrow() + time.sleep(1) + + print("检测并按 ESC 关闭任务切换") + exit_task_switch() + print("完成") diff --git "a/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/taskbar_mouse.py" "b/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/taskbar_mouse.py" deleted file mode 100644 index 5687291..0000000 --- "a/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/taskbar_mouse.py" +++ /dev/null @@ -1,92 +0,0 @@ -import ctypes -from ctypes import wintypes -import time -from threading import Thread, Event - -user32 = ctypes.windll.user32 - -# ---------------- 判断鼠标是否在任务栏 ---------------- -def get_hwnd_under_mouse(): - pt = wintypes.POINT() - user32.GetCursorPos(ctypes.byref(pt)) - return user32.WindowFromPoint(pt) - -def get_class_name(hwnd): - if not hwnd: - return "" - buf = ctypes.create_unicode_buffer(256) - user32.GetClassNameW(hwnd, buf, 256) - return buf.value - -def is_mouse_over_taskbar(): - """ - 判断鼠标是否在任务栏的可见区域 - Returns: - bool: True 在任务栏, False 不在 - """ - hwnd = get_hwnd_under_mouse() - while hwnd: - class_name = get_class_name(hwnd) - if class_name == "Shell_TrayWnd": - rect = wintypes.RECT() - user32.GetWindowRect(hwnd, ctypes.byref(rect)) - if not user32.IsWindowVisible(hwnd): - return False - pt = wintypes.POINT() - user32.GetCursorPos(ctypes.byref(pt)) - return rect.left <= pt.x <= rect.right and rect.top <= pt.y <= rect.bottom - hwnd = user32.GetParent(hwnd) - return False - -# ---------------- 任务栏监控类 ---------------- -class TaskbarMonitor: - def __init__(self, on_enter, on_exit, interval=0.1): - """ - 初始化任务栏监控 - Args: - on_enter (callable): 鼠标进入任务栏时调用函数,接收一个 stop_event 参数 - on_exit (callable): 鼠标离开任务栏时调用函数 - interval (float): 检测间隔,单位秒 - """ - self.on_enter = on_enter - self.on_exit = on_exit - self.interval = interval - self._over = False - self._worker_thread = None - self._stop_event = Event() - self._running = False - - def _run_worker(self): - self.on_enter(self._stop_event) - - def start(self): - """启动任务栏监控""" - self._running = True - self._monitor_thread = Thread(target=self._monitor_loop, daemon=True) - self._monitor_thread.start() - - def _monitor_loop(self): - try: - while self._running: - now_over = is_mouse_over_taskbar() - if now_over and not self._over: - self._over = True - self._stop_event.clear() - self._worker_thread = Thread(target=self._run_worker, daemon=True) - self._worker_thread.start() - elif not now_over and self._over: - self._over = False - self._stop_event.set() - if self._worker_thread: - self._worker_thread.join() - self.on_exit() - time.sleep(self.interval) - except KeyboardInterrupt: - self.stop() - - def stop(self): - """停止任务栏监控""" - self._running = False - self._stop_event.set() - if self._worker_thread: - self._worker_thread.join() diff --git "a/\346\211\223\345\214\205\345\221\275\344\273\244.txt" "b/\346\211\223\345\214\205\345\221\275\344\273\244.txt" index 9da8c6f..a34904e 100644 --- "a/\346\211\223\345\214\205\345\221\275\344\273\244.txt" +++ "b/\346\211\223\345\214\205\345\221\275\344\273\244.txt" @@ -1 +1 @@ -pyinstaller --name "桌面切换器" --windowed --onefile --icon "C:\Users\lqvsy\桌面\2_工作\logo.jpg" "C:\Users\lqvsy\桌面\2_工作\Windows-optimization\桌面切换\main.py" +pyinstaller --name "桌面切换器" --windowed --onefile --icon "C:\Users\lqvsy\桌面\1_Work\logo.jpg" "C:\Users\lqvsy\桌面\1_Work\Windows-optimization\桌面切换\main.py" -- Gitee From 83b0c5f2a2fd6b33b1513a183efa289b35cffd58 Mon Sep 17 00:00:00 2001 From: LZY <2217445143@qq.com> Date: Fri, 6 Feb 2026 17:12:21 +0800 Subject: [PATCH 5/9] =?UTF-8?q?=E5=A4=87=E4=BB=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../detection_taskbar.py" | 50 +++++++++++++++++-- .../main.py" | 22 +++++++- .../switch_desktop.py" | 37 ++++++++++++++ 3 files changed, 103 insertions(+), 6 deletions(-) create mode 100644 "\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/switch_desktop.py" diff --git "a/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/detection_taskbar.py" "b/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/detection_taskbar.py" index a09354a..e13b2a8 100644 --- "a/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/detection_taskbar.py" +++ "b/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/detection_taskbar.py" @@ -1,5 +1,8 @@ +# taskbar_mouse.py import ctypes from ctypes import wintypes +from pynput import mouse +import time user32 = ctypes.windll.user32 @@ -28,22 +31,59 @@ def is_mouse_over_taskbar(): hwnd = get_hwnd_under_mouse() while hwnd: if get_class_name(hwnd) == "Shell_TrayWnd": - return True # 鼠标下窗口是任务栏或任务栏子控件 + return True hwnd = user32.GetParent(hwnd) return False # ----------------------------- -# 主循环示例 +# 鼠标滚轮监听(只在任务栏触发) +# ----------------------------- +def start_taskbar_wheel_listener(on_scroll_up=None, on_scroll_down=None, throttle=0.1): + """ + 启动滚轮监听,只在任务栏上触发 + throttle: 两次触发最小间隔(秒) + """ + last_time = 0 + + def on_scroll(x, y, dx, dy): + nonlocal last_time + if not is_mouse_over_taskbar(): + return + now = time.time() + if now - last_time < throttle: + return # 节流 + last_time = now + if dy > 0 and on_scroll_up: + on_scroll_up() + elif dy < 0 and on_scroll_down: + on_scroll_down() + + listener = mouse.Listener(on_scroll=on_scroll) + listener.start() + return listener + + +# ----------------------------- +# 测试示例 # ----------------------------- if __name__ == "__main__": - import time - + print("任务栏鼠标滚轮检测示例") + + def up_action(): + print("鼠标在任务栏,滚轮向上") + + def down_action(): + print("鼠标在任务栏,滚轮向下") + + listener = start_taskbar_wheel_listener(up_action, down_action, throttle=0.1) + try: while True: if is_mouse_over_taskbar(): print("鼠标在任务栏") else: print("鼠标不在任务栏") - time.sleep(0.2) # 每 0.2 秒检测一次 + time.sleep(1) except KeyboardInterrupt: print("退出检测") + listener.stop() diff --git "a/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/main.py" "b/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/main.py" index fc80254..33db3c5 100644 --- "a/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/main.py" +++ "b/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/main.py" @@ -1 +1,21 @@ -pass \ No newline at end of file +from detection_taskbar import start_taskbar_wheel_listener +from switch_desktop import ctrl_win_left_arrow, ctrl_win_right_arrow +import time + +# 滚轮回调 +def up_action(): + ctrl_win_left_arrow() + +def down_action(): + ctrl_win_right_arrow() + +# 启动滚轮监听 +listener = start_taskbar_wheel_listener(up_action, down_action, throttle=0.0000001) + +print("任务栏滚轮检测已启动,Ctrl+C 退出") + +try: + input("按任意键继续...") +except KeyboardInterrupt: + print("退出检测") + listener.stop() diff --git "a/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/switch_desktop.py" "b/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/switch_desktop.py" new file mode 100644 index 0000000..885f453 --- /dev/null +++ "b/\344\273\273\345\212\241\346\240\217\351\274\240\346\240\207\346\273\232\345\212\250/switch_desktop.py" @@ -0,0 +1,37 @@ +from pynput.keyboard import Controller, Key +import time + +# 全局键盘控制器 +kb = Controller() + +# ----------------------------- +# 模拟 Ctrl + Win + 左箭头 +# ----------------------------- +def ctrl_win_left_arrow(): + kb.press(Key.ctrl) # 按下 Ctrl + kb.press(Key.cmd) # 按下 Win + kb.press(Key.left) # 按下左箭头 + kb.release(Key.left) + kb.release(Key.cmd) + kb.release(Key.ctrl) + +# ----------------------------- +# 模拟 Ctrl + Win + 右箭头 +# ----------------------------- +def ctrl_win_right_arrow(): + kb.press(Key.ctrl) # 按下 Ctrl + kb.press(Key.cmd) # 按下 Win + kb.press(Key.right) # 按下右箭头 + kb.release(Key.right) + kb.release(Key.cmd) + kb.release(Key.ctrl) + +# ----------------------------- +# 测试示例 +# ----------------------------- +if __name__ == "__main__": + print("模拟 Ctrl + Win + 右箭头(切换到右侧桌面)") + ctrl_win_right_arrow() + time.sleep(0.5) + print("模拟 Ctrl + Win + 左箭头(切换到左侧桌面)") + ctrl_win_left_arrow() \ No newline at end of file -- Gitee From e23ab82d47ce6e3536e635028f369a6c5c0da3b4 Mon Sep 17 00:00:00 2001 From: LZY <2217445143@qq.com> Date: Sun, 8 Feb 2026 20:06:00 +0800 Subject: [PATCH 6/9] =?UTF-8?q?=E5=A4=87=E4=BB=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mian.py | 97 ++++++++++++++++++++++++++++++ "\350\257\225\351\252\214main.py" | 98 +++++++++++++++++++++++++++++++ 2 files changed, 195 insertions(+) create mode 100644 mian.py create mode 100644 "\350\257\225\351\252\214main.py" diff --git a/mian.py b/mian.py new file mode 100644 index 0000000..53c8fd0 --- /dev/null +++ b/mian.py @@ -0,0 +1,97 @@ +import sys +import win32gui +import win32con +from PySide6.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout +from PySide6.QtCore import Qt, QPoint + +TARGET_HWND = 0x328108 # 你的目标窗口句柄 +MAX_W, MAX_H = 2000, 1200 # 避免 CreateDIBSection 失败 + + +class DraggableWidget(QWidget): + def __init__(self): + super().__init__() + self.dragging = False + self.drag_pos = QPoint() + + self.setWindowFlags(Qt.FramelessWindowHint) + self.setAttribute(Qt.WA_NoSystemBackground, False) + self.setAttribute(Qt.WA_TranslucentBackground, False) + + layout = QVBoxLayout(self) + layout.setContentsMargins(0, 0, 0, 0) + + label = QLabel("点击拖动我!\n这是挂在 HWND 下的 UI") + label.setStyleSheet("font-size:16px; background:#202020; color:white; padding:8px;") + label.setAlignment(Qt.AlignCenter) + layout.addWidget(label) + + self.resize(300, 120) + + # ---------------- 鼠标拖动 ---------------- + def mousePressEvent(self, e): + if e.button() == Qt.LeftButton: + self.dragging = True + self.drag_pos = e.globalPosition().toPoint() + + def mouseMoveEvent(self, e): + if not self.dragging: + return + delta = e.globalPosition().toPoint() - self.drag_pos + self.drag_pos = e.globalPosition().toPoint() + + hwnd = int(self.winId()) + if not win32gui.IsWindow(hwnd): + return + + x, y, r, b = win32gui.GetWindowRect(hwnd) + width, height = r - x, b - y + + # 移动窗口 + new_x = x + delta.x() + new_y = y + delta.y() + new_x = max(0, min(new_x, MAX_W)) + new_y = max(0, min(new_y, MAX_H)) + + win32gui.SetWindowPos( + hwnd, None, new_x, new_y, width, height, + win32con.SWP_NOZORDER | win32con.SWP_NOACTIVATE + ) + + def mouseReleaseEvent(self, e): + self.dragging = False + + +def embed_widget(widget: QWidget, parent_hwnd: int): + hwnd = int(widget.winId()) + + # 设置为子窗口 + style = win32gui.GetWindowLong(hwnd, win32con.GWL_STYLE) + style &= ~win32con.WS_POPUP + style |= win32con.WS_CHILD + win32gui.SetWindowLong(hwnd, win32con.GWL_STYLE, style) + + win32gui.SetParent(hwnd, parent_hwnd) + + # 使用 widget 自己的大小(不要拉满) + w, h = widget.width(), widget.height() + + win32gui.SetWindowPos( + hwnd, + None, + 50, 50, # 初始位置 + w, h, # 使用自身尺寸 + win32con.SWP_NOZORDER | win32con.SWP_SHOWWINDOW + ) + + + +if __name__ == "__main__": + app = QApplication(sys.argv) + + widget = DraggableWidget() + widget.show() + + embed_widget(widget, TARGET_HWND) + + sys.exit(app.exec()) diff --git "a/\350\257\225\351\252\214main.py" "b/\350\257\225\351\252\214main.py" new file mode 100644 index 0000000..cd2e308 --- /dev/null +++ "b/\350\257\225\351\252\214main.py" @@ -0,0 +1,98 @@ +import sys +import ctypes +import win32gui +import win32con +from PySide6.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout +from PySide6.QtCore import Qt, QPoint + +# ----------------- 拖动可用 ----------------- +MAX_W, MAX_H = 2000, 1200 # 最大尺寸限制 + +class DesktopOverlay(QWidget): + def __init__(self): + super().__init__() + self.dragging = False + self.drag_pos = QPoint() + + # 无边框 + self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint) + self.setAttribute(Qt.WA_TranslucentBackground, False) + + layout = QVBoxLayout(self) + layout.setContentsMargins(0, 0, 0, 0) + + label = QLabel("这是桌面浮层\n可拖动,不挡图标") + label.setStyleSheet("font-size:16px; background:#202020; color:white; padding:8px;") + label.setAlignment(Qt.AlignCenter) + layout.addWidget(label) + + self.resize(300, 120) + + # ----------------- 拖动 ----------------- + def mousePressEvent(self, e): + if e.button() == Qt.LeftButton: + self.dragging = True + self.drag_pos = e.globalPosition().toPoint() + + def mouseMoveEvent(self, e): + if not self.dragging: + return + delta = e.globalPosition().toPoint() - self.drag_pos + self.drag_pos = e.globalPosition().toPoint() + + new_x = self.x() + delta.x() + new_y = self.y() + delta.y() + new_x = max(0, min(new_x, MAX_W - self.width())) + new_y = max(0, min(new_y, MAX_H - self.height())) + + self.move(new_x, new_y) + + def mouseReleaseEvent(self, e): + self.dragging = False + +# ----------------- 找到桌面 WorkerW ----------------- +def get_desktop_hwnd(): + progman = win32gui.FindWindow("Progman", None) + # 发送消息强制创建 WorkerW + win32gui.SendMessageTimeout(progman, 0x052C, 0, 0, win32con.SMTO_NORMAL, 1000) + workerw = None + + def enum_windows(hwnd, lParam): + nonlocal workerw + class_name = win32gui.GetClassName(hwnd) + if class_name == "WorkerW": + child = win32gui.FindWindowEx(hwnd, 0, "SHELLDLL_DefView", None) + if child != 0: + workerw = hwnd + return True + + win32gui.EnumWindows(enum_windows, None) + if workerw: + return workerw + return progman # 回退到 Progman + +# ----------------- 挂到桌面 ----------------- +def attach_to_desktop(widget: QWidget): + hwnd = int(widget.winId()) + desktop_hwnd = get_desktop_hwnd() + + # 设置 WS_CHILD + style = win32gui.GetWindowLong(hwnd, win32con.GWL_STYLE) + style &= ~win32con.WS_POPUP + style |= win32con.WS_CHILD + win32gui.SetWindowLong(hwnd, win32con.GWL_STYLE, style) + + # 父窗口 + win32gui.SetParent(hwnd, desktop_hwnd) + + # 放到左上角 + win32gui.SetWindowPos(hwnd, None, 50, 50, widget.width(), widget.height(), + win32con.SWP_NOZORDER | win32con.SWP_SHOWWINDOW) + + +if __name__ == "__main__": + app = QApplication(sys.argv) + widget = DesktopOverlay() + widget.show() + attach_to_desktop(widget) + sys.exit(app.exec()) -- Gitee From cef4a901ec2373c680fb548cc8a5bbfafc35d7c6 Mon Sep 17 00:00:00 2001 From: LZY <2217445143@qq.com> Date: Mon, 9 Feb 2026 10:57:13 +0800 Subject: [PATCH 7/9] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../desktop_component.py" | 1 + .../refresh_desktop.py" | 27 +++++++------------ 2 files changed, 11 insertions(+), 17 deletions(-) create mode 100644 "\346\241\214\351\235\242\345\210\207\346\215\242/desktop_component.py" diff --git "a/\346\241\214\351\235\242\345\210\207\346\215\242/desktop_component.py" "b/\346\241\214\351\235\242\345\210\207\346\215\242/desktop_component.py" new file mode 100644 index 0000000..fc80254 --- /dev/null +++ "b/\346\241\214\351\235\242\345\210\207\346\215\242/desktop_component.py" @@ -0,0 +1 @@ +pass \ No newline at end of file diff --git "a/\346\241\214\351\235\242\345\210\207\346\215\242/refresh_desktop.py" "b/\346\241\214\351\235\242\345\210\207\346\215\242/refresh_desktop.py" index 00a4b58..ed5e632 100644 --- "a/\346\241\214\351\235\242\345\210\207\346\215\242/refresh_desktop.py" +++ "b/\346\241\214\351\235\242\345\210\207\346\215\242/refresh_desktop.py" @@ -9,30 +9,23 @@ user32 = ctypes.windll.user32 def refresh_desktop(): """ 刷新 Windows 桌面(模拟 F5)。 + 使用 Progman 窗口。 返回 True 表示刷新成功,False 表示未找到桌面窗口。 """ - defview = None - worker = None - while True: - worker = user32.FindWindowExW(None, worker, "WorkerW", None) - if not worker: - break - defview = user32.FindWindowExW(worker, None, "SHELLDLL_DefView", None) - if defview: - break + # 直接获取桌面主窗口 Progman + desktop = user32.FindWindowW("Progman", None) + if not desktop: + return False - listview = user32.FindWindowExW(defview, None, "SysListView32", None) if defview else None + # 发送 F5 消息 + user32.PostMessageW(desktop, WM_KEYDOWN, VK_F5, 0) + user32.PostMessageW(desktop, WM_KEYUP, VK_F5, 0) - if listview: - user32.PostMessageW(listview, WM_KEYDOWN, VK_F5, 0) - user32.PostMessageW(listview, WM_KEYUP, VK_F5, 0) - return True - else: - return False + return True # --------------------------------- if __name__ == "__main__": if refresh_desktop(): print("桌面已刷新 ✅") else: - print("找不到桌面图标窗口 ❌") + print("找不到桌面窗口 ❌") -- Gitee From 5725f61d92c7651401ac68584b7479f133dbe360 Mon Sep 17 00:00:00 2001 From: LZY <2217445143@qq.com> Date: Mon, 9 Feb 2026 12:17:05 +0800 Subject: [PATCH 8/9] =?UTF-8?q?=E6=8C=82=E5=88=B0=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E4=B8=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../desktop_component.py" | 59 ++++++- .../main.py" | 159 ++++++++++++++++-- .../main_cli.py" | 19 +++ .../main_gui.py" | 150 ----------------- 4 files changed, 222 insertions(+), 165 deletions(-) create mode 100644 "\346\241\214\351\235\242\345\210\207\346\215\242/main_cli.py" delete mode 100644 "\346\241\214\351\235\242\345\210\207\346\215\242/main_gui.py" diff --git "a/\346\241\214\351\235\242\345\210\207\346\215\242/desktop_component.py" "b/\346\241\214\351\235\242\345\210\207\346\215\242/desktop_component.py" index fc80254..c27228a 100644 --- "a/\346\241\214\351\235\242\345\210\207\346\215\242/desktop_component.py" +++ "b/\346\241\214\351\235\242\345\210\207\346\215\242/desktop_component.py" @@ -1 +1,58 @@ -pass \ No newline at end of file +import ctypes + +user32 = ctypes.windll.user32 + +GWL_STYLE = -16 +WS_CHILD = 0x40000000 +WS_VISIBLE = 0x10000000 + +def get_desktop_listview_hwnd(): + """ + 获取桌面图标列表窗口的句柄 (SysListView32) + 返回句柄,找不到返回 None + """ + defview = None + worker = None + + while True: + worker = user32.FindWindowExW(None, worker, "WorkerW", None) + if not worker: + break + defview = user32.FindWindowExW(worker, None, "SHELLDLL_DefView", None) + if defview: + break + + listview = user32.FindWindowExW(defview, None, "SysListView32", None) if defview else None + return listview + +def attach_window_to_desktop_only(hwnd): + """ + 只将指定窗口挂到桌面图标窗口上,不修改窗口样式 + hwnd: 目标窗口句柄 + 返回 True/False + """ + if not hwnd: + return False + + # 获取桌面图标窗口句柄 + desktop = get_desktop_listview_hwnd() + if not desktop: + return False + + # 只设置父窗口为桌面图标窗口 + user32.SetParent(hwnd, desktop) + + return True + + +# ------------------------- +if __name__ == "__main__": + import win32gui + + # 直接用 Notepad 窗口的 NativeWindowHandle + hwnd = win32gui.FindWindow("Notepad", "无标题 - Notepad") + + if attach_window_to_desktop_only(hwnd): + print("Notepad 窗口已挂到桌面 ✅") + else: + print("挂载失败 ❌") diff --git "a/\346\241\214\351\235\242\345\210\207\346\215\242/main.py" "b/\346\241\214\351\235\242\345\210\207\346\215\242/main.py" index fc52ab2..a773bdb 100644 --- "a/\346\241\214\351\235\242\345\210\207\346\215\242/main.py" +++ "b/\346\241\214\351\235\242\345\210\207\346\215\242/main.py" @@ -1,19 +1,150 @@ -import switch_desktop -import argparse +import sys +from functools import partial -def main(): - parser = argparse.ArgumentParser(description="接收一个路径参数并切换桌面") - parser.add_argument("path", help="输入的路径") - args = parser.parse_args() +from PySide6.QtWidgets import ( + QApplication, QWidget, QHBoxLayout, + QPushButton, QFrame, QVBoxLayout, QMessageBox +) +from PySide6.QtCore import Qt, QPoint +from PySide6.QtGui import QCursor - # 直接打印参数 - print(args.path) +from desktop_dirs import get_dirs, find_index_matching_current_dir +from switch_desktop import switch_desktop_path - # 切换桌面 - if switch_desktop.switch_desktop_path(args.path): - print("✅ 桌面切换完成并刷新") - else: - print("❌ 桌面切换失败") +class DesktopWidget(QWidget): + def __init__(self, entries): + super().__init__() + + # 不进任务栏 / 不进 Win+Tab + self.setWindowFlags(Qt.FramelessWindowHint | Qt.Tool) + self.setAttribute(Qt.WA_TranslucentBackground) + + self.entries = entries + self.buttons = [] + + main_layout = QVBoxLayout(self) + main_layout.setContentsMargins(0, 0, 0, 0) + + # 背景 + self.background = QWidget() + self.background.setStyleSheet(""" + background-color: rgba(50, 50, 50, 220); + border-radius: 15px; + """) + main_layout.addWidget(self.background) + + layout = QHBoxLayout(self.background) + layout.setContentsMargins(5, 5, 5, 5) + layout.setSpacing(5) + + # 左侧拖动条 + self.drag_frame = QFrame() + self.drag_frame.setFixedWidth(25) + self.drag_frame.setStyleSheet(""" + background-color: rgba(80, 80, 80, 200); + border-radius: 10px; + """) + self.drag_frame.setCursor(QCursor(Qt.SizeAllCursor)) + layout.addWidget(self.drag_frame) + + button_height = 35 + + # 添加按钮 + for entry in entries: + btn = QPushButton(entry["name"]) + btn.setFixedHeight(button_height) + btn.setCheckable(True) + btn.setStyleSheet(""" + QPushButton { + background-color: rgba(80, 80, 80, 220); + color: white; + border-radius: 10px; + border: none; + font-size: 14px; + padding-left: 10px; + padding-right: 10px; + } + QPushButton:hover { + background-color: rgba(100, 100, 100, 220); + } + QPushButton:checked { + background-color: rgba(60, 160, 90, 230); + } + """) + layout.addWidget(btn) + self.buttons.append(btn) + btn.clicked.connect(partial(self.on_button_clicked, entry["path"], btn)) + + # 初始位置 + self.move(300, 10) + + # 拖动状态 + self._drag_active = False + self._drag_position = QPoint() + + # ---------------- 点击按钮 ---------------- + def on_button_clicked(self, path: str, btn: QPushButton): + success = switch_desktop_path(path) + + if not success: + # 切换失败,恢复状态 + btn.setChecked(False) + return + + # 切换成功,保持当前按钮选中,其他按钮取消 + for b in self.buttons: + b.setChecked(b is btn) + + # ---------------- 拖动 ---------------- + def mousePressEvent(self, event): + if ( + event.button() == Qt.LeftButton + and event.position().x() <= self.drag_frame.width() + ): + self._drag_active = True + self._drag_position = event.globalPosition().toPoint() - self.frameGeometry().topLeft() + event.accept() + + def mouseMoveEvent(self, event): + if self._drag_active: + screen = QApplication.primaryScreen().availableGeometry() + pos = event.globalPosition().toPoint() - self._drag_position + + # 限制在屏幕内 + x = max(screen.left(), min(pos.x(), screen.right() - self.width())) + y = max(screen.top(), min(pos.y(), screen.bottom() - self.height())) + + self.move(x, y) + event.accept() + + def mouseReleaseEvent(self, event): + self._drag_active = False + + +# ---------------------------- 程序入口 ---------------------------- if __name__ == "__main__": - main() + app = QApplication(sys.argv) + + entries = get_dirs() + + # 桌面没有任何可用目录 → 弹窗提示 + 退出 + if not entries: + QMessageBox.information( + None, + "提示", + "请在 用户\\桌面 目录创建你要分类的文件夹,也可以是快捷方式" + ) + sys.exit(0) + + widget = DesktopWidget(entries) + + # 获取当前桌面对应按钮索引 + index = find_index_matching_current_dir(entries) + if index is not None and 0 <= index < len(widget.buttons): + # 初始高亮 + widget.buttons[index].setChecked(True) + # 否则不高亮,但组件仍显示 + + widget.show() + sys.exit(app.exec()) diff --git "a/\346\241\214\351\235\242\345\210\207\346\215\242/main_cli.py" "b/\346\241\214\351\235\242\345\210\207\346\215\242/main_cli.py" new file mode 100644 index 0000000..fc52ab2 --- /dev/null +++ "b/\346\241\214\351\235\242\345\210\207\346\215\242/main_cli.py" @@ -0,0 +1,19 @@ +import switch_desktop +import argparse + +def main(): + parser = argparse.ArgumentParser(description="接收一个路径参数并切换桌面") + parser.add_argument("path", help="输入的路径") + args = parser.parse_args() + + # 直接打印参数 + print(args.path) + + # 切换桌面 + if switch_desktop.switch_desktop_path(args.path): + print("✅ 桌面切换完成并刷新") + else: + print("❌ 桌面切换失败") + +if __name__ == "__main__": + main() diff --git "a/\346\241\214\351\235\242\345\210\207\346\215\242/main_gui.py" "b/\346\241\214\351\235\242\345\210\207\346\215\242/main_gui.py" deleted file mode 100644 index a773bdb..0000000 --- "a/\346\241\214\351\235\242\345\210\207\346\215\242/main_gui.py" +++ /dev/null @@ -1,150 +0,0 @@ -import sys -from functools import partial - -from PySide6.QtWidgets import ( - QApplication, QWidget, QHBoxLayout, - QPushButton, QFrame, QVBoxLayout, QMessageBox -) -from PySide6.QtCore import Qt, QPoint -from PySide6.QtGui import QCursor - -from desktop_dirs import get_dirs, find_index_matching_current_dir -from switch_desktop import switch_desktop_path - - -class DesktopWidget(QWidget): - def __init__(self, entries): - super().__init__() - - # 不进任务栏 / 不进 Win+Tab - self.setWindowFlags(Qt.FramelessWindowHint | Qt.Tool) - self.setAttribute(Qt.WA_TranslucentBackground) - - self.entries = entries - self.buttons = [] - - main_layout = QVBoxLayout(self) - main_layout.setContentsMargins(0, 0, 0, 0) - - # 背景 - self.background = QWidget() - self.background.setStyleSheet(""" - background-color: rgba(50, 50, 50, 220); - border-radius: 15px; - """) - main_layout.addWidget(self.background) - - layout = QHBoxLayout(self.background) - layout.setContentsMargins(5, 5, 5, 5) - layout.setSpacing(5) - - # 左侧拖动条 - self.drag_frame = QFrame() - self.drag_frame.setFixedWidth(25) - self.drag_frame.setStyleSheet(""" - background-color: rgba(80, 80, 80, 200); - border-radius: 10px; - """) - self.drag_frame.setCursor(QCursor(Qt.SizeAllCursor)) - layout.addWidget(self.drag_frame) - - button_height = 35 - - # 添加按钮 - for entry in entries: - btn = QPushButton(entry["name"]) - btn.setFixedHeight(button_height) - btn.setCheckable(True) - btn.setStyleSheet(""" - QPushButton { - background-color: rgba(80, 80, 80, 220); - color: white; - border-radius: 10px; - border: none; - font-size: 14px; - padding-left: 10px; - padding-right: 10px; - } - QPushButton:hover { - background-color: rgba(100, 100, 100, 220); - } - QPushButton:checked { - background-color: rgba(60, 160, 90, 230); - } - """) - layout.addWidget(btn) - self.buttons.append(btn) - btn.clicked.connect(partial(self.on_button_clicked, entry["path"], btn)) - - # 初始位置 - self.move(300, 10) - - # 拖动状态 - self._drag_active = False - self._drag_position = QPoint() - - # ---------------- 点击按钮 ---------------- - def on_button_clicked(self, path: str, btn: QPushButton): - success = switch_desktop_path(path) - - if not success: - # 切换失败,恢复状态 - btn.setChecked(False) - return - - # 切换成功,保持当前按钮选中,其他按钮取消 - for b in self.buttons: - b.setChecked(b is btn) - - # ---------------- 拖动 ---------------- - def mousePressEvent(self, event): - if ( - event.button() == Qt.LeftButton - and event.position().x() <= self.drag_frame.width() - ): - self._drag_active = True - self._drag_position = event.globalPosition().toPoint() - self.frameGeometry().topLeft() - event.accept() - - def mouseMoveEvent(self, event): - if self._drag_active: - screen = QApplication.primaryScreen().availableGeometry() - pos = event.globalPosition().toPoint() - self._drag_position - - # 限制在屏幕内 - x = max(screen.left(), min(pos.x(), screen.right() - self.width())) - y = max(screen.top(), min(pos.y(), screen.bottom() - self.height())) - - self.move(x, y) - event.accept() - - def mouseReleaseEvent(self, event): - self._drag_active = False - - -# ---------------------------- 程序入口 ---------------------------- -if __name__ == "__main__": - app = QApplication(sys.argv) - - entries = get_dirs() - - # 桌面没有任何可用目录 → 弹窗提示 + 退出 - if not entries: - QMessageBox.information( - None, - "提示", - "请在 用户\\桌面 目录创建你要分类的文件夹,也可以是快捷方式" - ) - sys.exit(0) - - widget = DesktopWidget(entries) - - # 获取当前桌面对应按钮索引 - index = find_index_matching_current_dir(entries) - if index is not None and 0 <= index < len(widget.buttons): - # 初始高亮 - widget.buttons[index].setChecked(True) - # 否则不高亮,但组件仍显示 - - widget.show() - sys.exit(app.exec()) -- Gitee From ae4c7cce9ba86529b374db35d00c83707316cf4e Mon Sep 17 00:00:00 2001 From: LZY <2217445143@qq.com> Date: Mon, 9 Feb 2026 13:00:11 +0800 Subject: [PATCH 9/9] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dwin+d=E9=9A=90=E8=97=8Fbu?= =?UTF-8?q?g?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main.py" | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git "a/\346\241\214\351\235\242\345\210\207\346\215\242/main.py" "b/\346\241\214\351\235\242\345\210\207\346\215\242/main.py" index a773bdb..e558d98 100644 --- "a/\346\241\214\351\235\242\345\210\207\346\215\242/main.py" +++ "b/\346\241\214\351\235\242\345\210\207\346\215\242/main.py" @@ -8,10 +8,8 @@ from PySide6.QtWidgets import ( from PySide6.QtCore import Qt, QPoint from PySide6.QtGui import QCursor -from desktop_dirs import get_dirs, find_index_matching_current_dir from switch_desktop import switch_desktop_path - class DesktopWidget(QWidget): def __init__(self, entries): super().__init__() @@ -124,6 +122,9 @@ class DesktopWidget(QWidget): # ---------------------------- 程序入口 ---------------------------- if __name__ == "__main__": + from desktop_dirs import get_dirs, find_index_matching_current_dir + from desktop_component import attach_window_to_desktop_only + app = QApplication(sys.argv) entries = get_dirs() @@ -147,4 +148,12 @@ if __name__ == "__main__": # 否则不高亮,但组件仍显示 widget.show() + + # 获取 Qt 窗口句柄并挂到桌面 + hwnd = int(widget.winId()) # Qt 原生窗口句柄 + if attach_window_to_desktop_only(hwnd): + print("已挂到桌面 ✅") + else: + print("挂到桌面失败 ❌") + sys.exit(app.exec()) -- Gitee