0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Python 制作按鍵觸發(fā)Windows通知的腳本

科技綠洲 ? 來(lái)源:Python實(shí)用寶典 ? 作者:Python實(shí)用寶典 ? 2023-11-01 16:09 ? 次閱讀

對(duì)于鍵盤(pán)沒(méi)有背光燈的同學(xué)而言,切換大小寫(xiě)或控制Num鍵開(kāi)關(guān)的時(shí)候沒(méi)有提示,經(jīng)常需要試探性地輸入一些字符來(lái)判斷開(kāi)關(guān)是否打開(kāi),體驗(yàn)非常糟糕。

因此,有人就想到自制腳本這一招,一旦觸發(fā)大小寫(xiě)切換或Num鍵切換就進(jìn)行windows通知提示:

https://github.com/skate1512/Toggle_Keys_Notification

今天我們來(lái)試試這個(gè)腳本,此外,我們還可以基于這個(gè)項(xiàng)目,擴(kuò)展成任意一個(gè)按鍵被觸發(fā)或切換都進(jìn)行 windows 通知的腳本:

圖片

1.準(zhǔn)備

開(kāi)始之前,你要確保Pythonpip已經(jīng)成功安裝在電腦上,如果沒(méi)有,請(qǐng)?jiān)L問(wèn)這篇文章:超詳細(xì)Python安裝指南 進(jìn)行安裝。如果你用Python的目的是數(shù)據(jù)分析,可以直接安裝Anaconda:Python數(shù)據(jù)分析與挖掘好幫手—Anaconda,它內(nèi)置了Python和pip.

此外,推薦大家用VSCode編輯器,因?yàn)樗梢栽诰庉嬈飨路降慕K端運(yùn)行命令安裝依賴(lài)模塊:Python 編程的最好搭檔—VSCode 詳細(xì)指南。

Windows環(huán)境下打開(kāi) Cmd (開(kāi)始-運(yùn)行-CMD),蘋(píng)果系統(tǒng)環(huán)境下請(qǐng)打開(kāi) Terminal (command+空格輸入Terminal),輸入命令安裝依賴(lài):

pip install win10toast

除此之外,我們需要下載作者的代碼,如果你能聯(lián)通GitHub,請(qǐng)前往以下地址下載:
https://github.com/skate1512/Toggle_Keys_Notification

如果不能聯(lián)通GitHub,或者網(wǎng)絡(luò)速度比較慢,請(qǐng)?jiān)赑ython實(shí)用寶典公眾號(hào)后臺(tái)回復(fù):按鍵觸發(fā)通知 下載本文完整源代碼。

2.源碼使用與解析

2.1 源碼使用

作者的項(xiàng)目可以在 Toggle_Keys_Notification 項(xiàng)目?jī)?nèi),運(yùn)行 notify.py 啟動(dòng)監(jiān)聽(tīng):

python notify.py

啟動(dòng)后點(diǎn)擊一下大小寫(xiě)切換鍵,觸發(fā)通知?jiǎng)t說(shuō)明代碼正常運(yùn)轉(zhuǎn):

圖片

2.2 源碼分析

該項(xiàng)目通過(guò)win32gui和win32con實(shí)現(xiàn)了彈出toast進(jìn)行通知的功能,最核心的_show_toast代碼位于 toast.py 中,下面是這個(gè)函數(shù)的部分代碼剖析:

注冊(cè)和創(chuàng)建 window :

message_map = {WM_DESTROY: self.on_destroy, }
# 注冊(cè)Window
self.wc = WNDCLASS()
self.hinst = self.wc.hInstance = GetModuleHandle(None)
self.wc.lpszClassName = str("PythonTaskbar") # 定義該窗口結(jié)構(gòu)的名稱(chēng)
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: 獲取一個(gè)應(yīng)用程序或動(dòng)態(tài)鏈接庫(kù)的模塊句柄。
WM_DESTROY: 關(guān)閉程序。
RegisterClass: 將定義好的Window屬性保存保存下來(lái)。
WS_OVERLAPPED: 重疊式窗口,該式樣窗口 帶有一個(gè)標(biāo)題欄和邊框。
WS_SYSMENU: 具有 SYSTEM 菜單欄的樣式
CW_USEDEFAULT: 采用系統(tǒng)默認(rèn)位置

CreateWindow 這個(gè)函數(shù)具有非常多的參數(shù),甚至有一個(gè)百度百科來(lái)詳細(xì)解析每一個(gè)參數(shù)的具體作用,大家感興趣可以移步:
https://baike.baidu.com/item/CreateWindow/5076220

了解win32這些模塊名稱(chēng)的意義后,理解上述代碼的邏輯便很輕松了。

圖標(biāo)加載及任務(wù)欄圖標(biāo)顯示配置:

# 圖標(biāo)
if icon_path is not None:
    # 獲取圖標(biāo)地址
    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ù)欄圖標(biāo)
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))

# 等待一會(huì)后銷(xiāo)毀
sleep(duration)
DestroyWindow(self.hwnd)
UnregisterClass(self.wc.lpszClassName, None)

這部分代碼控制了通知彈出框的展示和銷(xiāo)毀。如果你希望通知彈出框久一點(diǎn)再消失,可以適當(dāng)修改傳入的 duration 變量值。

DestroyWindow后,通知彈出框便消失了,整個(gè) show_toast 的過(guò)程結(jié)束。

其實(shí)非常簡(jiǎn)單,從 CreateWindow 到 DestroyWindow 處理彈出框的各種屬性,然后注銷(xiāo)窗體,完成整個(gè)彈出流程。

3.擴(kuò)展觸發(fā)通知

為了擴(kuò)展監(jiān)聽(tīng)的按鍵,并能監(jiān)聽(tīng)按鍵觸發(fā),需要先了解 notify.py 是如何檢測(cè)到按鍵變化的。

獲取按鍵狀態(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)是通過(guò) keyboard.GetKeyState(XXXX) 實(shí)現(xiàn)的。

而這個(gè)XXXX是對(duì)應(yīng)的按鍵的十六進(jìn)制,比如 VK_NUMLOCK 是Num鍵,對(duì)應(yīng)的16進(jìn)制代碼是0x90,VK_CAPITAL 是大小寫(xiě)按鍵,對(duì)應(yīng)的十六進(jìn)制代碼是0x14.

變量名是可以用戶(hù)自定義的,比如大小寫(xiě)鍵有些人習(xí)慣稱(chēng)之為VK_CAPITAL,也有些人喜歡稱(chēng)之為 VK_CAPITAL,都可以,只要其最終對(duì)應(yīng)的變量值為十六進(jìn)制的0x14即可。

部分按鍵16進(jìn)制清單如下(完整版可以閱讀原文查看):

常數(shù)名稱(chēng)十六進(jìn)制值對(duì)應(yīng)按鍵
VK_BACK08Backspace鍵
VK_TAB09Tab鍵
VK_CLEAR0CClear鍵(Num Lock關(guān)閉時(shí)的數(shù)字鍵盤(pán)5)
VK_RETURN0DEnter鍵
VK_SHIFT10Shift鍵
VK_CONTROL11Ctrl鍵
VK_MENU12Alt鍵
VK_PAUSE13Pause鍵
VK_CAPITAL14Caps Lock鍵

再來(lái)看看監(jiān)聽(tīng)邏輯:

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)

在剛開(kāi)始運(yùn)行監(jiān)聽(tīng)腳本時(shí),先獲取到按鍵的狀態(tài),在循環(huán)體中,不斷地獲得當(dāng)前按鍵狀態(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)聽(tīng)并通知的機(jī)制還是非常簡(jiǎn)單的,如果我們想要自定義一些按鍵,你只需要在開(kāi)頭添加對(duì)應(yīng)的按鍵的十六進(jìn)制編碼,然后添加一些監(jiān)聽(tīng)函數(shù)。

比如我們想監(jiān)聽(tīng) ESC 按鍵被按下:VK_ESCAPE=0x1B,使用 keyboard 模塊添加一個(gè)鉤子函數(shù),監(jiān)聽(tīng)按鍵:

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)

效果如下:

圖片

當(dāng)然,圖標(biāo)和標(biāo)題還可以進(jìn)一步優(yōu)化:

比如將Lock Key State這個(gè)標(biāo)題用 toast_title 變量替代,默認(rèn)為L(zhǎng)ock Key State。這樣在調(diào)用pop_up函數(shù)的時(shí)候就能自定義標(biāo)題了,效果如下:

圖片

總而言之,能擴(kuò)展的東西非常多,這只是一個(gè)學(xué)習(xí)的例子,如果大家感興趣的話可以在 Python實(shí)用寶典 公眾號(hào)后臺(tái)回復(fù) 按鍵觸發(fā)通知 下載完整源代碼進(jìn)行改造。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • WINDOWS
    +關(guān)注

    關(guān)注

    3

    文章

    3521

    瀏覽量

    88317
  • 鍵盤(pán)
    +關(guān)注

    關(guān)注

    4

    文章

    858

    瀏覽量

    39540
  • python
    +關(guān)注

    關(guān)注

    55

    文章

    4767

    瀏覽量

    84375
  • 腳本
    +關(guān)注

    關(guān)注

    1

    文章

    387

    瀏覽量

    14811
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    基于Python腳本的R語(yǔ)言的函數(shù)

    本文介紹了采用創(chuàng)建一個(gè)Python腳本,用該腳本模仿R風(fēng)格的函數(shù)的方法來(lái)方便地進(jìn)行統(tǒng)計(jì)。 是用R語(yǔ)言還是用Python語(yǔ)言?這是一個(gè)曠日持久的爭(zhēng)論。在此,我們可以嘗試采用折中路線:創(chuàng)建
    的頭像 發(fā)表于 10-12 09:33 ?2065次閱讀
    基于<b class='flag-5'>Python</b><b class='flag-5'>腳本</b>的R語(yǔ)言的函數(shù)

    10個(gè)殺手級(jí)的Python自動(dòng)化腳本

    今天浩道跟大家分享10個(gè)日常工作中用到的python自動(dòng)化腳本。讓你感受一番python簡(jiǎn)單強(qiáng)大之處!
    發(fā)表于 11-28 11:07 ?665次閱讀

    13個(gè)用于日常編程的高級(jí)Python腳本

    今天浩道跟大家分享13個(gè)用于日常編程的高級(jí)python腳本。讓你不會(huì)寫(xiě)腳本的也能感受到其魅力!
    發(fā)表于 12-09 11:47 ?609次閱讀

    制作Windows按鍵通知腳本

    對(duì)于鍵盤(pán)沒(méi)有背光燈的同學(xué)而言,切換大小寫(xiě)或控制Num鍵開(kāi)關(guān)的時(shí)候沒(méi)有提示,經(jīng)常需要試探性地輸入一些字符來(lái)判斷開(kāi)關(guān)是否打開(kāi),體驗(yàn)非常糟糕。
    的頭像 發(fā)表于 02-24 10:39 ?2065次閱讀
    <b class='flag-5'>制作</b><b class='flag-5'>Windows</b><b class='flag-5'>按鍵</b><b class='flag-5'>通知</b><b class='flag-5'>腳本</b>

    在執(zhí)行setupvars.bat腳本以初始化Windows10中OpenVINO環(huán)境時(shí),提示未安裝Python怎么解決?

    在執(zhí)行 setupvars.bat 腳本以初始化 Windows? 10 中OpenVINO?環(huán)境時(shí),遇到以下錯(cuò)誤消息: 未安裝 Python。
    發(fā)表于 08-15 06:52

    如何在 IIS 中執(zhí)行 Python 腳本

    如何在 IIS 中執(zhí)行 Python 腳本 Python 是一種解釋腳本語(yǔ)言,概念類(lèi)似 Microsoft Visual Basic Scripting Edition (VBSc
    發(fā)表于 02-23 15:13 ?1243次閱讀

    如何使html網(wǎng)頁(yè)與python腳本進(jìn)行通信

    現(xiàn)在運(yùn)行python腳本并轉(zhuǎn)到http://localhost/或http://localhost/并開(kāi)始按下按鈕,您應(yīng)該會(huì)在python腳本上看到輸入。
    的頭像 發(fā)表于 11-04 10:12 ?7833次閱讀

    Python】如何將Python腳本打包成exe可執(zhí)行文件

    Python實(shí)用技巧】如何將Python腳本打包成exe可執(zhí)行文件?
    的頭像 發(fā)表于 08-18 12:40 ?1.8w次閱讀
    【<b class='flag-5'>Python</b>】如何將<b class='flag-5'>Python</b><b class='flag-5'>腳本</b>打包成exe可執(zhí)行文件

    通過(guò)Python腳本實(shí)現(xiàn)WIFI密碼的暴力破解

    本文將記錄學(xué)習(xí)下如何通過(guò) Python 腳本實(shí)現(xiàn) WIFI 密碼的暴力破解。
    的頭像 發(fā)表于 09-19 09:55 ?6630次閱讀

    python3中制作腳本處理步進(jìn)電機(jī)沿滑軌和滾珠絲杠的運(yùn)動(dòng)

    電子發(fā)燒友網(wǎng)站提供《在python3中制作腳本處理步進(jìn)電機(jī)沿滑軌和滾珠絲杠的運(yùn)動(dòng).zip》資料免費(fèi)下載
    發(fā)表于 11-02 09:33 ?0次下載
    在<b class='flag-5'>python</b>3中<b class='flag-5'>制作</b><b class='flag-5'>腳本</b>處理步進(jìn)電機(jī)沿滑軌和滾珠絲杠的運(yùn)動(dòng)

    【shell腳本分享】性能指標(biāo)監(jiān)控與通知

    今天浩道跟大家分享一個(gè)關(guān)于性能監(jiān)控與通知相關(guān)的shell腳本!
    的頭像 發(fā)表于 01-09 09:35 ?1097次閱讀

    Python怎么玩轉(zhuǎn)JS腳本

    本項(xiàng)目旨在讓大家了解如何用Python來(lái)執(zhí)行JS腳本,其主要目的是在進(jìn)行數(shù)據(jù) 分析時(shí),需要利用爬蟲(chóng)獲取數(shù)據(jù),有時(shí)會(huì)遇到JS混淆加密反爬取難點(diǎn),此時(shí)我們需 要獲取網(wǎng)頁(yè)JS加密代碼將其轉(zhuǎn)換為Python代碼運(yùn)行,從而破解JS加密
    的頭像 發(fā)表于 02-23 16:26 ?1049次閱讀
    <b class='flag-5'>Python</b>怎么玩轉(zhuǎn)JS<b class='flag-5'>腳本</b>

    Python簡(jiǎn)單制作Windows按鍵通知腳本

    ,擴(kuò)展成任意一個(gè)按鍵觸發(fā)或切換都進(jìn)行 windows 通知腳本: 1.準(zhǔn)備 開(kāi)始之前,你要確保Pyt
    的頭像 發(fā)表于 10-17 11:10 ?626次閱讀
    <b class='flag-5'>Python</b>簡(jiǎn)單<b class='flag-5'>制作</b><b class='flag-5'>Windows</b><b class='flag-5'>按鍵</b><b class='flag-5'>通知</b><b class='flag-5'>腳本</b>

    Python超簡(jiǎn)單制作Windows按鍵通知腳本

    ,擴(kuò)展成任意一個(gè)按鍵觸發(fā)或切換都進(jìn)行 windows 通知腳本: 1.準(zhǔn)備 1.準(zhǔn)備 開(kāi)始之前,你要確保
    的頭像 發(fā)表于 11-01 09:24 ?418次閱讀
    <b class='flag-5'>Python</b>超簡(jiǎn)單<b class='flag-5'>制作</b><b class='flag-5'>Windows</b><b class='flag-5'>按鍵</b><b class='flag-5'>通知</b><b class='flag-5'>腳本</b>

    python調(diào)用windows命令

    Python是一種強(qiáng)大的編程語(yǔ)言,可以用于開(kāi)發(fā)各種不同類(lèi)型的應(yīng)用程序。其中一個(gè)常見(jiàn)的用途是使用Python調(diào)用Windows命令來(lái)執(zhí)行特定的任務(wù)。在本文中,我們將詳細(xì)討論如何使用Python
    的頭像 發(fā)表于 11-29 14:34 ?965次閱讀