Исправления бага при перетаскивании файлов из архива на рабочий стол в Windows 11
Давно уже бесило то, что элементы всегда попадали не в то место, куда ты указал мышкой. Только при ручном нажатии обновить файл/папка вставала на своё место. Это конечно ужас, и нервы лопнули. При помощи Chat-GPT написал хоть и костыльный, но рабочий фикс!
Перерыл весь тырнет в поисках решения, но блин, что-то вообще глухо! Ни на Reddit, ни на всяких гик-форумах – нифига не нашёл. Как будто всем кроме меня пофиг на этот баг..
Скрипт вроде как корректно работает. Проверялся разными способами. Если будут баги (двусмысленно хех), то пишите.
Демонстрация бага и его исправление
UPD: Сделал также версию для C++ в виде одного exe файла без зависимостей (исходники прилагаются):
Работает на python. Необходимо установить библиотеки:
pip install watchdog pywin32 pystray pillow
В некоторых случаях: py -m pip install watchdog pywin32 pystray pillow
import os
import time
import threading
import argparse
import tkinter as tk
from tkinter import scrolledtext
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import win32gui
import ctypes
# для трея
import pystray
from PIL import Image, ImageDraw
DESKTOP_PATH = os.path.join(os.path.expanduser("~"), "Desktop")
WM_COMMAND = 0x111
DESKTOP_REFRESH = 28931 # то самое, что F5 делает в explorer
def get_desktop_shellview():
# ищем Progman
hProgman = win32gui.FindWindow("Progman", None)
hShellView = None
# ищем WorkerW, пока не найдём SHELLDLL_DefView
hWorker = win32gui.FindWindowEx(0, 0, "WorkerW", None)
while hWorker:
hShellView = win32gui.FindWindowEx(hWorker, 0, "SHELLDLL_DefView", None)
if hShellView:
break
hWorker = win32gui.FindWindowEx(0, hWorker, "WorkerW", None)
# если не нашли в WorkerW, пробуем Progman
if not hShellView:
hShellView = win32gui.FindWindowEx(hProgman, 0, "SHELLDLL_DefView", None)
return hShellView
def refresh_desktop_fast(log_widget=None):
hShellView = get_desktop_shellview()
if hShellView:
win32gui.PostMessage(hShellView, WM_COMMAND, DESKTOP_REFRESH, 0)
_log("рабочий стол обновлён мгновенно (WM_COMMAND Refresh)", log_widget)
else:
_log("не удалось найти SHELLDLL_DefView рабочего стола", log_widget)
def _log(msg, log_widget=None):
print(msg)
if log_widget:
log_widget.insert(tk.END, msg + "\n")
log_widget.see(tk.END)
class DesktopHandler(FileSystemEventHandler):
def __init__(self, log_widget=None):
self.log_widget = log_widget
self.file_times = {}
def _log(self, msg):
print(msg)
if self.log_widget:
self.log_widget.insert(tk.END, msg + "\n")
self.log_widget.see(tk.END)
def on_created(self, event):
if event.is_directory:
self._log(f"Папка создана: {event.src_path}")
else:
self._log(f"Файл создан: {event.src_path}")
refresh_desktop_fast(self.log_widget)
self.file_times[event.src_path] = time.time()
def start_observer(log_widget=None):
event_handler = DesktopHandler(log_widget)
observer = Observer()
observer.schedule(event_handler, DESKTOP_PATH, recursive=False)
observer.start()
return observer
def run_gui():
root = tk.Tk()
root.title("Desktop Watcher")
root.geometry("600x400")
log_widget = scrolledtext.ScrolledText(root, state='normal')
log_widget.pack(expand=True, fill='both')
observer = start_observer(log_widget)
def on_close():
observer.stop()
observer.join()
root.destroy()
root.protocol("WM_DELETE_WINDOW", on_close)
root.mainloop()
def run_tray():
observer = start_observer()
def stop_observer(icon, item):
observer.stop()
observer.join()
icon.stop()
def create_image():
img = Image.new("RGB", (64, 64), (50, 50, 50))
d = ImageDraw.Draw(img)
d.rectangle([16, 16, 48, 48], fill=(200, 200, 200))
return img
menu = pystray.Menu(pystray.MenuItem("Выход", stop_observer))
icon = pystray.Icon("desktop_watcher", create_image(), "Desktop Watcher", menu)
icon.run()
def run_silent():
observer = start_observer()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("-enable_tray", action="store_true", help="Включить режим трея")
parser.add_argument("-enable_gui", action="store_true", help="Включить GUI")
args = parser.parse_args()
if args.enable_gui:
run_gui()
elif args.enable_tray:
run_tray()
else:
run_silent()
P.S. Оставлю перевод на инглиш для индексации в гугле. Мало ли, какой нить американец найдёт это решение:
Python script for fix bug drag&drop from archive to Desktop
It's been driving me crazy for a long time that elements always ended up in a different place than where you pointed with the mouse. Only when you manually clicked "update" would the file/folder get back into place. This is of course horrible, and my nerves snapped. Using Chat-GPT, I wrote a hacky, but working fix!