mi dai questo script commentandolo nel codice:

import time
import threading
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import psutil
from pywinauto import Application
import win32gui
import win32con
import win32process
import os
import ctypes
import uuid
import sqlite3

Per tray icon
import pystray
from PIL import Image, ImageDraw

DB_FILE = 'gestione_aziende_adempimenti.db'

Globals
pid_to_unique_id = {}
unique_id_to_save_data = {}
handled_hwnds = set()
exit_flag = False

Tray icon functions
def create_image():
width = 16
height = 16
color1 = "black"
color2 = "white"
image = Image.new('RGB', (width, height), color1)
dc = ImageDraw.Draw(image)
dc.rectangle([(width // 4, height // 4), (width * 3 // 4, height * 3 // 4)], fill=color2)
return image

def on_quit(icon, item):
global exit_flag
exit_flag = True
icon.stop()

def setup_tray_icon():
icon = pystray.Icon("SaveAsMonitor")
icon.icon = create_image()
icon.title = "SaveAs Monitor"
icon.menu = pystray.Menu(pystray.MenuItem("Esci", on_quit))
return icon

def hide_window(hwnd):
win32gui.ShowWindow(hwnd, win32con.SW_HIDE)

def show_window(hwnd):
win32gui.ShowWindow(hwnd, win32con.SW_SHOW)

def bring_to_front(hwnd):
try:
win32gui.SetForegroundWindow(hwnd)
except Exception:
pass

DB functions
def fetch_aziende_for_gui():
conn = sqlite3.connect(DB_FILE)
c = conn.cursor()
c.execute("SELECT codice, denominazione FROM aziende ORDER BY denominazione")
rows = c.fetchall()
conn.close()
return rows

def fetch_adempimenti_for_gui():
conn = sqlite3.connect(DB_FILE)
c = conn.cursor()
c.execute("SELECT codice_adempimento, descrizione, cartella_salvataggio, IFNULL(nome_file,'') FROM adempimenti ORDER BY descrizione")
rows = c.fetchall()
conn.close()
return rows

def fetch_file_by_path(percorso):
conn = sqlite3.connect(DB_FILE)
c = conn.cursor()
c.execute('SELECT codice_azienda, codice_adempimento FROM files WHERE percorso_file = ?', (percorso,))
row = c.fetchone()
conn.close()
return row

def inserisci_file_db(codice_azienda, codice_adempimento, percorso_file):
conn = sqlite3.connect(DB_FILE)
c = conn.cursor()
try:
c.execute("INSERT INTO files (codice_azienda, codice_adempimento, percorso_file) VALUES (?, ?, ?)",
(codice_azienda, codice_adempimento, percorso_file))
conn.commit()
except sqlite3.IntegrityError:
# Ignora duplicati oppure aggiorna se vuoi
pass
finally:
conn.close()

Custom save GUI
def custom_save_gui(default_ext, file_types, default_name, initial_folder=None):
root = tk.Tk()
root.title("Salvataggio personalizzato")
root.geometry("700x250")
root.attributes("-topmost", True)


selezionato = {'full_path': None}
cancelled = {'value': True}

aziende = fetch_aziende_for_gui()
adempimenti = fetch_adempimenti_for_gui()

var_azienda = tk.StringVar()
var_adempimento = tk.StringVar()
var_folder = tk.StringVar()
var_filename = tk.StringVar(value=default_name)

full_path = None
if initial_folder and default_name:
    full_path = os.path.normpath(os.path.join(initial_folder, default_name))

preselected_azienda_cod = None
preselected_adempimento_cod = None
if full_path:
    found = fetch_file_by_path(full_path)
    if found:
        preselected_azienda_cod, preselected_adempimento_cod = found

def get_azienda_name(cod):
    for a in aziende:
        if a[0] == cod:
            return a[1]
    return ""

def get_adempimento_name(cod):
    for a in adempimenti:
        if a[0] == cod:
            return a[1]
    return ""

var_azienda.set(get_azienda_name(preselected_azienda_cod) if preselected_azienda_cod else (aziende[0][1] if aziende else ""))
var_adempimento.set(get_adempimento_name(preselected_adempimento_cod) if preselected_adempimento_cod else (adempimenti[0][1] if adempimenti else ""))

def aggiorna_percorso(*args):
    try:
        azienda_selezionata = next(a for a in aziende if a[1] == var_azienda.get())
        codice_az = azienda_selezionata[0]

        ademp_selezionato = next(a for a in adempimenti if a[1] == var_adempimento.get())
        codice_ad, descrizione_ad, cartella_salvataggio, nome_file = ademp_selezionato

        conn = sqlite3.connect(DB_FILE)
        c = conn.cursor()
        c.execute("SELECT root FROM aziende WHERE codice=?", (codice_az,))
        root_path = c.fetchone()
        conn.close()
        root_path = root_path[0] if root_path else os.getcwd()

        full_folder_path = os.path.join(root_path, cartella_salvataggio)
        os.makedirs(full_folder_path, exist_ok=True)

        var_folder.set(full_folder_path)

        filename = nome_file if nome_file.strip() else default_name
        if not filename.lower().endswith(default_ext.lower()):
            filename += default_ext

        var_filename.set(filename)
    except StopIteration:
        pass

def scegli_cartella_manual():
    folder_selected = filedialog.askdirectory(initialdir=var_folder.get() or os.getcwd())
    if folder_selected:
        var_folder.set(folder_selected)

def conferma(event=None):
    folder = var_folder.get()
    filename = var_filename.get()
    if not folder or not filename:
        messagebox.showerror("Errore", "Cartella e nome file sono obbligatori")
        return
    selezionato['full_path'] = os.path.normpath(os.path.join(folder, filename))
    cancelled['value'] = False
    root.destroy()

def on_close():
    cancelled['value'] = True
    root.destroy()

tk.Label(root, text="Azienda:").pack(anchor='w', padx=10, pady=(10, 0))
combo_aziende = ttk.Combobox(root, values=[a[1] for a in aziende], textvariable=var_azienda, state='readonly')
combo_aziende.pack(fill='x', padx=10)

tk.Label(root, text="Adempimento:").pack(anchor='w', padx=10, pady=(10, 0))
combo_adempimenti = ttk.Combobox(root, values=[a[1] for a in adempimenti], textvariable=var_adempimento, state='readonly')
combo_adempimenti.pack(fill='x', padx=10)

tk.Label(root, text="Cartella di destinazione:").pack(anchor='w', padx=10, pady=(10, 0))
folder_entry = tk.Entry(root, textvariable=var_folder, width=80)
folder_entry.pack(side='left', padx=(10, 0), pady=5, fill='x', expand=True)
btn_folder = tk.Button(root, text="Scegli cartella", command=scegli_cartella_manual)
btn_folder.pack(side='left', padx=10, pady=5)

tk.Label(root, text="Nome file:").pack(anchor='w', padx=10, pady=(10, 0))
filename_entry = tk.Entry(root, textvariable=var_filename, width=80)
filename_entry.pack(padx=10, pady=5, fill="x")

btn_conferma = tk.Button(root, text="Conferma", command=conferma)
btn_conferma.pack(pady=10)

root.protocol("WM_DELETE_WINDOW", on_close)

aggiorna_percorso()
var_azienda.trace_add('write', aggiorna_percorso)
var_adempimento.trace_add('write', aggiorna_percorso)

filename_entry.bind('<Return>', conferma)
folder_entry.bind('<Return>', conferma)

filename_entry.focus_set()
root.focus_force()
root.mainloop()

if cancelled['value']:
    return None, None, None

return selezionato['full_path'], \
       next(a[0] for a in aziende if a[1] == var_azienda.get()), \
       next(a[0] for a in adempimenti if a[1] == var_adempimento.get())
#---- Funzioni ausiliarie usate dal monitoraggio ----

def click_button_fallback_hwnd(hwnd_button):
try:
win32gui.SendMessage(hwnd_button, win32con.BM_CLICK, 0, 0)
except Exception:
pass

def enumerate_child_windows(hwnd):
children = []
def enum_proc(child_hwnd, param):
param.append(child_hwnd)
return True
win32gui.EnumChildWindows(hwnd, enum_proc, children)
return children

def detect_default_extension(process_name):
process_name = process_name.lower() if process_name else ""


mapping = {
    "winword.exe": ".docx",
    "excel.exe": ".xlsx",
    "powerpnt.exe": ".pptx",
    "onenote.exe": ".one",
    "msaccess.exe": ".accdb",
    "outlook.exe": ".pst",
    "swriter.exe": ".odt",
    "scalc.exe": ".ods",
    "simpress.exe": ".odp",
    "soffice.bin": ".odt",
    "acrord32.exe": ".pdf",
    "acrobat.exe": ".pdf",
    "photoshop.exe": ".psd",
    "illustrator.exe": ".ai",
    "chrome.exe": ".html",
    "firefox.exe": ".html",
    "msedge.exe": ".html",
    "opera.exe": ".html",
    "brave.exe": ".html",
    "notepad.exe": ".txt",
    "notepad++.exe": ".txt",
    "sublime_text.exe": ".txt",
    "code.exe": ".txt",
    "vim.exe": ".txt",
    "mspaint.exe": ".png",
    "paint.exe": ".png",
    "gimp.exe": ".xcf",
    "inkscape.exe": ".svg",
    "vlc.exe": ".m3u",
    "audacity.exe": ".aup",
    "spotify.exe": ".dat",
    "7z.exe": ".7z",
    "winrar.exe": ".rar",
    "winzip.exe": ".zip",
    "wordpad.exe": ".rtf",
    "calc.exe": ".txt",
}

return mapping.get(process_name, ".dat")
def wait_for_modal_dialog_closed(pid, parent_hwnd, timeout=30):
keywords = ["conferma", "sovrascrivi", "attenzione", "avviso", "replace", "overwrite", "confirm", "already exists"]
user32 = ctypes.windll.user32
end_time = time.time() + timeout


while time.time() < end_time and not exit_flag:
    found = False

    def enum_windows_callback(hwnd, lParam):
        if not user32.IsWindowVisible(hwnd):
            return True
        style = user32.GetWindowLongW(hwnd, win32con.GWL_STYLE)
        if not (style & win32con.WS_POPUP):
            return True
        owner = user32.GetWindow(hwnd, win32con.GW_OWNER)
        if owner != parent_hwnd:
            return True
        length = user32.GetWindowTextLengthW(hwnd)
        buffer = ctypes.create_unicode_buffer(length + 1)
        user32.GetWindowTextW(hwnd, buffer, length + 1)
        title = buffer.value.lower()
        for k in keywords:
            if k in title:
                nonlocal found
                found = True
                return False
        return True

    EnumWindowsProc = ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.c_int, ctypes.c_int)
    user32.EnumWindows(EnumWindowsProc(enum_windows_callback), 0)

    if not found:
        return
    time.sleep(0.3)
def is_modal_confirm_window(hwnd, parent_hwnds):
user32 = ctypes.windll.user32


if not win32gui.IsWindowVisible(hwnd):
    return False

style = user32.GetWindowLongW(hwnd, win32con.GWL_STYLE)
if not (style & win32con.WS_POPUP):
    return False

owner = user32.GetWindow(hwnd, win32con.GW_OWNER)
if owner not in parent_hwnds:
    return False

title_length = user32.GetWindowTextLengthW(hwnd)
if title_length == 0:
    return False

buffer = ctypes.create_unicode_buffer(title_length + 1)
user32.GetWindowTextW(hwnd, buffer, title_length + 1)
title = buffer.value.lower()

keywords = ["conferma", "sovrascrivi", "attenzione", "avviso", "replace", "overwrite", "confirm", "already exists"]

for k in keywords:
    if k in title:
        return True

return False
def enum_save_dialog_windows(windows, save_windows):
main_dialog_hwnds = set()
for hwnd in windows:
if win32gui.IsWindowVisible(hwnd):
title = win32gui.GetWindowText(hwnd)
if title and ("save as" in title.lower() or "salva con nome" in title.lower()):
main_dialog_hwnds.add(hwnd)
for hwnd in windows:
if hwnd in main_dialog_hwnds:
pid = win32process.GetWindowThreadProcessId(hwnd)[1]
if not is_modal_confirm_window(hwnd, main_dialog_hwnds):
save_windows[hwnd] = pid

def get_unique_id_for_pid(pid):
if pid not in pid_to_unique_id:
pid_to_unique_id[pid] = str(uuid.uuid4())
return pid_to_unique_id[pid]

def monitor_save_dialog(process_name, app, pid, hwnd):
global handled_hwnds, pid_to_unique_id, unique_id_to_save_data


unique_id = get_unique_id_for_pid(pid)

print(f"[{process_name}] Monitoraggio HWND {hwnd} PID {pid} con unique_id {unique_id} avviato")
gui_shown = False
handled_hwnds.add(hwnd)


try:
    dlg = app.window(handle=hwnd)
    

    while dlg.exists() and not exit_flag:
        if not dlg.is_visible():
            time.sleep(0.3)
            continue

        if not gui_shown:
            wait_for_modal_dialog_closed(pid, hwnd)
            hide_window(hwnd)

            saved_path = unique_id_to_save_data.get(unique_id)

            ext = detect_default_extension(process_name)
            default_name = "file" + ext

            if saved_path:
                initial_folder = os.path.dirname(saved_path)
                default_name = os.path.basename(saved_path)
                if not default_name.lower().endswith(ext.lower()):
                    default_name += ext
            else:
                initial_folder = None

            result = custom_save_gui(ext, [], default_name, initial_folder)
            if result is None or result[0] is None:
                selected_path = None
                codice_az_salvato = None
                codice_ad_salvato = None
            else:
                selected_path, codice_az_salvato, codice_ad_salvato = result

            gui_shown = True

            if selected_path is not None:
                normalized_path = os.path.normpath(selected_path)
                unique_id_to_save_data[unique_id] = normalized_path

                show_window(hwnd)
                bring_to_front(hwnd)
                time.sleep(0.1)

                filename_edit = dlg.child_window(class_name="Edit")
                fixed_path = normalized_path.replace('/', '\\')
                filename_edit.set_edit_text(fixed_path)

                children = enumerate_child_windows(hwnd)
                btn_hwnd = None
                for ch in children:
                    text = win32gui.GetWindowText(ch)
                    cls = win32gui.GetClassName(ch)
                    if cls == 'Button' and ('salva' in text.lower() or 'save' in text.lower()):
                        btn_hwnd = ch
                        break

                if btn_hwnd:
                    try:
                        btn = dlg.child_window(handle=btn_hwnd)
                        btn.click_input()
                        wait_for_modal_dialog_closed(pid, hwnd)
                        if codice_az_salvato and codice_ad_salvato:
                            inserisci_file_db(codice_az_salvato, codice_ad_salvato, normalized_path)
                    except Exception as e:
                        print(f"{process_name}: click_input() non riuscito: {e}. Uso fallback BM_CLICK")
                        click_button_fallback_hwnd(btn_hwnd)
                        wait_for_modal_dialog_closed(pid, hwnd)
                        if codice_az_salvato and codice_ad_salvato:
                            inserisci_file_db(codice_az_salvato, codice_ad_salvato, normalized_path)
            else:
                print(f"{process_name}: GUI annullata, chiudo finestra dialog")
                win32gui.PostMessage(hwnd, win32con.WM_CLOSE, 0, 0)
                break

        time.sleep(0.5)
        dlg = app.window(handle=hwnd)

    print(f"[{process_name}] Finestra HWND {hwnd} chiusa, termina monitoraggio")

except Exception as e:
    print(f"{process_name} - Errore monitoraggio dialog: {e}")

if hwnd in handled_hwnds:
    handled_hwnds.remove(hwnd)
    print(f"{process_name}: HWND {hwnd} rimosso da gestiti")
Riporto qui solo il main loop e l'avvio icon tray come nel tuo script originale
def main_loop():
global handled_hwnds, exit_flag, pid_to_unique_id, unique_id_to_save_data
pid_to_unique_id = {}
unique_id_to_save_data = {}
handled_hwnds = set()
monitored_hwnds = {}


while not exit_flag:
    all_hwnds = []
    win32gui.EnumWindows(lambda hwnd, param: param.append(hwnd), all_hwnds)

    save_windows = {}
    enum_save_dialog_windows(all_hwnds, save_windows)

    for hwnd in list(monitored_hwnds.keys()):
        if not win32gui.IsWindow(hwnd) or hwnd not in save_windows:
            monitored_hwnds.pop(hwnd)
            if hwnd in handled_hwnds:
                handled_hwnds.remove(hwnd)

    for hwnd, pid in save_windows.items():
        if hwnd in handled_hwnds:
            continue

        try:
            proc = psutil.Process(pid)
            proc_name = proc.name()
        except Exception:
            proc_name = "sconosciuto"

        try:
            app = Application().connect(process=pid)
            t = threading.Thread(target=monitor_save_dialog, args=(proc_name, app, pid, hwnd), daemon=True)
            t.start()
            monitored_hwnds[hwnd] = t
            print(f"[Main] Avviato monitor PID {pid} HWND {hwnd} ({proc_name})")
        except Exception as e:
            print(f"[Main] Errore connessione PID {pid} HWND {hwnd}: {e}")

    time.sleep(2)
E infine, l'avvio
if name == "main":
icon = setup_tray_icon()
main_thread = threading.Thread(target=main_loop, daemon=True)
main_thread.start()
icon.run()
print("Terminazione in corso...")
exit_flag = True
main_thread.join(timeout=5)
print("Chiusura completata.")