NumLock 状态悬浮窗插件 - 开发笔记

为什么要开发这个插件

  • 我有一个没有状态指示灯的键盘,

  • 我需要保证它占用系统资源足够少,并且代码不能过于复杂

明确插件目标

  • 实时监听 NumLock 键状态变更
  • 在屏幕右下角弹出状态提示框(ON / OFF)
  • 提示窗在 1.5 秒后自动隐藏
  • 支持按 - 键退出程序,并显示“退出”提示

选择开发语言与技术栈

选型理由:

  • 使用 Python 是为了开发效率高,语法简洁
  • 使用 tkinter 快速构建轻量 GUI,无需额外依赖
  • 使用 keyboard 实现全局键盘监听
  • 使用 ctypes 获取 NumLock 状态(调用的 Windows API节约系统资源)

具体实现

NumLock状态检测

def get_numlock_state(self):
    return bool(ctypes.WinDLL("User32.dll").GetKeyState(0x90) & 1)
  • 0x90 是 NumLock 的虚拟键码

  • 调用 GetKeyState 获取当前开关状态(ON 为 1)

主界面浮窗

使用 tkinter.Tk() 创建无边框窗口:

self.root.overrideredirect(True)         # 去除边框
self.root.attributes('-topmost', True)   # 保持置顶
self.root.attributes('-alpha', 0.8)      # 设置为 80% 透明
  • 窗口大小:130x45

  • 位置:屏幕右下角偏移一点(避免压到任务栏)

显示状态文字

self.label = tk.Label(
    self.root,
    fg="lime",
    bg="black",
    font=("Consolas", 16, "bold")  # 加粗字体
)
  • 状态变为 ON 时显示绿色文字

  • 状态变为 OFF 时显示红色文字

  • 加粗字体突出提示效果

监听 NumLock 键变化

def keyboard_listener(self):
    def on_press(event):
        if event.name == "num lock":
            self.queue.put("update")
    keyboard.on_press(on_press)
  • 通过 keyboard.on_press 捕捉按键
  • 使用 Queue 将事件传递给主线程刷新界面(避免跨线程修改 UI)

弹窗提示并自动隐藏

self.root.deiconify()
self.fade_timer = threading.Timer(1.5, self.safe_withdraw)
self.fade_timer.start()
  • 每次状态变化时显示窗口
  • 启动定时器,在 1.5 秒后自动调用 withdraw() 隐藏窗口

退出功能

keyboard.wait("-")
self.label.config(text="退出", fg="yellow")
self.root.deiconify()
time.sleep(1)
self.root.quit()
  • 监听 - 键作为退出信号
  • 显示“退出”提示
  • 延迟 1 秒关闭主窗口

结构梳理

线程名称 功能说明
主线程 显示 UI,处理事件队列
keyboard_listener 实时监听 NumLock 键
exit_listener 监听退出按键并触发退出流程

成品效果

//TODO 扩展

本插件实现了对键盘 NumLock 状态的轻量提示功能,界面简洁、资源占用少。后续完善:

  • 支持 CapsLock / ScrollLock 状态检测
  • 加入托盘图标
  • 设置自定义快捷键或透明度
  • 以及更多自定义功能

欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1701220998@qq.com
导航页 GitHub