For those who have no backlight on their keyboard, there is no prompt when switching case or controlling the Num key switch. It is often a bad experience to enter some characters tentatively to determine whether the switch is on or off.
As a result, one might think of homemade scripting as a way to notify windows whenever a case or Num switch is triggered:
https://github.com/skate1512/Toggle_Keys_Notification
Let's try this script today. In addition, based on this project, we can extend it to a script that notifies windows whenever a key is triggered or switched:
1. Prepare
1. Prepare
Select one of the following ways to enter command installation dependencies:
1. The Windows environment opens Cmd (Start-Run-CMD).
2. MacOS environment opens Terminal (command + space input Terminal).
3. If you are using a VSCode editor or Pycharm, you can use Terminal directly below the interface.
pip install win10toast
In addition, we need to download the author's code. If you can connect GitHub, go to the following address to download it:
https://github.com/skate1512/Toggle_Keys_Notification
If you can't connect GitHub or the network is slow, reply in the Python Utilities Public Number background: Key Trigger Notification to download the full source code for this article.
2. Source Code Use and Resolution
2.1 Source Use
Author's project can be in Toggle_ Keys_ Within the Notification project, run notify.py starts listening:
python notify.py
Click the case switch key once after boot, triggering the notification indicates that the code is working properly:
2.2 Source Code Analysis
This project implements pop-up toast notification via win32gui and win32con, the core of which is _ Show_ The toast code is in toast. In py, here is a partial code analysis of this function:
Register and create window s:
message_map = {WM_DESTROY: self.on_destroy, } # Register Window self.wc = WNDCLASS() self.hinst = self.wc.hInstance = GetModuleHandle(None) self.wc.lpszClassName = str("PythonTaskbar") # Define the name of the window structure self.wc.lpfnWndProc = message_map try: self.classAtom = RegisterClass(self.wc) except: pass # Window Format style = WS_OVERLAPPED | WS_SYSMENU # Create Window self.hwnd = CreateWindow(self.classAtom, "Taskbar", style, 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, self.hinst, None) UpdateWindow(self.hwnd)
The win32 module used is parsed below.
GetModuleHandle: Gets a module handle to an application or dynamic link library.
WM_DESTROY: Close the program.
RegisterClass: Save the defined Window s properties.
WS_OVERLAPPED: Overlapping window with a title bar and border.
WS_SYSMENU: Style with SYSTEM menu bar
CW_USEDEFAULT: Use system default location
CreateWindow has a lot of parameters, even a Baidu Encyclopedia to analyze the specific role of each parameter in detail, you can move on if you are interested:
https://baike.baidu.com/item/CreateWindow/5076220
Once you understand the meaning of the module names win32, it's easy to understand the logic of the above code.
Icon loading and taskbar icon display configuration:
# Icon if icon_path is not None: # Get Icon Address icon_path = path.realpath(icon_path) else: icon_path = resource_filename(Requirement.parse("win10toast"), "win10toast/data/python.ico") # Load Format 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) # Taskbar Icon 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)) # Wait a while and destroy sleep(duration) DestroyWindow(self.hwnd) UnregisterClass(self.wc.lpszClassName, None)
This part of the code controls the display and destruction of notification pop-up boxes. If you want to notify the pop-up box to disappear a little longer, you can modify the value of the incoming duration variable appropriately.
After DestroyWindow, the notification pop-up disappears and the entire show_ The toast process ends.
It's really simple, from CreateWindow to DestroyWindow, to process the various properties of a pop-up box, then log off the form and complete the entire pop-up process.
3. Extended Trigger Notification
In order to extend the keys you listen for and to listen for key triggers, you need to know notify first. How py detects key changes.
Get the key status:
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"
You can see that the keyboard is used to get the keyboard status. GetKeyState (XXXX) implementation.
And this XXXX is the hexadecimal of the corresponding key, such as VK_NUMLOCK is the Num key, corresponding to the hexadecimal code 0x90, VK_CAPITAL is a case key with hexadecimal code 0x14.
Variable names are user-customizable, such as case keys, which some people are accustomed to calling VK_CAPITAL, which some people like to call VK_CAPITAL, as long as its final corresponding variable value is hexadecimal 0x14.
The hexadecimal list of some keys is as follows (full version can read the original):
Constant Name | Hexadecimal Value | Corresponding keys |
---|---|---|
VK_BACK | 08 | Backspace key |
VK_TAB | 09 | Tab key |
VK_CLEAR | 0C | Clear key (Num Lock number keyboard 5 when off) |
VK_RETURN | 0D | Enter key |
VK_SHIFT | 10 | Shift key |
VK_CONTROL | 11 | Ctrl key |
VK_MENU | 12 | Alt key |
VK_PAUSE | 13 | Pause key |
VK_CAPITAL | 14 | Caps Lock key |
Let's look at listening logic again:
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)
When the listening script is first run, it gets the state of the key first, gets the current state of the key continuously in the loop body, and triggers pop_if the state changes Up function, pop up show_as we just mentioned Toast function:
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)
The whole set of mechanisms to listen for and notify is still very simple. If we want to customize some keys, you just need to start by adding the hexadecimal encoding of the corresponding keys and then add some listening functions.
For example, we want to listen for ESC keys being pressed: VK_ESCAPE=0x1B, add a hook function using the keyboard module to listen for keys:
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") # Backfill with None after tapping button.event_type = None
Then add logic to the loop:
kb.hook(hook_esc)
The results are as follows:
Of course, icons and titles can be further optimized:
For example, use the title Lock Key State with toast_ Tile variable substitution, defaulting to Lock Key State. This calls pop_ When you use the up function, you can customize the title as follows:
All in all, there's a lot to expand, and this is just an example of learning. If you're interested, you can revert to the programmer's Start Public Notice in the background, press trigger notification, download the full source code for modification.
This is the end of the article. Thank you for watching
To be honest, it's a pleasure to see some of the reader's responses in the background every time. I want to contribute some of my collection of programming dry goods to everyone, to give back to each reader, and I hope to help you.
The main dry goods are:
Over 2000 Python e-books (both mainstream and classic books should be available)
(2) Python Standard Library (most Chinese version)
3. Project Source (Forty or fifty interesting and classic hands-on projects and sources)
(4) Videos about Python basic introduction, crawling, web development, big data analysis (suitable for white learning)
_Summary of all Python knowledge points (you can understand all Python directions and techniques)
* If you can use it, you can take it directly. In my QQ technical exchange group, you can take it by yourself. The group number is 857113825. *