להורדה | תוכנה קטנה לשליטה בתוכנות מסך מלא וסגירה בכח
-
טוב.. מי שלא אוהב תוכנות שנוצרו עם AI נא לדלג לשרשור אחר שכוייח מראש!
ועכשיו לתוכנה
דאע"פ דהוי AI הושקעו המון שעות לשפר ולשכלל ולמנוע קריסות ושאר ירקותקודם כל כרגיל אין אחריות על כלום!!!
ועכשיו לאחר שהזהרנו אומר לכם שניסיתי כמה פעמים ולא היתה שום בעייה נתקדם
אז מאחר שאני מתעסק עם בר אילן ב"ה הרבה ולאחר שהסגירה שלו בעייתית כמו שצויין בשרשור הזה לדוגמא
וגם הפריע לי בהרבה תוכנות שאי אפשר לעשות אותם במסך מלא (כמו F11)בקשתי מהגבינה מלאכותית
שתגבן לי איזו תוכנה קטנה ומועילה לסדר לי קצת את החייםואני חושב שלמי שצריך את זה זה יהיה לעזר רב! ומשום כך אני משתף אתכם בע"ה
טוב לאחר הברברת נתקדם לתוכנה
אז אספר לכם שזו תוכנה קלה פשוטה ומהירה (לא אמרתי יציבה... אבל אותי כעת זה ממש מספק)
יכול להיות שיש עוד תוכנות כאלו ויכול להיות שאין פחות מעניין אותי כי זו תוכנה בול למה שאני צריךלהורדה - ניהול חלונות.exe כ- 20MB
צילום מסך והדרכה חביבה שלא נ"ל שכ"כ צריך בספויילר
נכתב בשביל משתמשי בר אילן שב"ה קצת פחות טכנולוגים
טוב כשלב ראשון כמובן לוחצים על התוכנה שיורדת
נפתח המסך הבא

טוב יש כאן כמה אופציות
Of course, if you speak English, click the button on the top left.- להוסיף ולהסיר תוכנות
כרגע בברירת מחדל יש את responsa.exe שזה קובץ ההפעלה של בר אילן אם זה רק מה שאתם צריכים אין לכם מה לעשות עוד והתקדמו לשלב הבא
במידה שלא ואת רוצים תוכנה אחרת חפשו את קובץ ההפעלה שלה
לא כ"כ מסובך אתם צריכים לרדת לשורש ולראות מה קובץ ההפעלה
לחפש נניח את תוכנת וורד בחיפוש>ללחוץ על פתח מיקום קובץ ועל כל דבר שנפתח ללחוץ שוב מקש ימני>פתח מיקום עד שמגיעים לקובץ עם סיומת exe
לדוגמא קובץ ההפעלה של וורד הוא WINWORD.EXE וכן הלאה
להכניס לשורה למטה וללחוץ על 'הוסף'
ועכשיו בפתיחת התוכנה יופיעו הסמלים הבאים

-
וזה דבר חשוב באם אתם לא רוצים שבכל הפעלה של המחשב תאלצו להדליק את התוכנה פשוט לחצו על הכפתור למטה שמדליק את זה באופן אוטומטי בכל הפעלה
תמיד תוכלו לבטל את זה בלחיצה חוזרת! -
באם תרצו לכבות כליל את התוכנה סתאם כי לא בא לכם על התוכנה או כל סיבה אחרת
היא מסתתרת בצד שמאל למטה
לחצו כאן

ואז מקש ימני כאן ויציאה

שימו לב! שאם אם לוחצים על התוכנה שהיא כבר דלוקה היא נפתחת פעמיים וזה סתם גוזל משאבים תמיד תבדקו בשורת המשימות אם היא פתוחה
וכמובן כמובן הכל בקוד פתוח למי שרוצה בספויילר ממש כאן
ומעט פרטים יותר טכניים
קודם הקוד נו הנחש ההוא פייתון (צריך לכתוב?)import tkinter as tk from tkinter import messagebox, ttk import sys, os, json, threading, time # הגדרות לפי משתמש USER_NAME = os.getlogin() TEMP_DIR = os.environ.get('TEMP', os.getcwd()) CONFIG_FILE = os.path.join(TEMP_DIR, f"win_helper_{USER_NAME}.json") # תמיכת נתיב נכנס לקבצי משאבים כשהבנייה ב-PyInstaller def resource_path(relative_path): try: base_path = sys._MEIPASS except Exception: base_path = os.path.abspath(".") return os.path.join(base_path, relative_path) ICON_PATH = resource_path("app_icon.ico") try: import win32gui, win32con, win32api, win32process, winreg import psutil from PIL import Image, ImageDraw import pystray from pystray import MenuItem as item except ImportError: pass # מילון שפות LANGS = { "he": { "title": "ניהול חלונות (עברית)", "p_label": "תוכנות במעקב:", "add_btn": "הוסף", "rem_btn": "הסר נבחר", "help_btn": "הוראות", "startup_on": "הפעל אוטומטית עם המחשב", "startup_off": "בטל הפעלה אוטומטית", "lang_btn": "Switch to English", "help_text": "1. גרור את הפס האפור כדי להזיז את הכפתורים.\n2. כפתור ⛶ הופך למסך מלא.\n3. הסמל יעלם כשתהיה במסך מלא ויחזור כשתצא.\n4. ניתן לעבור חופשי בין תוכנות (Alt+Tab).", "help_title": "הוראות שימוש", "added": "נוסף בהצלחה", "process_name": "שם תהליך (EXE)" }, "en": { "title": "Window Manager (English)", "p_label": "Tracked Applications:", "add_btn": "Add", "rem_btn": "Remove Selected", "help_btn": "Instructions", "startup_on": "Run at Startup", "startup_off": "Disable Startup", "lang_btn": "החלףלעברית", "help_text": "1. Drag the gray bar to move buttons.\n2. Use ⛶ for Fullscreen.\n3. Icons hide in Fullscreen and return when window is normal.\n4. Free switching between apps (Alt+Tab).", "help_title": "Instructions", "added": "Added successfully", "process_name": "Process Name (EXE)" } } def load_config(): if os.path.exists(CONFIG_FILE): with open(CONFIG_FILE, "r", encoding="utf-8") as f: try: return json.load(f) except: pass return {"apps": ["responsa.exe"], "lang": "he"} def save_config(config): with open(CONFIG_FILE, "w", encoding="utf-8") as f: json.dump(config, f) class FloatingButtons: def __init__(self, target_hwnd, manager): self.target_hwnd = target_hwnd self.manager = manager self.root = tk.Toplevel() self.root.overrideredirect(True) self.root.attributes("-topmost", True) self.root.attributes("-alpha", 0.75) # מסגרת self.main_frame = tk.Frame(self.root, bg="#1a1a1a", bd=1) self.main_frame.pack() # ידית גרירה self.drag_handle = tk.Frame(self.main_frame, bg="#505050", width=12, cursor="fleur") self.drag_handle.pack(side="left", fill="y") self.drag_handle.bind("<Button-1>", self.start_move) self.drag_handle.bind("<B1-Motion>", self.do_move) self.btn_frame = tk.Frame(self.main_frame, bg="#1a1a1a") self.btn_frame.pack(side="left", padx=2, pady=2) btn_style = {"bg": "#1a1a1a", "fg": "white", "relief": "flat", "font": ("Segoe UI Symbol", 9), "width": 4} # כפתור מסך מלא self.btn_full = tk.Button(self.btn_frame, text="⛶", command=self.toggle_fullscreen, **btn_style) self.btn_full.pack(side="left", padx=1) # כפתור סגירה self.btn_close = tk.Button(self.btn_frame, text="✕", command=self.kill_target, **btn_style) self.btn_close.configure(fg="#ff5555") self.btn_close.pack(side="left", padx=1) self.fullscreen_data = None self.offset_x = 240 self.offset_y = 10 self.update_position() def start_move(self, event): self._start_x = event.x self._start_y = event.y def do_move(self, event): x = self.root.winfo_pointerx() - self._start_x y = self.root.winfo_pointery() - self._start_y self.root.geometry(f"+{x}+{y}") rect = win32gui.GetWindowRect(self.target_hwnd) self.offset_x = rect[2] - x self.offset_y = y - rect[1] def is_target_fullscreen(self): try: rect = win32gui.GetWindowRect(self.target_hwnd) screen_w = win32api.GetSystemMetrics(win32con.SM_CXSCREEN) screen_h = win32api.GetSystemMetrics(win32con.SM_CYSCREEN) # אם החלון בגודל המסך בדיוק וחסר לו מסגרת (WS_POPUP) style = win32gui.GetWindowLong(self.target_hwnd, win32con.GWL_STYLE) return (rect[2]-rect[0] >= screen_w and rect[3]-rect[1] >= screen_h and not (style & win32con.WS_CAPTION)) except: return False def update_position(self): if not win32gui.IsWindow(self.target_hwnd): self.root.destroy() return try: fg = win32gui.GetForegroundWindow() active = (fg == self.target_hwnd or fg == self.root.winfo_id()) # הסתרה אם התוכנה במסך מלא (שלה או שלנו) if self.is_target_fullscreen() or not active: self.root.withdraw() else: self.root.deiconify() rect = win32gui.GetWindowRect(self.target_hwnd) x = rect[2] - self.offset_x y = rect[1] + self.offset_y self.root.geometry(f"+{x}+{y}") except: pass self.root.after(50, self.update_position) def toggle_fullscreen(self): hwnd = self.target_hwnd if not self.fullscreen_data: style = win32gui.GetWindowLong(hwnd, win32con.GWL_STYLE) rect = win32gui.GetWindowRect(hwnd) self.fullscreen_data = (style, rect) win32gui.SetWindowLong(hwnd, win32con.GWL_STYLE, win32con.WS_POPUP | win32con.WS_VISIBLE) mon = win32api.GetMonitorInfo(win32api.MonitorFromWindow(hwnd))['Monitor'] win32gui.SetWindowPos(hwnd, win32con.HWND_TOP, mon[0], mon[1], mon[2]-mon[0], mon[3]-mon[1], win32con.SWP_FRAMECHANGED) # לצאת ממסך מלא בלחיצת ESC דרך חוט חיצוני threading.Thread(target=self.esc_monitor, daemon=True).start() else: self.exit_fullscreen() def esc_monitor(self): while self.fullscreen_data: if win32api.GetAsyncKeyState(win32con.VK_ESCAPE): self.root.after(0, self.exit_fullscreen) break time.sleep(0.1) def exit_fullscreen(self): if self.fullscreen_data: style, rect = self.fullscreen_data win32gui.SetWindowLong(self.target_hwnd, win32con.GWL_STYLE, style) win32gui.SetWindowPos(self.target_hwnd, win32con.HWND_NOTOPMOST, rect[0], rect[1], rect[2]-rect[0], rect[3]-rect[1], win32con.SWP_FRAMECHANGED) win32gui.ShowWindow(self.target_hwnd, win32con.SW_MAXIMIZE) self.fullscreen_data = None def kill_target(self): try: _, pid = win32process.GetWindowThreadProcessId(self.target_hwnd) handle = win32api.OpenProcess(win32con.PROCESS_TERMINATE, False, pid) win32api.TerminateProcess(handle, -1) win32api.CloseHandle(handle) except: pass class ManagerApp: def __init__(self, root): self.root = root self.config = load_config() self.active_overlays = {} self.setup_ui() self.running = True threading.Thread(target=self.scan_loop, daemon=True).start() threading.Thread(target=self.run_tray, daemon=True).start() def setup_ui(self): l = LANGS[self.config["lang"]] is_rtl = (self.config["lang"] == "he") self.root.title(l["title"]) self.root.geometry("450x500") self.root.protocol('WM_DELETE_WINDOW', self.hide) # איקון חלון התוכנה (taskbar) - ניסיון ראשון try: self.root.iconbitmap(ICON_PATH) except Exception: try: icon = tk.PhotoImage(file=ICON_PATH) self.root.iconphoto(False, icon) except Exception: pass for widget in self.root.winfo_children(): widget.destroy() main = ttk.Frame(self.root, padding=20) main.pack(fill="both", expand=True) # כותרת ושפה top_f = ttk.Frame(main) top_f.pack(fill="x") ttk.Button(top_f, text=l["lang_btn"], command=self.toggle_lang).pack(side="left") tk.Label(main, text=l["p_label"], font=("Segoe UI", 12, "bold")).pack(pady=10) # רשימה self.tree = ttk.Treeview(main, columns=("n"), show="headings", height=8) self.tree.heading("n", text=l["process_name"]) self.tree.pack(fill="both", expand=True) self.refresh_tree() # הוספה add_f = ttk.Frame(main) add_f.pack(fill="x", pady=10) self.new_entry = ttk.Entry(add_f, justify="center") self.new_entry.pack(side="right" if is_rtl else "left", fill="x", expand=True, padx=5) self.new_entry.insert(0, "responsa.exe") ttk.Button(add_f, text=l["add_btn"], command=self.add_item).pack(side="left" if is_rtl else "right") # כפתורים btn_f = ttk.Frame(main) btn_f.pack(fill="x") ttk.Button(btn_f, text=l["rem_btn"], command=self.remove_item).pack(side="right" if is_rtl else "left", fill="x", expand=True, padx=2) ttk.Button(btn_f, text=l["help_btn"], command=self.show_help).pack(side="left" if is_rtl else "right", fill="x", expand=True, padx=2) self.start_btn = ttk.Button(main, text="...", command=self.toggle_startup) self.start_btn.pack(fill="x", pady=10) self.update_startup_ui() def toggle_lang(self): self.config["lang"] = "en" if self.config["lang"] == "he" else "he" save_config(self.config) self.setup_ui() def show_help(self): l = LANGS[self.config["lang"]] messagebox.showinfo(l["help_title"], l["help_text"]) def refresh_tree(self): for i in self.tree.get_children(): self.tree.delete(i) for a in self.config.get("apps", []): self.tree.insert("", "end", values=(a,)) def add_item(self): n = self.new_entry.get().lower().strip() if n and n not in self.config["apps"]: self.config["apps"].append(n) save_config(self.config) self.refresh_tree() def remove_item(self): sel = self.tree.selection() if sel: name = self.tree.item(sel[0])['values'][0] self.config["apps"].remove(name) save_config(self.config) self.refresh_tree() def update_startup_ui(self): l = LANGS[self.config["lang"]] try: key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Run", 0, winreg.KEY_READ) winreg.QueryValueEx(key, "WindowHelper") winreg.CloseKey(key) self.start_btn.configure(text=l["startup_off"]) self.startup_active = True except: self.start_btn.configure(text=l["startup_on"]) self.startup_active = False def toggle_startup(self): path = r"Software\Microsoft\Windows\CurrentVersion\Run" if not self.startup_active: key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, path, 0, winreg.KEY_SET_VALUE) winreg.SetValueEx(key, "WindowHelper", 0, winreg.REG_SZ, sys.executable) winreg.CloseKey(key) else: key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, path, 0, winreg.KEY_SET_VALUE) try: winreg.DeleteValue(key, "WindowHelper") except: pass winreg.CloseKey(key) self.update_startup_ui() def scan_loop(self): while self.running: def callback(hwnd, _): if win32gui.IsWindowVisible(hwnd): try: _, pid = win32process.GetWindowThreadProcessId(hwnd) name = psutil.Process(pid).name().lower() if name in self.config["apps"] and hwnd not in self.active_overlays and pid != os.getpid(): self.root.after(0, lambda: self.active_overlays.update({hwnd: FloatingButtons(hwnd, self)})) except: pass win32gui.EnumWindows(callback, None) time.sleep(1.0) def hide(self): self.root.withdraw() def show(self): self.root.after(0, self.root.deiconify) def run_tray(self): img = Image.open(ICON_PATH) if os.path.exists(ICON_PATH) else Image.new('RGB', (64, 64), (0, 120, 215)) icon = pystray.Icon("winhelper", img, "Window Helper", (item('Settings / הגדרות', self.show), item('Exit / יציאה', lambda i: self.stop(i)))) icon.run() def stop(self, i): self.running = False i.stop() self.root.after(0, self.root.destroy) if __name__ == "__main__": root = tk.Tk() app = ManagerApp(root) root.mainloop()הקובץ apps_config.json להגדרות התוכנה נמצא בתקיית %temp% בכדי לא ללכלך..
===
מאד אשמח שמי שימצא עניין וישתמש בתוכנה נישתית זו יודיעני זה ממש משמח והיה זה שכרי!
מי שמוצא באג טעות או כל דבר אחר בתוכנה זו מוזמן לתקן בשמחה ואין עיני צרה
נ.ב. אם יש שיפור שאני רוצה להוסיף זה מצב קיוסק שהוספתי ועבד מצויין אולם לאחר שזה סיבך קצת את הפיתוח ונגס מזמני היקר נגיסות גדולות השמטתי את זה
אני חושב שתוכנה זו היא בסיס מצוין לקיוסק קליל
אולי אוסיף את זה בהמשך או שמישהו יתנדב בשמחהטוב אני חושב שכתבתי המון על תוכנה כה קטנה

אז שיהיה בהצלחה והרבה סייעתא דשמייא אמן. - להוסיף ולהסיר תוכנות
-
טוב.. מי שלא אוהב תוכנות שנוצרו עם AI נא לדלג לשרשור אחר שכוייח מראש!
ועכשיו לתוכנה
דאע"פ דהוי AI הושקעו המון שעות לשפר ולשכלל ולמנוע קריסות ושאר ירקותקודם כל כרגיל אין אחריות על כלום!!!
ועכשיו לאחר שהזהרנו אומר לכם שניסיתי כמה פעמים ולא היתה שום בעייה נתקדם
אז מאחר שאני מתעסק עם בר אילן ב"ה הרבה ולאחר שהסגירה שלו בעייתית כמו שצויין בשרשור הזה לדוגמא
וגם הפריע לי בהרבה תוכנות שאי אפשר לעשות אותם במסך מלא (כמו F11)בקשתי מהגבינה מלאכותית
שתגבן לי איזו תוכנה קטנה ומועילה לסדר לי קצת את החייםואני חושב שלמי שצריך את זה זה יהיה לעזר רב! ומשום כך אני משתף אתכם בע"ה
טוב לאחר הברברת נתקדם לתוכנה
אז אספר לכם שזו תוכנה קלה פשוטה ומהירה (לא אמרתי יציבה... אבל אותי כעת זה ממש מספק)
יכול להיות שיש עוד תוכנות כאלו ויכול להיות שאין פחות מעניין אותי כי זו תוכנה בול למה שאני צריךלהורדה - ניהול חלונות.exe כ- 20MB
צילום מסך והדרכה חביבה שלא נ"ל שכ"כ צריך בספויילר
נכתב בשביל משתמשי בר אילן שב"ה קצת פחות טכנולוגים
טוב כשלב ראשון כמובן לוחצים על התוכנה שיורדת
נפתח המסך הבא

טוב יש כאן כמה אופציות
Of course, if you speak English, click the button on the top left.- להוסיף ולהסיר תוכנות
כרגע בברירת מחדל יש את responsa.exe שזה קובץ ההפעלה של בר אילן אם זה רק מה שאתם צריכים אין לכם מה לעשות עוד והתקדמו לשלב הבא
במידה שלא ואת רוצים תוכנה אחרת חפשו את קובץ ההפעלה שלה
לא כ"כ מסובך אתם צריכים לרדת לשורש ולראות מה קובץ ההפעלה
לחפש נניח את תוכנת וורד בחיפוש>ללחוץ על פתח מיקום קובץ ועל כל דבר שנפתח ללחוץ שוב מקש ימני>פתח מיקום עד שמגיעים לקובץ עם סיומת exe
לדוגמא קובץ ההפעלה של וורד הוא WINWORD.EXE וכן הלאה
להכניס לשורה למטה וללחוץ על 'הוסף'
ועכשיו בפתיחת התוכנה יופיעו הסמלים הבאים

-
וזה דבר חשוב באם אתם לא רוצים שבכל הפעלה של המחשב תאלצו להדליק את התוכנה פשוט לחצו על הכפתור למטה שמדליק את זה באופן אוטומטי בכל הפעלה
תמיד תוכלו לבטל את זה בלחיצה חוזרת! -
באם תרצו לכבות כליל את התוכנה סתאם כי לא בא לכם על התוכנה או כל סיבה אחרת
היא מסתתרת בצד שמאל למטה
לחצו כאן

ואז מקש ימני כאן ויציאה

שימו לב! שאם אם לוחצים על התוכנה שהיא כבר דלוקה היא נפתחת פעמיים וזה סתם גוזל משאבים תמיד תבדקו בשורת המשימות אם היא פתוחה
וכמובן כמובן הכל בקוד פתוח למי שרוצה בספויילר ממש כאן
ומעט פרטים יותר טכניים
קודם הקוד נו הנחש ההוא פייתון (צריך לכתוב?)import tkinter as tk from tkinter import messagebox, ttk import sys, os, json, threading, time # הגדרות לפי משתמש USER_NAME = os.getlogin() TEMP_DIR = os.environ.get('TEMP', os.getcwd()) CONFIG_FILE = os.path.join(TEMP_DIR, f"win_helper_{USER_NAME}.json") # תמיכת נתיב נכנס לקבצי משאבים כשהבנייה ב-PyInstaller def resource_path(relative_path): try: base_path = sys._MEIPASS except Exception: base_path = os.path.abspath(".") return os.path.join(base_path, relative_path) ICON_PATH = resource_path("app_icon.ico") try: import win32gui, win32con, win32api, win32process, winreg import psutil from PIL import Image, ImageDraw import pystray from pystray import MenuItem as item except ImportError: pass # מילון שפות LANGS = { "he": { "title": "ניהול חלונות (עברית)", "p_label": "תוכנות במעקב:", "add_btn": "הוסף", "rem_btn": "הסר נבחר", "help_btn": "הוראות", "startup_on": "הפעל אוטומטית עם המחשב", "startup_off": "בטל הפעלה אוטומטית", "lang_btn": "Switch to English", "help_text": "1. גרור את הפס האפור כדי להזיז את הכפתורים.\n2. כפתור ⛶ הופך למסך מלא.\n3. הסמל יעלם כשתהיה במסך מלא ויחזור כשתצא.\n4. ניתן לעבור חופשי בין תוכנות (Alt+Tab).", "help_title": "הוראות שימוש", "added": "נוסף בהצלחה", "process_name": "שם תהליך (EXE)" }, "en": { "title": "Window Manager (English)", "p_label": "Tracked Applications:", "add_btn": "Add", "rem_btn": "Remove Selected", "help_btn": "Instructions", "startup_on": "Run at Startup", "startup_off": "Disable Startup", "lang_btn": "החלףלעברית", "help_text": "1. Drag the gray bar to move buttons.\n2. Use ⛶ for Fullscreen.\n3. Icons hide in Fullscreen and return when window is normal.\n4. Free switching between apps (Alt+Tab).", "help_title": "Instructions", "added": "Added successfully", "process_name": "Process Name (EXE)" } } def load_config(): if os.path.exists(CONFIG_FILE): with open(CONFIG_FILE, "r", encoding="utf-8") as f: try: return json.load(f) except: pass return {"apps": ["responsa.exe"], "lang": "he"} def save_config(config): with open(CONFIG_FILE, "w", encoding="utf-8") as f: json.dump(config, f) class FloatingButtons: def __init__(self, target_hwnd, manager): self.target_hwnd = target_hwnd self.manager = manager self.root = tk.Toplevel() self.root.overrideredirect(True) self.root.attributes("-topmost", True) self.root.attributes("-alpha", 0.75) # מסגרת self.main_frame = tk.Frame(self.root, bg="#1a1a1a", bd=1) self.main_frame.pack() # ידית גרירה self.drag_handle = tk.Frame(self.main_frame, bg="#505050", width=12, cursor="fleur") self.drag_handle.pack(side="left", fill="y") self.drag_handle.bind("<Button-1>", self.start_move) self.drag_handle.bind("<B1-Motion>", self.do_move) self.btn_frame = tk.Frame(self.main_frame, bg="#1a1a1a") self.btn_frame.pack(side="left", padx=2, pady=2) btn_style = {"bg": "#1a1a1a", "fg": "white", "relief": "flat", "font": ("Segoe UI Symbol", 9), "width": 4} # כפתור מסך מלא self.btn_full = tk.Button(self.btn_frame, text="⛶", command=self.toggle_fullscreen, **btn_style) self.btn_full.pack(side="left", padx=1) # כפתור סגירה self.btn_close = tk.Button(self.btn_frame, text="✕", command=self.kill_target, **btn_style) self.btn_close.configure(fg="#ff5555") self.btn_close.pack(side="left", padx=1) self.fullscreen_data = None self.offset_x = 240 self.offset_y = 10 self.update_position() def start_move(self, event): self._start_x = event.x self._start_y = event.y def do_move(self, event): x = self.root.winfo_pointerx() - self._start_x y = self.root.winfo_pointery() - self._start_y self.root.geometry(f"+{x}+{y}") rect = win32gui.GetWindowRect(self.target_hwnd) self.offset_x = rect[2] - x self.offset_y = y - rect[1] def is_target_fullscreen(self): try: rect = win32gui.GetWindowRect(self.target_hwnd) screen_w = win32api.GetSystemMetrics(win32con.SM_CXSCREEN) screen_h = win32api.GetSystemMetrics(win32con.SM_CYSCREEN) # אם החלון בגודל המסך בדיוק וחסר לו מסגרת (WS_POPUP) style = win32gui.GetWindowLong(self.target_hwnd, win32con.GWL_STYLE) return (rect[2]-rect[0] >= screen_w and rect[3]-rect[1] >= screen_h and not (style & win32con.WS_CAPTION)) except: return False def update_position(self): if not win32gui.IsWindow(self.target_hwnd): self.root.destroy() return try: fg = win32gui.GetForegroundWindow() active = (fg == self.target_hwnd or fg == self.root.winfo_id()) # הסתרה אם התוכנה במסך מלא (שלה או שלנו) if self.is_target_fullscreen() or not active: self.root.withdraw() else: self.root.deiconify() rect = win32gui.GetWindowRect(self.target_hwnd) x = rect[2] - self.offset_x y = rect[1] + self.offset_y self.root.geometry(f"+{x}+{y}") except: pass self.root.after(50, self.update_position) def toggle_fullscreen(self): hwnd = self.target_hwnd if not self.fullscreen_data: style = win32gui.GetWindowLong(hwnd, win32con.GWL_STYLE) rect = win32gui.GetWindowRect(hwnd) self.fullscreen_data = (style, rect) win32gui.SetWindowLong(hwnd, win32con.GWL_STYLE, win32con.WS_POPUP | win32con.WS_VISIBLE) mon = win32api.GetMonitorInfo(win32api.MonitorFromWindow(hwnd))['Monitor'] win32gui.SetWindowPos(hwnd, win32con.HWND_TOP, mon[0], mon[1], mon[2]-mon[0], mon[3]-mon[1], win32con.SWP_FRAMECHANGED) # לצאת ממסך מלא בלחיצת ESC דרך חוט חיצוני threading.Thread(target=self.esc_monitor, daemon=True).start() else: self.exit_fullscreen() def esc_monitor(self): while self.fullscreen_data: if win32api.GetAsyncKeyState(win32con.VK_ESCAPE): self.root.after(0, self.exit_fullscreen) break time.sleep(0.1) def exit_fullscreen(self): if self.fullscreen_data: style, rect = self.fullscreen_data win32gui.SetWindowLong(self.target_hwnd, win32con.GWL_STYLE, style) win32gui.SetWindowPos(self.target_hwnd, win32con.HWND_NOTOPMOST, rect[0], rect[1], rect[2]-rect[0], rect[3]-rect[1], win32con.SWP_FRAMECHANGED) win32gui.ShowWindow(self.target_hwnd, win32con.SW_MAXIMIZE) self.fullscreen_data = None def kill_target(self): try: _, pid = win32process.GetWindowThreadProcessId(self.target_hwnd) handle = win32api.OpenProcess(win32con.PROCESS_TERMINATE, False, pid) win32api.TerminateProcess(handle, -1) win32api.CloseHandle(handle) except: pass class ManagerApp: def __init__(self, root): self.root = root self.config = load_config() self.active_overlays = {} self.setup_ui() self.running = True threading.Thread(target=self.scan_loop, daemon=True).start() threading.Thread(target=self.run_tray, daemon=True).start() def setup_ui(self): l = LANGS[self.config["lang"]] is_rtl = (self.config["lang"] == "he") self.root.title(l["title"]) self.root.geometry("450x500") self.root.protocol('WM_DELETE_WINDOW', self.hide) # איקון חלון התוכנה (taskbar) - ניסיון ראשון try: self.root.iconbitmap(ICON_PATH) except Exception: try: icon = tk.PhotoImage(file=ICON_PATH) self.root.iconphoto(False, icon) except Exception: pass for widget in self.root.winfo_children(): widget.destroy() main = ttk.Frame(self.root, padding=20) main.pack(fill="both", expand=True) # כותרת ושפה top_f = ttk.Frame(main) top_f.pack(fill="x") ttk.Button(top_f, text=l["lang_btn"], command=self.toggle_lang).pack(side="left") tk.Label(main, text=l["p_label"], font=("Segoe UI", 12, "bold")).pack(pady=10) # רשימה self.tree = ttk.Treeview(main, columns=("n"), show="headings", height=8) self.tree.heading("n", text=l["process_name"]) self.tree.pack(fill="both", expand=True) self.refresh_tree() # הוספה add_f = ttk.Frame(main) add_f.pack(fill="x", pady=10) self.new_entry = ttk.Entry(add_f, justify="center") self.new_entry.pack(side="right" if is_rtl else "left", fill="x", expand=True, padx=5) self.new_entry.insert(0, "responsa.exe") ttk.Button(add_f, text=l["add_btn"], command=self.add_item).pack(side="left" if is_rtl else "right") # כפתורים btn_f = ttk.Frame(main) btn_f.pack(fill="x") ttk.Button(btn_f, text=l["rem_btn"], command=self.remove_item).pack(side="right" if is_rtl else "left", fill="x", expand=True, padx=2) ttk.Button(btn_f, text=l["help_btn"], command=self.show_help).pack(side="left" if is_rtl else "right", fill="x", expand=True, padx=2) self.start_btn = ttk.Button(main, text="...", command=self.toggle_startup) self.start_btn.pack(fill="x", pady=10) self.update_startup_ui() def toggle_lang(self): self.config["lang"] = "en" if self.config["lang"] == "he" else "he" save_config(self.config) self.setup_ui() def show_help(self): l = LANGS[self.config["lang"]] messagebox.showinfo(l["help_title"], l["help_text"]) def refresh_tree(self): for i in self.tree.get_children(): self.tree.delete(i) for a in self.config.get("apps", []): self.tree.insert("", "end", values=(a,)) def add_item(self): n = self.new_entry.get().lower().strip() if n and n not in self.config["apps"]: self.config["apps"].append(n) save_config(self.config) self.refresh_tree() def remove_item(self): sel = self.tree.selection() if sel: name = self.tree.item(sel[0])['values'][0] self.config["apps"].remove(name) save_config(self.config) self.refresh_tree() def update_startup_ui(self): l = LANGS[self.config["lang"]] try: key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Run", 0, winreg.KEY_READ) winreg.QueryValueEx(key, "WindowHelper") winreg.CloseKey(key) self.start_btn.configure(text=l["startup_off"]) self.startup_active = True except: self.start_btn.configure(text=l["startup_on"]) self.startup_active = False def toggle_startup(self): path = r"Software\Microsoft\Windows\CurrentVersion\Run" if not self.startup_active: key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, path, 0, winreg.KEY_SET_VALUE) winreg.SetValueEx(key, "WindowHelper", 0, winreg.REG_SZ, sys.executable) winreg.CloseKey(key) else: key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, path, 0, winreg.KEY_SET_VALUE) try: winreg.DeleteValue(key, "WindowHelper") except: pass winreg.CloseKey(key) self.update_startup_ui() def scan_loop(self): while self.running: def callback(hwnd, _): if win32gui.IsWindowVisible(hwnd): try: _, pid = win32process.GetWindowThreadProcessId(hwnd) name = psutil.Process(pid).name().lower() if name in self.config["apps"] and hwnd not in self.active_overlays and pid != os.getpid(): self.root.after(0, lambda: self.active_overlays.update({hwnd: FloatingButtons(hwnd, self)})) except: pass win32gui.EnumWindows(callback, None) time.sleep(1.0) def hide(self): self.root.withdraw() def show(self): self.root.after(0, self.root.deiconify) def run_tray(self): img = Image.open(ICON_PATH) if os.path.exists(ICON_PATH) else Image.new('RGB', (64, 64), (0, 120, 215)) icon = pystray.Icon("winhelper", img, "Window Helper", (item('Settings / הגדרות', self.show), item('Exit / יציאה', lambda i: self.stop(i)))) icon.run() def stop(self, i): self.running = False i.stop() self.root.after(0, self.root.destroy) if __name__ == "__main__": root = tk.Tk() app = ManagerApp(root) root.mainloop()הקובץ apps_config.json להגדרות התוכנה נמצא בתקיית %temp% בכדי לא ללכלך..
===
מאד אשמח שמי שימצא עניין וישתמש בתוכנה נישתית זו יודיעני זה ממש משמח והיה זה שכרי!
מי שמוצא באג טעות או כל דבר אחר בתוכנה זו מוזמן לתקן בשמחה ואין עיני צרה
נ.ב. אם יש שיפור שאני רוצה להוסיף זה מצב קיוסק שהוספתי ועבד מצויין אולם לאחר שזה סיבך קצת את הפיתוח ונגס מזמני היקר נגיסות גדולות השמטתי את זה
אני חושב שתוכנה זו היא בסיס מצוין לקיוסק קליל
אולי אוסיף את זה בהמשך או שמישהו יתנדב בשמחהטוב אני חושב שכתבתי המון על תוכנה כה קטנה

אז שיהיה בהצלחה והרבה סייעתא דשמייא אמן.@AVIVI
א. נחמד מאד
ב. לי זה לא נדלק בכלל, הלכתי למנהל המשימות ראיתי שבכל הדלקה נוצרים 2 תהליכים, מחקתי אחד ואז התוכנה נפתחה. - להוסיף ולהסיר תוכנות
-
@AVIVI
א. נחמד מאד
ב. לי זה לא נדלק בכלל, הלכתי למנהל המשימות ראיתי שבכל הדלקה נוצרים 2 תהליכים, מחקתי אחד ואז התוכנה נפתחה.@יוסי-מחשבים
תודה!
מוזר מה שקרה לך
ניסתי בשני מחשבים ועל הפעם הראשונה עבד
אולי לחצת פעמיים? -
@יוסי-מחשבים
תודה!
מוזר מה שקרה לך
ניסתי בשני מחשבים ועל הפעם הראשונה עבד
אולי לחצת פעמיים?@AVIVI כתב בלהורדה | תוכנה קטנה לשליטה בתוכנות מסך מלא וסגירה בכח:
ניסתי בשני מחשבים ועל הפעם הראשונה עבד
אולי לחצת פעמיים?לא לחצתי פעמיים, ניסיתי בשני מחשבים ובשניהם כנ"ל.
-
@AVIVI כתב בלהורדה | תוכנה קטנה לשליטה בתוכנות מסך מלא וסגירה בכח:
ניסתי בשני מחשבים ועל הפעם הראשונה עבד
אולי לחצת פעמיים?לא לחצתי פעמיים, ניסיתי בשני מחשבים ובשניהם כנ"ל.
@יוסי-מחשבים ח"ו שחשדתי בך ללחוץ פעמיים סתם
הרי ביודעי ומכירי קאמינא על הידע הרב שיש לך ועל העזרה שלך לי אישית ולהרבה אנשים כאן הרבה פעמים בחפץ לב ובנדיבות ושמחה ועל כך אני מודה לךוכשכתבתי התכוונתי לשאר האנשים שמשום שהתוכנה נפתחת מעט לאט הם לוחצים פעם שנייה ובאמת היא נפתחת פעמיים כמו שכתבתי בסוף המדריך
האם כוונתך למה שמופיע בתמונה הזו?

כי אם כן לא ראיתי בזה שום בעיה זה עבד לי עם שני התהליכים הללו מצויין ולא הוזקקתי לכבות אחד מהםובא נאמר אם יש באג כלשהו אתה תדע לסדר אותו יותר טוב ממני...
