From f75b78340e69166f266693b493a93fe5e5767ee7 Mon Sep 17 00:00:00 2001 From: LZY <2217445143@qq.com> Date: Tue, 10 Feb 2026 17:07:47 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E5=A5=BDgpt=EF=BC=8C=E8=BF=99=E4=B9=88?= =?UTF-8?q?=E5=BF=AB=E5=B0=B1=E5=87=BA=E4=BB=A3=E7=A0=81=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mian.py | 159 ++++++++++++++++++++++---------------------------------- 1 file changed, 63 insertions(+), 96 deletions(-) diff --git a/mian.py b/mian.py index 53c8fd0..4dc5502 100644 --- a/mian.py +++ b/mian.py @@ -1,97 +1,64 @@ -import sys +import ctypes +from ctypes import wintypes 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()) +import time + +# ---------------- WinEventHook 定义 ---------------- +user32 = ctypes.windll.user32 + +# 事件常量 +EVENT_SYSTEM_MOVESIZESTART = 0x000A # 窗口开始移动/调整大小 +EVENT_SYSTEM_MOVESIZEEND = 0x000B # 窗口移动/调整大小结束 +WINEVENT_OUTOFCONTEXT = 0x0000 # 事件在外部进程,不注入 DLL + +# 定义回调类型 +WinEventProcType = ctypes.WINFUNCTYPE( + None, wintypes.HANDLE, wintypes.DWORD, wintypes.HWND, + wintypes.LONG, wintypes.LONG, wintypes.DWORD, wintypes.DWORD +) + +# ---------------- 获取目标窗口 ---------------- +hwnd_target = win32gui.FindWindow("Notepad", "无标题 - Notepad") +if not hwnd_target: + print("Notepad window not found.") + exit() + +print(f"Monitoring Notepad HWND={hwnd_target} for drag events...") + +# ---------------- 回调函数 ---------------- +def callback(hWinEventHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime): + if hwnd != hwnd_target: + return # 只关注目标窗口 + if event == EVENT_SYSTEM_MOVESIZESTART: + print("Notepad started moving (drag start).") + elif event == EVENT_SYSTEM_MOVESIZEEND: + print("Notepad finished moving (drag end).") + +# 转成 C 风格回调 +proc = WinEventProcType(callback) + +# ---------------- 设置 WinEventHook ---------------- +hook_start = user32.SetWinEventHook( + EVENT_SYSTEM_MOVESIZESTART, + EVENT_SYSTEM_MOVESIZEEND, + 0, + proc, + 0, 0, + WINEVENT_OUTOFCONTEXT +) + +if not hook_start: + print("Failed to set WinEventHook.") + exit() + +# ---------------- 消息循环 ---------------- +try: + msg = wintypes.MSG() + while True: + while user32.PeekMessageW(ctypes.byref(msg), 0, 0, 0, 1): + user32.TranslateMessage(ctypes.byref(msg)) + user32.DispatchMessageW(ctypes.byref(msg)) + time.sleep(0.01) +except KeyboardInterrupt: + user32.UnhookWinEvent(hook_start) + print("Stopped monitoring.") -- Gitee From 089e27e91b3ef98a64cd9b99eef2863f254ed6d9 Mon Sep 17 00:00:00 2001 From: LZY <2217445143@qq.com> Date: Tue, 10 Feb 2026 17:23:32 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E7=AE=80=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mian.py | 44 ++++++++++++++++++-------------------------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/mian.py b/mian.py index 4dc5502..53b8969 100644 --- a/mian.py +++ b/mian.py @@ -1,44 +1,34 @@ import ctypes from ctypes import wintypes -import win32gui import time +import win32gui -# ---------------- WinEventHook 定义 ---------------- +# ---------------- WinEventHook ---------------- user32 = ctypes.windll.user32 -# 事件常量 -EVENT_SYSTEM_MOVESIZESTART = 0x000A # 窗口开始移动/调整大小 -EVENT_SYSTEM_MOVESIZEEND = 0x000B # 窗口移动/调整大小结束 -WINEVENT_OUTOFCONTEXT = 0x0000 # 事件在外部进程,不注入 DLL +EVENT_SYSTEM_MOVESIZESTART = 0x000A +EVENT_SYSTEM_MOVESIZEEND = 0x000B +WINEVENT_OUTOFCONTEXT = 0x0000 -# 定义回调类型 +# 回调类型 WinEventProcType = ctypes.WINFUNCTYPE( None, wintypes.HANDLE, wintypes.DWORD, wintypes.HWND, wintypes.LONG, wintypes.LONG, wintypes.DWORD, wintypes.DWORD ) -# ---------------- 获取目标窗口 ---------------- -hwnd_target = win32gui.FindWindow("Notepad", "无标题 - Notepad") -if not hwnd_target: - print("Notepad window not found.") - exit() - -print(f"Monitoring Notepad HWND={hwnd_target} for drag events...") - -# ---------------- 回调函数 ---------------- def callback(hWinEventHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime): - if hwnd != hwnd_target: - return # 只关注目标窗口 + # 不再过滤窗口可见性 + title = win32gui.GetWindowText(hwnd) if event == EVENT_SYSTEM_MOVESIZESTART: - print("Notepad started moving (drag start).") + print(f"Window started moving: HWND={hwnd}, Title='{title}'") elif event == EVENT_SYSTEM_MOVESIZEEND: - print("Notepad finished moving (drag end).") + print(f"Window finished moving: HWND={hwnd}, Title='{title}'") # 转成 C 风格回调 proc = WinEventProcType(callback) -# ---------------- 设置 WinEventHook ---------------- -hook_start = user32.SetWinEventHook( +# 注册系统范围的事件钩子 +hook = user32.SetWinEventHook( EVENT_SYSTEM_MOVESIZESTART, EVENT_SYSTEM_MOVESIZEEND, 0, @@ -47,11 +37,13 @@ hook_start = user32.SetWinEventHook( WINEVENT_OUTOFCONTEXT ) -if not hook_start: +if not hook: print("Failed to set WinEventHook.") exit() -# ---------------- 消息循环 ---------------- +print("Listening for all window drag events. Press Ctrl+C to stop.") + +# 消息循环 try: msg = wintypes.MSG() while True: @@ -60,5 +52,5 @@ try: user32.DispatchMessageW(ctypes.byref(msg)) time.sleep(0.01) except KeyboardInterrupt: - user32.UnhookWinEvent(hook_start) - print("Stopped monitoring.") + user32.UnhookWinEvent(hook) + print("Stopped listening.") -- Gitee From 9159872e611b53d83daa205f83387e581bdd40d3 Mon Sep 17 00:00:00 2001 From: LZY <2217445143@qq.com> Date: Tue, 10 Feb 2026 20:11:04 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E5=A4=87=E4=BB=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 4 + .../main.py" | 126 ++++++++++++++++++ .../wait_for_move_event.py" | 69 ++++++++++ 3 files changed, 199 insertions(+) create mode 100644 .vscode/settings.json create mode 100644 "\346\213\226\345\212\250\347\252\227\345\217\243\346\227\266\351\200\217\346\230\216/main.py" create mode 100644 "\346\213\226\345\212\250\347\252\227\345\217\243\346\227\266\351\200\217\346\230\216/wait_for_move_event.py" diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..ba2a6c0 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "python-envs.defaultEnvManager": "ms-python.python:system", + "python-envs.pythonProjects": [] +} \ No newline at end of file diff --git "a/\346\213\226\345\212\250\347\252\227\345\217\243\346\227\266\351\200\217\346\230\216/main.py" "b/\346\213\226\345\212\250\347\252\227\345\217\243\346\227\266\351\200\217\346\230\216/main.py" new file mode 100644 index 0000000..628bc1c --- /dev/null +++ "b/\346\213\226\345\212\250\347\252\227\345\217\243\346\227\266\351\200\217\346\230\216/main.py" @@ -0,0 +1,126 @@ +import ctypes +import time +from ctypes import wintypes + +# Windows API 常量 +GWL_EXSTYLE = -20 +WS_EX_LAYERED = 0x00080000 +LWA_ALPHA = 0x00000002 + +# 加载 user32.dll +user32 = ctypes.windll.user32 + + +class WindowTransparency: + """ + 窗口透明度控制器 + + Args: + hwnd: 窗口句柄 + alpha: 默认透明度 0-255,默认200 + interval: 动画间隔(秒),0为无动画直接设置,默认0 + """ + + def __init__(self, hwnd: int, alpha: int = 200, interval: float = 0): + self.hwnd = hwnd + self.alpha = alpha # 默认透明度 + self.interval = interval # 动画间隔(秒) + self._current_alpha = 255 # 当前透明度 + self._original_alpha = 255 # 记录原始透明度 + + self._ensure_layered() + + def _ensure_layered(self) -> None: + """确保窗口有 WS_EX_LAYERED 样式""" + ex_style = user32.GetWindowLongW(self.hwnd, GWL_EXSTYLE) + if not (ex_style & WS_EX_LAYERED): + user32.SetWindowLongW(self.hwnd, GWL_EXSTYLE, ex_style | WS_EX_LAYERED) + + def _animate(self, start: int, end: int, interval: float = None) -> None: + """内部动画方法""" + iv = interval if interval is not None else self.interval + + # 无动画,直接设置 + if iv <= 0: + user32.SetLayeredWindowAttributes(self.hwnd, 0, end, LWA_ALPHA) + self._current_alpha = end + return + + # 计算步数:每步变化至少1,确保平滑 + diff = abs(end - start) + steps = max(diff, 1) # 至少1步 + + for i in range(1, steps + 1): + progress = i / steps + current = int(start + (end - start) * progress) + user32.SetLayeredWindowAttributes(self.hwnd, 0, current, LWA_ALPHA) + time.sleep(iv) + + self._current_alpha = end + + def fade_to(self, target_alpha: int = None, interval: float = None) -> None: + """ + 渐变到指定透明度 + + Args: + target_alpha: 目标透明度,默认使用初始化时的alpha + interval: 动画间隔,默认使用初始化时的interval(0为无动画) + """ + target = target_alpha if target_alpha is not None else self.alpha + + # 首次设置透明度时记录原始值 + if self._original_alpha == 255 and self._current_alpha == 255: + self._original_alpha = 255 + + self._animate(self._current_alpha, target, interval) + + def fade_in(self, interval: float = None) -> None: + """淡入(透明->不透明)""" + self._animate(self._current_alpha, 255, interval) + + def fade_out(self, interval: float = None) -> None: + """淡出(不透明->透明)""" + self._animate(self._current_alpha, 0, interval) + + def fade_reset(self, interval: float = None) -> None: + """渐变回默认透明度""" + self._animate(self._current_alpha, self.alpha, interval) + + def fade_restore(self, interval: float = None) -> None: + """渐变恢复原始透明度""" + self._animate(self._current_alpha, self._original_alpha, interval) + + def set_transparent(self, alpha: int = None) -> None: + """直接设置透明度(无动画,无视interval)""" + target = alpha if alpha is not None else self.alpha + user32.SetLayeredWindowAttributes(self.hwnd, 0, target, LWA_ALPHA) + self._current_alpha = target + +if __name__ == "__main__": + import win32gui + import time + + # 示例:对记事本窗口进行透明度控制 + hwnd = win32gui.FindWindow("Notepad", "无标题 - Notepad") + if not hwnd: + print("未找到记事本窗口,请先打开记事本。") + else: + controller = WindowTransparency(hwnd, alpha=150, interval=0.01) + + print("淡出到透明...") + controller.fade_out() + time.sleep(1) + + print("淡入到默认透明度...") + controller.fade_to() + time.sleep(1) + + print("淡入到不透明...") + controller.fade_in() + time.sleep(1) + + print("恢复到原始透明度...") + controller.fade_restore() + time.sleep(1) + + print("完成。") \ No newline at end of file diff --git "a/\346\213\226\345\212\250\347\252\227\345\217\243\346\227\266\351\200\217\346\230\216/wait_for_move_event.py" "b/\346\213\226\345\212\250\347\252\227\345\217\243\346\227\266\351\200\217\346\230\216/wait_for_move_event.py" new file mode 100644 index 0000000..cc13c27 --- /dev/null +++ "b/\346\213\226\345\212\250\347\252\227\345\217\243\346\227\266\351\200\217\346\230\216/wait_for_move_event.py" @@ -0,0 +1,69 @@ +import ctypes +from ctypes import wintypes +import win32gui + +# WinEvent constants +user32 = ctypes.windll.user32 +EVENT_SYSTEM_MOVESIZESTART = 0x000A +EVENT_SYSTEM_MOVESIZEEND = 0x000B +WINEVENT_OUTOFCONTEXT = 0x0000 + +# WinEvent 回调类型 +WinEventProcType = ctypes.WINFUNCTYPE( + None, wintypes.HANDLE, wintypes.DWORD, wintypes.HWND, + wintypes.LONG, wintypes.LONG, wintypes.DWORD, wintypes.DWORD +) + +def wait_for_move_event(): + """阻塞直到检测到 MOVE/RESIZE 开始或结束事件。 + + 返回 (is_start, hwnd) + - is_start == True :检测到 EVENT_SYSTEM_MOVESIZESTART(开始拖动) + - is_start == False :检测到 EVENT_SYSTEM_MOVESIZEEND(结束/松开) + """ + result = {"evt": None, "hwnd": None} + + def _cb(hWinEventHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime): + if event == EVENT_SYSTEM_MOVESIZESTART: + result["evt"] = True + result["hwnd"] = hwnd + user32.PostQuitMessage(0) + elif event == EVENT_SYSTEM_MOVESIZEEND: + result["evt"] = False + result["hwnd"] = hwnd + user32.PostQuitMessage(0) + + proc = WinEventProcType(_cb) + + hook = user32.SetWinEventHook( + EVENT_SYSTEM_MOVESIZESTART, + EVENT_SYSTEM_MOVESIZEEND, + 0, + proc, + 0, 0, + WINEVENT_OUTOFCONTEXT + ) + + if not hook: + raise RuntimeError("SetWinEventHook failed") + + # 阻塞消息循环,直到回调中调用 PostQuitMessage + msg = wintypes.MSG() + try: + while user32.GetMessageW(ctypes.byref(msg), 0, 0, 0) != 0: + user32.TranslateMessage(ctypes.byref(msg)) + user32.DispatchMessageW(ctypes.byref(msg)) + finally: + user32.UnhookWinEvent(hook) + + return result["evt"], result["hwnd"] + + +if __name__ == "__main__": + while True: + print("Waiting for move/resize event...") + is_start, hwnd = wait_for_move_event() + if is_start: + print(f"Detected MOVE START: HWND={hwnd}") + else: + print(f"Detected MOVE END: HWND={hwnd}") -- Gitee From b2bc50dbc9c12d9de0a1514fd58a745c0773808e Mon Sep 17 00:00:00 2001 From: LZY <2217445143@qq.com> Date: Wed, 11 Feb 2026 11:05:37 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E5=A4=87=E4=BB=BD=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main.py" | 133 ++---------------- .../wait_for_move_event.py" | 1 - .../window_transparency.py" | 120 ++++++++++++++++ 3 files changed, 132 insertions(+), 122 deletions(-) create mode 100644 "\346\213\226\345\212\250\347\252\227\345\217\243\346\227\266\351\200\217\346\230\216/window_transparency.py" diff --git "a/\346\213\226\345\212\250\347\252\227\345\217\243\346\227\266\351\200\217\346\230\216/main.py" "b/\346\213\226\345\212\250\347\252\227\345\217\243\346\227\266\351\200\217\346\230\216/main.py" index 628bc1c..3351b7e 100644 --- "a/\346\213\226\345\212\250\347\252\227\345\217\243\346\227\266\351\200\217\346\230\216/main.py" +++ "b/\346\213\226\345\212\250\347\252\227\345\217\243\346\227\266\351\200\217\346\230\216/main.py" @@ -1,126 +1,17 @@ -import ctypes -import time -from ctypes import wintypes +from wait_for_move_event import wait_for_move_event +from window_transparency import WindowTransparency -# Windows API 常量 -GWL_EXSTYLE = -20 -WS_EX_LAYERED = 0x00080000 -LWA_ALPHA = 0x00000002 - -# 加载 user32.dll -user32 = ctypes.windll.user32 +while True: + is_start, hwnd = wait_for_move_event() + if is_start: + controller = WindowTransparency(hwnd, alpha=230, interval=0.005) + controller.fade_to() + else: + try: + controller.fade_in() + except NameError: + pass -class WindowTransparency: - """ - 窗口透明度控制器 - - Args: - hwnd: 窗口句柄 - alpha: 默认透明度 0-255,默认200 - interval: 动画间隔(秒),0为无动画直接设置,默认0 - """ - - def __init__(self, hwnd: int, alpha: int = 200, interval: float = 0): - self.hwnd = hwnd - self.alpha = alpha # 默认透明度 - self.interval = interval # 动画间隔(秒) - self._current_alpha = 255 # 当前透明度 - self._original_alpha = 255 # 记录原始透明度 - - self._ensure_layered() - - def _ensure_layered(self) -> None: - """确保窗口有 WS_EX_LAYERED 样式""" - ex_style = user32.GetWindowLongW(self.hwnd, GWL_EXSTYLE) - if not (ex_style & WS_EX_LAYERED): - user32.SetWindowLongW(self.hwnd, GWL_EXSTYLE, ex_style | WS_EX_LAYERED) - - def _animate(self, start: int, end: int, interval: float = None) -> None: - """内部动画方法""" - iv = interval if interval is not None else self.interval - - # 无动画,直接设置 - if iv <= 0: - user32.SetLayeredWindowAttributes(self.hwnd, 0, end, LWA_ALPHA) - self._current_alpha = end - return - - # 计算步数:每步变化至少1,确保平滑 - diff = abs(end - start) - steps = max(diff, 1) # 至少1步 - - for i in range(1, steps + 1): - progress = i / steps - current = int(start + (end - start) * progress) - user32.SetLayeredWindowAttributes(self.hwnd, 0, current, LWA_ALPHA) - time.sleep(iv) - - self._current_alpha = end - - def fade_to(self, target_alpha: int = None, interval: float = None) -> None: - """ - 渐变到指定透明度 - - Args: - target_alpha: 目标透明度,默认使用初始化时的alpha - interval: 动画间隔,默认使用初始化时的interval(0为无动画) - """ - target = target_alpha if target_alpha is not None else self.alpha - - # 首次设置透明度时记录原始值 - if self._original_alpha == 255 and self._current_alpha == 255: - self._original_alpha = 255 - - self._animate(self._current_alpha, target, interval) - - def fade_in(self, interval: float = None) -> None: - """淡入(透明->不透明)""" - self._animate(self._current_alpha, 255, interval) - - def fade_out(self, interval: float = None) -> None: - """淡出(不透明->透明)""" - self._animate(self._current_alpha, 0, interval) - - def fade_reset(self, interval: float = None) -> None: - """渐变回默认透明度""" - self._animate(self._current_alpha, self.alpha, interval) - - def fade_restore(self, interval: float = None) -> None: - """渐变恢复原始透明度""" - self._animate(self._current_alpha, self._original_alpha, interval) - - def set_transparent(self, alpha: int = None) -> None: - """直接设置透明度(无动画,无视interval)""" - target = alpha if alpha is not None else self.alpha - user32.SetLayeredWindowAttributes(self.hwnd, 0, target, LWA_ALPHA) - self._current_alpha = target -if __name__ == "__main__": - import win32gui - import time - # 示例:对记事本窗口进行透明度控制 - hwnd = win32gui.FindWindow("Notepad", "无标题 - Notepad") - if not hwnd: - print("未找到记事本窗口,请先打开记事本。") - else: - controller = WindowTransparency(hwnd, alpha=150, interval=0.01) - - print("淡出到透明...") - controller.fade_out() - time.sleep(1) - - print("淡入到默认透明度...") - controller.fade_to() - time.sleep(1) - - print("淡入到不透明...") - controller.fade_in() - time.sleep(1) - - print("恢复到原始透明度...") - controller.fade_restore() - time.sleep(1) - - print("完成。") \ No newline at end of file diff --git "a/\346\213\226\345\212\250\347\252\227\345\217\243\346\227\266\351\200\217\346\230\216/wait_for_move_event.py" "b/\346\213\226\345\212\250\347\252\227\345\217\243\346\227\266\351\200\217\346\230\216/wait_for_move_event.py" index cc13c27..9f0d01f 100644 --- "a/\346\213\226\345\212\250\347\252\227\345\217\243\346\227\266\351\200\217\346\230\216/wait_for_move_event.py" +++ "b/\346\213\226\345\212\250\347\252\227\345\217\243\346\227\266\351\200\217\346\230\216/wait_for_move_event.py" @@ -1,6 +1,5 @@ import ctypes from ctypes import wintypes -import win32gui # WinEvent constants user32 = ctypes.windll.user32 diff --git "a/\346\213\226\345\212\250\347\252\227\345\217\243\346\227\266\351\200\217\346\230\216/window_transparency.py" "b/\346\213\226\345\212\250\347\252\227\345\217\243\346\227\266\351\200\217\346\230\216/window_transparency.py" new file mode 100644 index 0000000..8767b47 --- /dev/null +++ "b/\346\213\226\345\212\250\347\252\227\345\217\243\346\227\266\351\200\217\346\230\216/window_transparency.py" @@ -0,0 +1,120 @@ +import ctypes +import time + +# Windows API 常量 +GWL_EXSTYLE = -20 +WS_EX_LAYERED = 0x00080000 +LWA_ALPHA = 0x00000002 + +# 加载 user32.dll +user32 = ctypes.windll.user32 + + +class WindowTransparency: + """ + 窗口透明度控制器 + + Args: + hwnd: 窗口句柄 + alpha: 默认透明度 0-255,默认200 + interval: 动画间隔(秒),0为无动画直接设置,默认0 + """ + + def __init__(self, hwnd: int, alpha: int = 200, interval: float = 0.002): + self.hwnd = hwnd + self.alpha = alpha # 默认透明度 + self.interval = interval # 动画间隔(秒) + self._current_alpha = 255 # 当前透明度 + self._original_alpha = 255 # 记录原始透明度 + + self._ensure_layered() + + def _ensure_layered(self) -> None: + """确保窗口有 WS_EX_LAYERED 样式""" + ex_style = user32.GetWindowLongW(self.hwnd, GWL_EXSTYLE) + if not (ex_style & WS_EX_LAYERED): + user32.SetWindowLongW(self.hwnd, GWL_EXSTYLE, ex_style | WS_EX_LAYERED) + + def _animate(self, start: int, end: int, interval: float = None) -> None: + """内部动画方法""" + iv = interval if interval is not None else self.interval + + # 无动画,直接设置 + if iv <= 0: + user32.SetLayeredWindowAttributes(self.hwnd, 0, end, LWA_ALPHA) + self._current_alpha = end + return + + # 计算步数:每步变化至少1,确保平滑 + diff = abs(end - start) + steps = max(diff, 1) # 至少1步 + + for i in range(1, steps + 1): + progress = i / steps + current = int(start + (end - start) * progress) + user32.SetLayeredWindowAttributes(self.hwnd, 0, current, LWA_ALPHA) + time.sleep(iv) + + self._current_alpha = end + + def fade_to(self, target_alpha: int = None, interval: float = None) -> None: + """ + 渐变到指定透明度 + + Args: + target_alpha: 目标透明度,默认使用初始化时的alpha + interval: 动画间隔,默认使用初始化时的interval(0为无动画) + """ + target = target_alpha if target_alpha is not None else self.alpha + + # 首次设置透明度时记录原始值 + if self._original_alpha == 255 and self._current_alpha == 255: + self._original_alpha = 255 + + self._animate(self._current_alpha, target, interval) + + def fade_in(self, interval: float = None) -> None: + """淡入(透明->不透明)""" + self._animate(self._current_alpha, 255, interval) + + def fade_out(self, interval: float = None) -> None: + """淡出(不透明->透明)""" + self._animate(self._current_alpha, 0, interval) + + def fade_reset(self, interval: float = None) -> None: + """渐变回默认透明度""" + self._animate(self._current_alpha, self.alpha, interval) + + def fade_restore(self, interval: float = None) -> None: + """渐变恢复原始透明度""" + self._animate(self._current_alpha, self._original_alpha, interval) + + def set_transparent(self, alpha: int = None) -> None: + """直接设置透明度(无动画,无视interval)""" + target = alpha if alpha is not None else self.alpha + user32.SetLayeredWindowAttributes(self.hwnd, 0, target, LWA_ALPHA) + self._current_alpha = target + +if __name__ == "__main__": + import win32gui + + # 示例:对记事本窗口进行透明度控制 + hwnd = win32gui.FindWindow("Notepad", "无标题 - Notepad") + if not hwnd: + print("未找到记事本窗口,请先打开记事本。") + else: + controller = WindowTransparency(hwnd, alpha=150, interval=0.002) + + print("淡入到默认透明度...") + controller.fade_to() + time.sleep(1) + + print("淡入到不透明...") + controller.fade_in() + time.sleep(1) + + print("恢复到原始透明度...") + controller.fade_restore() + time.sleep(1) + + print("完成。") \ No newline at end of file -- Gitee From 9263a0d558e33a79e7896c5e07b9c45cba22e8c4 Mon Sep 17 00:00:00 2001 From: LZY <2217445143@qq.com> Date: Wed, 11 Feb 2026 16:15:47 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=A1=B9=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 55 ++++++++--- pyproject.toml | 7 +- ...11\347\262\230\350\264\264\351\224\256.py" | 0 ...55\350\213\261\346\217\220\347\244\272.py" | 0 ...72\345\237\237\346\243\200\346\265\213.py" | 1 - .../\345\267\246\344\270\212\350\247\222.py" | 0 ...3\345\214\205\345\221\275\344\273\244.txt" | 1 - "\350\257\225\351\252\214main.py" | 98 ------------------- 8 files changed, 46 insertions(+), 116 deletions(-) rename "src/\345\205\250\351\200\211\347\262\230\350\264\264\351\224\256.py" => "\345\205\266\344\273\226/\345\205\250\351\200\211\347\262\230\350\264\264\351\224\256.py" (100%) rename "src/\350\276\223\345\205\245\346\263\225\344\270\255\350\213\261\346\217\220\347\244\272.py" => "\345\205\266\344\273\226/\350\276\223\345\205\245\346\263\225\344\270\255\350\213\261\346\217\220\347\244\272.py" (100%) rename "src/lib/\345\214\272\345\237\237\346\243\200\346\265\213.py" => "\345\267\246\344\270\212\350\247\222/\345\214\272\345\237\237\346\243\200\346\265\213.py" (98%) rename "src/\345\267\246\344\270\212\350\247\222.py" => "\345\267\246\344\270\212\350\247\222/\345\267\246\344\270\212\350\247\222.py" (100%) delete mode 100644 "\346\211\223\345\214\205\345\221\275\344\273\244.txt" delete mode 100644 "\350\257\225\351\252\214main.py" diff --git a/README.md b/README.md index 76f8170..8d857aa 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,57 @@ # Windows-optimization [![star](https://gitee.com/LZY4/Windows-optimization/badge/star.svg?theme=dark)](https://gitee.com/LZY4/Windows-optimization/stargazers) [![GitHub](https://img.shields.io/github/stars/cnlnr/Windows-optimization)](https://github.com/cnlnr/Windows-optimization) + 此项目专门用于 Windows 系统的优化 -项目还在完善中 +## 安装 + +本项目没有打包 exe 需要使用 [Python](https://www.python.org/) 才能运行 + +下载: ---- +记得回来看一下有没有新版本 -桌面切换器已经开发的差不多了,请在 https://gitee.com/LZY4/Windows-optimization/releases 里下载 +### 安装依赖 -如果你想将应用开机自启动,请在文件管理器输入 `启动` 地址将 exe 放在里面 +```shell +python -m pip install -e . -i https://pypi.tuna.tsinghua.edu.cn/simple +``` -如果你想关闭应用,请按住 `Alt` + `F4` 快捷键 +### 开机自启动 -新增功能:自然排序,使用 `1_文件` `2_文件` 排序,会自动去掉前缀 +打开文件资源管理器,地址栏输入 `启动` 将启动脚本以及快捷键放到里面 ---- +## 反馈 -正在寻找共同维护人员,请 Issues 联系我 +如果你发现了一些 Bug 或想提出一些意见和功能,请新建一个 [Issues](https://gitee.com/LZY4/Windows-optimization/issues) -如果报错可能是因为缺少依赖库,请根据错误手动安装 +## 二次开发 -使用的开源项目: +请声明使用或参考了此项目 -https://github.com/MScholtes/VirtualDesktop +## 支持 -https://github.com/boppreh/keyboard +帮忙点个 Star ,或赞赏一些 ❤️ -... \ No newline at end of file +```test + █▀▀▀▀▀▀▀█▀██▀███▀▀██▀▀▀▀▀█▀█▀██▀▀▀▀▀▀▀█ + █ █▀▀▀█ █ ▄█ ██▀▀█ █ ▀▀▄ ███ █▀▀▀█ █ + █ █ █ █▀▄ ▄▀▀▀ ▄█▀██▄█▀▄█▀█▀█ █ █ █ █▀▀▀▀▀▀▀██▀██▀█▀███▀▀███▀██▀▀▀▀▀▀▀█ + █ ▀▀▀▀▀ █▀█ █▀▄▀▄ █▀█▀█▀▄ █ █ █ ▀▀▀▀▀ █ █ █▀▀▀█ █▀ ▄▀██▀ █▄█ ██▄█ █▀▀▀█ █ + █▀██▀▀▀▀▀▀██▄█▀███▄▄█▄▀███▄█ ▀▀██▀█▀▀▀█ █ █ █ █ ██▄▄█▀ ▀▀▄▄▀▄█ ▀█ █ █ █ + ███ █ ▄▀█▀▀█ █▄ ▀ ▄▄▀▀▀ ▀█ ▀▀██▀ ▄▀█ █ ▀▀▀▀▀ █ █▀█▀█▀█▀▄▀▄▀▄▀█▀█ ▀▀▀▀▀ █ + █▀█▄▄ ▀█▄▄▄▄▄ ▀▄▄█▄▄██▀▄█ ▀█ ▀ ▄█▄ ▄█ █▀█▀▀▀▀▀█▄██ ▀▀▀█ ▀█ ▄▄ ▀ █▀▀▀▀▀███ + █ █ ██ ▀██ ▄▀██▄ █▀▀█▀▄▄▀▄█ ▀▄█▀ ▀▀ ▀█ ███▄▄ ▀▀█ ▄▄ ▄ ▀█ ▄▄ █ ▄██▄▄▀▄ ▀▄█ + █▄▀▄▀ ▄▀█▀██▀ ▄▄▄▀▀▀ █ ▄▀▄█▀▄▀█▄█ ▄█ █▄ ▀█ █▀██▀█▀▀▄▀ ▀▄▄ ▀▀█▄▄▄█ ▄ ██ + █▄▄ ▀█▀█▀▀▀▄▄ ▄█▀ ▀▀█▀▄▀ █ ▀▀ ▀▀ ▄█▀█ █ ▄██ ▄▀▀▀ ▄▄███ ▀▀▄█▀ █▄▄ ▀█▄▄ ▄█ + █▀ █ ▄ ▀▀▀ ██▄▄▀█ ██▄▀▄ ▀▀ ▀ ▄▀▄▀ ▀█ ██▄▄▀▀ ▀█▀█▀███▀ ▀▀▄██▄▀█▀ ▄▀▀ ▄█▀█ + ██▀█▄▄▀▀█▀█▄▄▄▄▀ █▄▄██▄▀▀██▄▀▀▄ █▄▀▀▄ █ █▄ ▀ ▄▀▄▀ ▄▄▄ ▀▀█ ▄ █▄▀ ▄ ▀▄ ▀▄█ + █ ▀▄█▄▀▀ █ ▄▀ ██ ▄▀▄▀ ██▀█▀▄▄▀▄▀▄▀▀▄███ █ ▀▄▄▄▀██▀ ▄█▀█ ██▀▄█ ▄ █ █▄ ▄█ █ + █ ▀▀▄█▀█▄▀▄█▀▄▀▀█▀ ▀▀▀▀▄▄▀ ▀▄█▀▀ ▄▀ ▀█ █ ██▄▄ ▀█ ▀ ▀▄▄ ▄▄ ▀▀▄ ▄▄▄▄▄█▀ ▄▀▄█ + █ ██ ▄ ▀▄▀█▀ ▄▀▄▀ ██▄█▀▀█ █▄▀ ▀ █ ▀██ █ █▄▄█▀▀ ▀▄▀▄ █▀█ ▀█ ▄▄ ▄▀ ▀ ▀▄▄ ▀█ + █▀▀▀▀▀▀▀█ ▀ █▀▄▀█ ▄ ▀█ ▄ █▀█ ▄█▄ █ █▀▀▀▀▀▀▀█▄▄▀██ ▀▀ █▄▄█ ▀ █▀█ █ ▀▄█ + █ █▀▀▀█ █ ▀▀▄█ █▀▀▀█▄▄█▄▀ ▀▀▀ ▀██ █ █ █▀▀▀█ █ ▀▄▀██ ▀▄▄ ▀▀█ ▀▀▀ ▄█▄█ + █ █ █ █▄█▀ ▀▀███▀█▄ ▄ █ ▄ ▄▀▀ ▄█ █ █ █ █ █ ▄▀▄▀ ▀▄ █▀▀██▀ ▀▀▄███▄█ + █ ▀▀▀▀▀ █▀ ▄ ▀█ ▄█▄▄█▄▀▄██▀▄▄▀█▀▄▄ ▄▄ █ █ ▀▀▀▀▀ █▀ ▀▀▀▄█ ▀▀ ██▄▄▀▀▀▄▀▄ ▄▀██ + ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ + 微信支付 支付宝 +``` diff --git a/pyproject.toml b/pyproject.toml index 3bf417d..33b2407 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,8 +4,9 @@ build-backend = "setuptools.build_meta" [project] name = "Windows-optimization" -version = "0.0.1" # ✅ 版本号必须有,已经正确 -dependencies = ["keyboard", "PySide6"] # ✅ 只放 Python 依赖 +version = "0.0.1" +dependencies = ["keyboard", "PySide6","pynput", "natsort", "pywin32"] +classifiers = ["Operating System :: Microsoft :: Windows"] [tool.setuptools.packages.find] -where = ["src/lib"] \ No newline at end of file +where = ["."] diff --git "a/src/\345\205\250\351\200\211\347\262\230\350\264\264\351\224\256.py" "b/\345\205\266\344\273\226/\345\205\250\351\200\211\347\262\230\350\264\264\351\224\256.py" similarity index 100% rename from "src/\345\205\250\351\200\211\347\262\230\350\264\264\351\224\256.py" rename to "\345\205\266\344\273\226/\345\205\250\351\200\211\347\262\230\350\264\264\351\224\256.py" diff --git "a/src/\350\276\223\345\205\245\346\263\225\344\270\255\350\213\261\346\217\220\347\244\272.py" "b/\345\205\266\344\273\226/\350\276\223\345\205\245\346\263\225\344\270\255\350\213\261\346\217\220\347\244\272.py" similarity index 100% rename from "src/\350\276\223\345\205\245\346\263\225\344\270\255\350\213\261\346\217\220\347\244\272.py" rename to "\345\205\266\344\273\226/\350\276\223\345\205\245\346\263\225\344\270\255\350\213\261\346\217\220\347\244\272.py" diff --git "a/src/lib/\345\214\272\345\237\237\346\243\200\346\265\213.py" "b/\345\267\246\344\270\212\350\247\222/\345\214\272\345\237\237\346\243\200\346\265\213.py" similarity index 98% rename from "src/lib/\345\214\272\345\237\237\346\243\200\346\265\213.py" rename to "\345\267\246\344\270\212\350\247\222/\345\214\272\345\237\237\346\243\200\346\265\213.py" index 165807d..f02cc9b 100644 --- "a/src/lib/\345\214\272\345\237\237\346\243\200\346\265\213.py" +++ "b/\345\267\246\344\270\212\350\247\222/\345\214\272\345\237\237\346\243\200\346\265\213.py" @@ -1,5 +1,4 @@ import ctypes -from ctypes import wintypes import time # 导入Windows API函数 diff --git "a/src/\345\267\246\344\270\212\350\247\222.py" "b/\345\267\246\344\270\212\350\247\222/\345\267\246\344\270\212\350\247\222.py" similarity index 100% rename from "src/\345\267\246\344\270\212\350\247\222.py" rename to "\345\267\246\344\270\212\350\247\222/\345\267\246\344\270\212\350\247\222.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" deleted file mode 100644 index a34904e..0000000 --- "a/\346\211\223\345\214\205\345\221\275\344\273\244.txt" +++ /dev/null @@ -1 +0,0 @@ -pyinstaller --name "桌面切换器" --windowed --onefile --icon "C:\Users\lqvsy\桌面\1_Work\logo.jpg" "C:\Users\lqvsy\桌面\1_Work\Windows-optimization\桌面切换\main.py" diff --git "a/\350\257\225\351\252\214main.py" "b/\350\257\225\351\252\214main.py" deleted file mode 100644 index cd2e308..0000000 --- "a/\350\257\225\351\252\214main.py" +++ /dev/null @@ -1,98 +0,0 @@ -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