Python Windows CUI应用如何在自定义函数返回后实现控制台闪烁
问题原因
你原有代码的执行顺序是先跑闪烁检测的while循环,循环完全结束后才会执行input()调用输出提示,所以提示只能在闪烁停止后展示。
解决方案
最简改法:调整执行顺序
核心思路是先手动输出输入提示并强制刷新控制台缓冲区,再执行闪烁逻辑,最后等待用户输入:
import time import ctypes from ctypes import windll # 你的原有实现,此处省略具体代码 def get_foreground_window_title(): pass def custom_formatted_input(message: str = "") -> str: # 1. 先打印输入提示,不换行,flush保证内容立刻输出到控制台 prompt = f"{time.strftime('%Y-%m-%d %H:%M:%S')}{' '.ljust(4)}[INPUT]{' '.ljust(6)}{message} " print(prompt, end='', flush=True) console_hwnd = windll.kernel32.GetConsoleWindow() # 2. 执行闪烁逻辑,直到控制台窗口被激活 while get_foreground_window_title() != "cmd.exe": windll.user32.FlashWindow(console_hwnd, True) time.sleep(0.5) # 3. 窗口激活后等待用户输入 return input()
装饰器实现
如果需要把闪烁逻辑抽离复用,可以用装饰器封装:
def flash_when_inactive(func): def wrapper(message: str = "", *args, **kwargs): # 先输出输入提示 prompt = f"{time.strftime('%Y-%m-%d %H:%M:%S')}{' '.ljust(4)}[INPUT]{' '.ljust(6)}{message} " print(prompt, end='', flush=True) # 闪烁检测逻辑 console_hwnd = windll.kernel32.GetConsoleWindow() while get_foreground_window_title() != "cmd.exe": windll.user32.FlashWindow(console_hwnd, True) time.sleep(0.5) # 执行原输入逻辑 return func(*args, **kwargs) return wrapper # 给基础输入函数加装饰器即可 @flash_when_inactive def custom_input() -> str: return input() # 调用示例 user_input = custom_input("请输入操作指令:")
优化建议:使用系统原生闪烁API
不用自己写循环控制闪烁,调用FlashWindowEx可以实现系统级的自动闪烁,直到窗口激活为止,性能更稳定:
def flash_console_until_active(): 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) ] # 0x3 = FLASHW_ALL(同时闪烁标题栏和任务栏),0xC = FLASHW_TIMERNOFG(直到窗口激活才停止) FLASH_FLAGS = 0x3 | 0xC console_hwnd = windll.kernel32.GetConsoleWindow() fw = FLASHWINFO( cbSize=ctypes.sizeof(FLASHWINFO), hwnd=console_hwnd, dwFlags=FLASH_FLAGS, uCount=0, # 0代表无限闪烁直到激活 dwTimeout=500 # 闪烁间隔500ms ) windll.user32.FlashWindowEx(ctypes.byref(fw))
使用这个API之后可以去掉手动写的while闪烁循环,代码更简洁。
内容的提问来源于stack exchange,提问作者user16667377
相关产品推荐
相关产品推荐

