Python制作Windows按鍵通知腳本
前言
對于鍵盤沒有背光燈的同學而言,切換大小寫或控制Num鍵開關(guān)的時候沒有提示,經(jīng)常需要試探性地輸入一些字符來判斷開關(guān)是否打開,體驗非常糟糕。
因此,有人就想到自制腳本這一招,一旦觸發(fā)大小寫切換或Num鍵切換就進行windows通知提示:
https://github.com/skate1512/Toggle_Keys_Notification
今天我們來試試這個腳本,此外,我們還可以基于這個項目,擴展成任意一個按鍵被觸發(fā)或切換都進行 windows 通知的腳本:
1.準備
開始之前,你要確保Python和pip已經(jīng)成功安裝在電腦上,如果沒有,可以訪問這篇文章:超詳細Python安裝指南進行安裝。
(可選1)如果你用Python的目的是數(shù)據(jù)分析,可以直接安裝Anaconda,它內(nèi)置了Python和pip.
(可選2)此外,推薦大家用VSCode編輯器,它有許多的優(yōu)點
請選擇以下任一種方式輸入命令安裝依賴:
1. Windows 環(huán)境 打開 Cmd (開始-運行-CMD)。
2. MacOS 環(huán)境 打開 Terminal (command+空格輸入Terminal)。
3. 如果你用的是 VSCode編輯器 或 Pycharm,可以直接使用界面下方的Terminal.
pip?install?win10toast
除此之外,我們需要下載作者的代碼,如果你能聯(lián)通GitHub,請前往以下地址下載:
https://github.com/skate1512/Toggle_Keys_Notification
2.源碼使用與解析
2.1 源碼使用
作者的項目可以在 Toggle_Keys_Notification 項目內(nèi),運行 notify.py 啟動監(jiān)聽:
python?notify.py
啟動后點擊一下大小寫切換鍵,觸發(fā)通知則說明代碼正常運轉(zhuǎn):
2.2 源碼分析
該項目通過win32gui和win32con實現(xiàn)了彈出toast進行通知的功能,最核心的_show_toast代碼位于 toast.py 中,下面是這個函數(shù)的部分代碼剖析:
注冊和創(chuàng)建 window :
message_map = {WM_DESTROY:?self.on_destroy, } # 注冊Window self.wc = WNDCLASS() self.hinst =?self.wc.hInstance = GetModuleHandle(None) self.wc.lpszClassName = str("PythonTaskbar")?# 定義該窗口結(jié)構(gòu)的名稱 self.wc.lpfnWndProc = message_map try: ????self.classAtom = RegisterClass(self.wc) except: ????pass # Window格式 style = WS_OVERLAPPED | WS_SYSMENU # 創(chuàng)建Window self.hwnd = CreateWindow(self.classAtom,?"Taskbar", style, ?????????????????????????0,?0, CW_USEDEFAULT, ?????????????????????????CW_USEDEFAULT, ?????????????????????????0,?0,?self.hinst, None) UpdateWindow(self.hwnd)
所使用到的win32模塊解析如下。
GetModuleHandle
: 獲取一個應用程序或動態(tài)鏈接庫的模塊句柄。
WM_DESTROY
: 關(guān)閉程序。
RegisterClass
:將定義好的Window屬性保存保存下來。
WS_OVERLAPPED
: 重疊式窗口,該式樣窗口 帶有一個標題欄和邊框。
WS_SYSMENU
: 具有 SYSTEM 菜單欄的樣式
CW_USEDEFAULT
: 采用系統(tǒng)默認位置
CreateWindow
這個函數(shù)有非常多的參數(shù),甚至有一個百度百科來詳細解析每一個參數(shù)的具體作用
了解win32這些模塊名稱的意義后,理解上述代碼的邏輯便很輕松了。
圖標加載及任務(wù)欄圖標顯示配置:
# 圖標 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_DEFAULTSIZE try: ????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) # 任務(wù)欄圖標 flags = NIF_ICON | NIF_MESSAGE | NIF_TIP nid = (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 的過程結(jié)束。
其實非常簡單,從 CreateWindow 到 DestroyWindow 處理彈出框的各種屬性,然后注銷窗體,完成整個彈出流程。
3.擴展觸發(fā)通知
為了擴展監(jiān)聽的按鍵,并能監(jiān)聽按鍵觸發(fā),需要先了解 notify.py 是如何檢測到按鍵變化的。
獲取按鍵狀態(tài):
keyboard = ctypes.WinDLL("User32.dll") VK_NUMLOCK =?0x90 VK_CAPITAL =?0x14 def?get_capslock_state(): ????"""Returns the current Caps Lock State(On/Off)""" ????return?"Caps Lock On"?if?keyboard.GetKeyState(VK_CAPITAL)?else?"Caps Lock Off" def?get_numlock_state(): ????"""Returns The current Num Lock State(On/Off)""" ????return?"Num Lock On"?if?keyboard.GetKeyState(VK_NUMLOCK)?else?"Num Lock Off"
可以看到,獲取按鍵狀態(tài)是通過 keyboard.GetKeyState(XXXX)
實現(xiàn)的。
而這個XXXX是對應的按鍵的十六進制,比如 VK_NUMLOCK
是Num鍵,對應的16進制代碼是0x90, VK_CAPITAL
是大小寫按鍵,對應的十六進制代碼是0x14.
變量名是可以用戶自定義的,比如大小寫鍵有些人習慣稱之為 VK_CAPITAL
,也有些人喜歡稱之為 VK_CAPITAL
,都可以,只要其最終對應的變量值為十六進制的0x14即可。
部分按鍵16進制清單如下(完整版可以閱讀原文查看):
常數(shù)名稱 | 十六進制值 | 對應按鍵 |
---|---|---|
VK_BACK | 08 | Backspace鍵 |
VK_TAB | 09 | Tab鍵 |
VK_CLEAR | 0C | Clear鍵(Num Lock關(guān)閉時的數(shù)字鍵盤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鍵 |
再來看看監(jiān)聽邏輯:
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)
在剛開始運行監(jiān)聽腳本時,先獲取到按鍵的狀態(tài),在循環(huán)體中,不斷地獲得當前按鍵狀態(tài),如果發(fā)生了狀態(tài)變化,則觸發(fā) pop_up
函數(shù),彈出剛剛我們提到的 show_toast
函數(shù):
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)
整套監(jiān)聽并通知的機制還是非常簡單的,如果我們想要自定義一些按鍵,你只需要在開頭添加對應的按鍵的十六進制編碼,然后添加一些監(jiān)聽函數(shù)。
比如我們想監(jiān)聽 ESC 按鍵被按下: VK_ESCAPE=0x1B
,使用 keyboard 模塊添加一個鉤子函數(shù),監(jiān)聽按鍵:
import?keyboard?as?kb def?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
然后再在循環(huán)體內(nèi)添加判斷邏輯:
kb.hook(hook_esc)
效果如下:
當然,圖標和標題還可以進一步優(yōu)化:
比如將Lock Key State這個標題用 toast_title 變量替代,默認為Lock Key State。這樣在調(diào)用pop_up函數(shù)的時候就能自定義標題了,效果如下:
到此這篇關(guān)于Python制作Windows按鍵通知腳本的文章就介紹到這了,更多相關(guān)Python Windows按鍵通知內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python3內(nèi)置模塊之base64編解碼方法詳解
這篇文章主要介紹了Python3內(nèi)置模塊之base64編解碼方法詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-07-07pandas如何將dataframe中的NaN替換成None
這篇文章主要介紹了pandas如何將dataframe中的NaN替換成None問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-08-08python通過pil模塊將raw圖片轉(zhuǎn)換成png圖片的方法
這篇文章主要介紹了python通過pil模塊將raw圖片轉(zhuǎn)換成png圖片的方法,實例分析了Python中pil模塊的使用技巧,并Image.fromstring函數(shù)進行了較為詳盡的分析說明,需要的朋友可以參考下2015-03-03用python3讀取python2的pickle數(shù)據(jù)方式
今天小編就為大家分享一篇用python3讀取python2的pickle數(shù)據(jù)方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-12-12分享Pandas庫中的一些寶藏函數(shù)transform()
Pandas具有很多強大的功能,transform就是其中之一,利用它可以高效地匯總數(shù)據(jù)且不改變數(shù)據(jù)行數(shù),transform是一種什么數(shù)據(jù)操作?如果熟悉SQL的窗口函數(shù),就非常容易理解了2021-09-09簡單了解Python下用于監(jiān)視文件系統(tǒng)的pyinotify包
這篇文章主要介紹了Python下用于監(jiān)視文件系統(tǒng)的pyinotify包,pyinotify基于inotify事件驅(qū)動機制,需要的朋友可以參考下2015-11-11