对于键盘没有背光灯的同学而言,切换大小写或控制num键开关的时候没有提示,经常需要试探性地输入一些字符来判断开关是否打开,体验非常糟糕。
因此,有人就想到自制脚本这一招,一旦触发大小写切换或num键切换就进行windows通知提示:
https://github.com/skate1512/toggle_keys_notification
今天我们来试试这个脚本,此外,我们还可以基于这个项目,扩展成任意一个按键被触发或切换都进行 windows 通知的脚本:
1.准备开始之前,你要确保python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细python安装指南 进行安装。如果你用python的目的是数据分析,可以直接安装anaconda:python数据分析与挖掘好帮手—anaconda,它内置了python和pip.
此外,推荐大家用vscode编辑器,因为它可以在编辑器下方的终端运行命令安装依赖模块:python 编程的最好搭档—vscode 详细指南。
windows环境下打开 cmd (开始-运行-cmd),苹果系统环境下请打开 terminal (command+空格输入terminal),输入命令安装依赖:
pip install win10toast除此之外,我们需要下载作者的代码,如果你能联通github,请前往以下地址下载:
https://github.com/skate1512/toggle_keys_notification
如果不能联通github,或者网络速度比较慢,请在python实用宝典公众号后台回复:按键触发通知 下载本文完整源代码。
2.源码使用与解析2.1 源码使用作者的项目可以在 toggle_keys_notification 项目内,运行 notify.py 启动监听:
python notify.py启动后点击一下大小写切换键,触发通知则说明代码正常运转:
2.2 源码分析该项目通过win32gui和win32con实现了弹出toast进行通知的功能,最核心的_show_toast代码位于 toast.py 中,下面是这个函数的部分代码剖析:
注册和创建 window :
message_map = {wm_destroy: self.on_destroy, }# 注册windowself.wc = wndclass()self.hinst = self.wc.hinstance = getmodulehandle(none)self.wc.lpszclassname = str(pythontaskbar) # 定义该窗口结构的名称self.wc.lpfnwndproc = message_maptry: self.classatom = registerclass(self.wc)except: pass# window格式style = ws_overlapped | ws_sysmenu# 创建windowself.hwnd = createwindow(self.classatom, taskbar, style, 0, 0, cw_usedefault, cw_usedefault, 0, 0, self.hinst, none)updatewindow(self.hwnd)所使用到的win32模块解析如下。
getmodulehandle: 获取一个应用程序或动态链接库的模块句柄。
wm_destroy: 关闭程序。
registerclass: 将定义好的window属性保存保存下来。
ws_overlapped: 重叠式窗口,该式样窗口 带有一个标题栏和边框。
ws_sysmenu: 具有 system 菜单栏的样式
cw_usedefault: 采用系统默认位置
createwindow 这个函数具有非常多的参数,甚至有一个百度百科来详细解析每一个参数的具体作用,大家感兴趣可以移步:
https://baike.baidu.com/item/createwindow/5076220
了解win32这些模块名称的意义后,理解上述代码的逻辑便很轻松了。
图标加载及任务栏图标显示配置:
# 图标if icon_path is not none: # 获取图标地址 icon_path = path.realpath(icon_path)else: icon_path = resource_filename(requirement.parse(win10toast), win10toast/data/python.ico)# 加载格式icon_flags = lr_loadfromfile | lr_defaultsizetry: hicon = loadimage(self.hinst, icon_path, image_icon, 0, 0, icon_flags)except exception as e: logging.error(some trouble with the icon ({}): {} .format(icon_path, e)) hicon = loadicon(0, idi_application)# 任务栏图标flags = nif_icon | nif_message | nif_tipnid = (self.hwnd, 0, flags, wm_user + 20, hicon, tooltip)shell_notifyicon(nim_add, nid)shell_notifyicon(nim_modify, (self.hwnd, 0, nif_info, wm_user + 20, hicon, balloon tooltip, msg, 200, title, niif_icon_mask))# 等待一会后销毁sleep(duration)destroywindow(self.hwnd)unregisterclass(self.wc.lpszclassname, none)这部分代码控制了通知弹出框的展示和销毁。如果你希望通知弹出框久一点再消失,可以适当修改传入的 duration 变量值。
destroywindow后,通知弹出框便消失了,整个 show_toast 的过程结束。
其实非常简单,从 createwindow 到 destroywindow 处理弹出框的各种属性,然后注销窗体,完成整个弹出流程。
3.扩展触发通知为了扩展监听的按键,并能监听按键触发,需要先了解 notify.py 是如何检测到按键变化的。
获取按键状态:
keyboard = ctypes.windll(user32.dll)vk_numlock = 0x90vk_capital = 0x14def get_capslock_state(): returns the current caps lock state(on/off) return caps lock on if keyboard.getkeystate(vk_capital) else caps lock offdef get_numlock_state(): returns the current num lock state(on/off) return num lock on if keyboard.getkeystate(vk_numlock) else num lock off可以看到,获取按键状态是通过 keyboard.getkeystate(xxxx) 实现的。
而这个xxxx是对应的按键的十六进制,比如 vk_numlock 是num键,对应的16进制代码是0x90,vk_capital 是大小写按键,对应的十六进制代码是0x14.
变量名是可以用户自定义的,比如大小写键有些人习惯称之为vk_capital,也有些人喜欢称之为 vk_capital,都可以,只要其最终对应的变量值为十六进制的0x14即可。
部分按键16进制清单如下(完整版可以阅读原文查看):
常数名称十六进制值对应按键
vk_back 08 backspace键
vk_tab 09 tab键
vk_clear 0c clear键(num lock关闭时的数字键盘5)
vk_return 0d enter键
vk_shift 10 shift键
vk_control 11 ctrl键
vk_menu 12 alt键
vk_pause 13 pause键
vk_capital 14 caps lock键
再来看看监听逻辑:
caps_curr = get_capslock_state()num_curr = get_numlock_state()while true: caps_change = get_capslock_state() num_change = get_numlock_state() if caps_curr != caps_change: if caps_change == caps lock on: pop_up(caps lock on, capslock_on.ico) else: pop_up(caps lock off, capslock_off.ico) caps_curr = caps_change time.sleep(0.1) if num_curr != num_change: if num_change == num lock on: pop_up(num lock on, numlock_on.ico) else: pop_up(num lock off, numlock_off.ico) num_curr = num_change time.sleep(0.2)在刚开始运行监听脚本时,先获取到按键的状态,在循环体中,不断地获得当前按键状态,如果发生了状态变化,则触发pop_up函数,弹出刚刚我们提到的show_toast函数:
def pop_up(body, icon): generates pop-up notification when state changes notification = toastnotifier() notification.show_toast(lock key state, body, icon_path=assets+icon, duration=1.5)整套监听并通知的机制还是非常简单的,如果我们想要自定义一些按键,你只需要在开头添加对应的按键的十六进制编码,然后添加一些监听函数。
比如我们想监听 esc 按键被按下:vk_escape=0x1b,使用 keyboard 模块添加一个钩子函数,监听按键:
import keyboard as kbdef hook_esc(button): alert if esc button is pressed esc_button = kb.keyboardevent('down', vk_escape, 'esc') if button.event_type == 'down' and esc_button.name == button.name: pop_up(esc pressed, capslock_on.ico) # 敲击后回填为none button.event_type = none然后再在循环体内添加判断逻辑:
kb.hook(hook_esc)效果如下:
当然,图标和标题还可以进一步优化:
比如将lock key state这个标题用 toast_title 变量替代,默认为lock key state。这样在调用pop_up函数的时候就能自定义标题了,效果如下:
总而言之,能扩展的东西非常多,这只是一个学习的例子,如果大家感兴趣的话可以在 python实用宝典 公众号后台回复 按键触发通知 下载完整源代码进行改造。
了解直流电气特性的微控制器-Understanding DC
了解单层金属芯PCB及其优势
歌尔光学新一代小型化高性能AR显示模组
常见的华三H3C光模块型号大全
小区水泵监控系统解决方案
Python 制作按键触发Windows通知的脚本
微克科技PCB专用电子材料项目建设开工
Diodes推出全新的 PAM8106 10W 立体声 D 类音频放大器
关于工业机器人的位置控制
业界最快的采样速率数字电流检测放大器
国内首款量产的车规级共晶工艺封装灯珠
应用于医疗监护仪扩展接口的I2C总线分析器的设计
如何用MOS管实现防反接电路以及降压电路呢?
区块链技术将可以解决WiFi网络存在的重大安全漏洞
什么是无线网关,无线网关的功能都有哪些
采用DSP处理器和SPI总线实现IP视频电话高速硬件加密引擎的应用方案
联邦快递的燃料电池电动货车已经用于运送货物了
更懂企业用户,皓丽会议电视的双模式有什么不同?
腾达携多款新品惊艳亮相2018天翼智能生态博览会
关于荧光定量瘦肉精检测仪的详细介绍