You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python Tkinter实现系统级强制模态警示窗口?

实现Windows系统级高优先级警示窗口(Tkinter)

问题核心

你要的是系统级模态窗口,这和Tkinter自带的grab_set_global(仅限制当前Python程序)完全不同——后者无法阻止用户切换到其他系统应用。之前的代码只做了窗口置顶和强制聚焦,没真正实现系统级的输入锁定。

可行实现方案(Windows平台)

Windows下要达成这个效果,必须结合Win32 API的关键函数,从窗口样式、输入捕获、系统锁定三个维度处理:

完整代码实现

import tkinter as tk
import ctypes
import threading
import time
import winsound

# 定义Win32常量
GWL_EXSTYLE = -20
WS_EX_TOPMOST = 0x00000008
SWP_NOMOVE = 0x0002
SWP_NOSIZE = 0x0001
HWND_TOPMOST = -1
MB_SYSTEMMODAL = 0x00001000

# 全局状态控制
notification_active = threading.Event()
lock = threading.Lock()

def play_alert_sound():
    # 播放Windows系统警示音
    winsound.MessageBeep(winsound.MB_ICONEXCLAMATION)

def flash_window(hwnd):
    # 实现窗口闪烁效果
    class FLASHWINFO(ctypes.Structure):
        _fields_ = [("cbSize", ctypes.c_uint),
                    ("hwnd", ctypes.c_void_p),
                    ("dwFlags", ctypes.c_uint),
                    ("uCount", ctypes.c_uint),
                    ("dwTimeout", ctypes.c_uint)]
    fwi = FLASHWINFO()
    fwi.cbSize = ctypes.sizeof(FLASHWINFO)
    fwi.hwnd = hwnd
    fwi.dwFlags = 0x00000003  # 闪烁窗口标题栏+内容,直到窗口激活
    fwi.uCount = 0
    fwi.dwTimeout = 0
    ctypes.windll.user32.FlashWindowEx(ctypes.byref(fwi))

def make_system_modal(window):
    hwnd = window.winfo_id()
    # 设置窗口始终置顶
    ctypes.windll.user32.SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE)
    # 强制修改窗口扩展样式,确保置顶属性生效
    ex_style = ctypes.windll.user32.GetWindowLongPtrW(hwnd, GWL_EXSTYLE)
    ctypes.windll.user32.SetWindowLongPtrW(hwnd, GWL_EXSTYLE, ex_style | WS_EX_TOPMOST)
    # 激活并聚焦窗口
    ctypes.windll.user32.SetForegroundWindow(hwnd)
    ctypes.windll.user32.SetActiveWindow(hwnd)

    # 关键:启动系统模态MessageBox辅助锁定(Windows安全限制下无法完全锁定所有操作,但可阻止常规切换)
    def system_lock_msg():
        ctypes.windll.user32.MessageBoxW(hwnd, "请处理该警示后继续操作", "高优先级警示", MB_SYSTEMMODAL | 0x00000030)
        close_alert()
    threading.Thread(target=system_lock_msg, daemon=True).start()

def keep_window_active(window):
    while notification_active.is_set():
        if window.winfo_exists():
            window.lift()
            window.focus_force()
            flash_window(window.winfo_id())
            window.update_idletasks()
        time.sleep(0.05)

def show_alert():
    global notification_window
    notification_window = tk.Toplevel(root)
    notification_window.title("高优先级警示")
    notification_window.geometry("400x200")
    # 禁用窗口默认关闭按钮(强制用户点击确认)
    notification_window.protocol("WM_DELETE_WINDOW", lambda: None)
    
    tk.Label(notification_window, text="⚠️ 紧急警示:请立即处理该事项!", font=("Arial", 14)).pack(pady=30)
    tk.Button(notification_window, text="确认处理", command=close_alert, font=("Arial", 12)).pack(pady=10)
    
    notification_active.set()
    play_alert_sound()
    make_system_modal(notification_window)
    # 启动线程持续保持窗口激活状态
    threading.Thread(target=keep_window_active, args=(notification_window,), daemon=True).start()

def close_alert():
    notification_active.clear()
    # 关闭辅助锁定的MessageBox
    hwnd_msg = ctypes.windll.user32.FindWindowW(None, "高优先级警示")
    if hwnd_msg:
        ctypes.windll.user32.SendMessageW(hwnd_msg, 0x0010, 0, 0)  # 发送WM_CLOSE消息
    if notification_window.winfo_exists():
        notification_window.destroy()

if __name__ == "__main__":
    root = tk.Tk()
    root.withdraw()  # 隐藏主窗口
    show_alert()
    root.mainloop()

关键说明

  • 系统级限制的局限性:Windows出于安全考虑,无法完全阻止所有系统操作(比如Ctrl+Alt+Del打开任务管理器),但上述代码可阻止用户切换到其他应用、操作桌面等常规行为。
  • 闪烁效果:通过FlashWindowEx实现窗口持续闪烁,直到用户激活窗口。
  • 提示音:调用系统默认警示音,也可替换为自定义音频文件。

内容的提问来源于stack exchange,提问作者anonim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 21:56:13