项目文件夹

文件
2026-07-13 12:28:27 +08:00

239 行
7.6 KiB
Python

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
"""
阻塞鼠标侧键(前进键)和键盘 Caps Lock 事件
使用 pynput 监听鼠标和键盘事件,并阻止:
1. 鼠标前进侧键(X2 / Button.x2
2. 键盘 Caps Lock 键
适用于防止误触鼠标侧键或 Caps Lock 导致的意外操作。
运行方式:
python block_mouse_forward.py
退出方式:
按 Ctrl+C 终止程序
依赖安装:
pip install pynput
技术说明:
- 使用 win32_event_filter 有选择性地抑制特定事件
- 鼠标:Button.x1 为后退键,Button.x2 为前进键
- 键盘:Caps Lock 的 VK 码为 0x14
"""
from pynput import mouse, keyboard
import sys
class InputBlocker:
"""输入设备阻塞器"""
# Windows 鼠标消息常量
WM_XBUTTONDOWN = 0x020B
WM_XBUTTONUP = 0x020C
WM_XBUTTONDBLCLK = 0x020D
# XBUTTON 按键标识
XBUTTON1 = 0x0001 # 后退键
XBUTTON2 = 0x0002 # 前进键
# Windows 键盘虚拟键码
VK_CAPITAL = 0x14 # Caps Lock
def __init__(self):
"""初始化阻塞器"""
self.mouse_listener = None
self.keyboard_listener = None
# 统计计数器
self.mouse_forward_blocked = 0
self.mouse_back_detected = 0
self.capslock_blocked = 0
def create_mouse_filter(self):
"""
创建鼠标 Windows 事件过滤器
Returns:
callable: 鼠标事件过滤函数
"""
def win32_event_filter(msg, data):
"""
鼠标事件过滤器
Args:
msg: Windows 消息类型
data: MSLLHOOKSTRUCT 结构,包含鼠标数据
Returns:
bool: 返回 False 则隐藏该事件
"""
# 检查是否为 XBUTTON 按键消息
if msg in (self.WM_XBUTTONDOWN, self.WM_XBUTTONUP, self.WM_XBUTTONDBLCLK):
# 提取 XBUTTON 标识(高位字)
xbutton = (data.mouseData >> 16) & 0xFFFF
if xbutton == self.XBUTTON2:
# 前进键(X2- 阻塞
if msg == self.WM_XBUTTONDOWN:
self.mouse_forward_blocked += 1
print(f"🚫 已阻塞鼠标前进按键按下 #{self.mouse_forward_blocked}")
elif msg == self.WM_XBUTTONUP:
print(f"🚫 已阻塞鼠标前进按键松开 #{self.mouse_forward_blocked}")
# 调用 suppress_event() 阻止事件传递到系统
self.mouse_listener.suppress_event()
return False
elif xbutton == self.XBUTTON1:
# 后退键(X1- 仅记录,不阻塞
if msg == self.WM_XBUTTONDOWN:
self.mouse_back_detected += 1
print(f"⚠️ 检测到鼠标后退按键按下 #{self.mouse_back_detected}")
elif msg == self.WM_XBUTTONUP:
print(f"⚠️ 检测到鼠标后退按键松开 #{self.mouse_back_detected}")
return True
return win32_event_filter
def create_keyboard_filter(self):
"""
创建键盘 Windows 事件过滤器
Returns:
callable: 键盘事件过滤函数
"""
def win32_event_filter(msg, data):
"""
键盘事件过滤器
Args:
msg: Windows 消息类型(本过滤器基于 vkCode 判断,无需检查 msg
data: KBDLLHOOKSTRUCT 结构,包含键盘数据
Returns:
bool: 返回 False 则隐藏该事件
"""
# 检查是否为 Caps Lock 键(通过虚拟键码判断)
if data.vkCode == self.VK_CAPITAL:
# 阻塞 Caps Lock 按键
self.capslock_blocked += 1
# 根据消息类型判断是按下还是松开
if msg == 0x0100: # WM_KEYDOWN
print(f"🚫 已阻塞 Caps Lock 按键按下 #{self.capslock_blocked}")
elif msg == 0x0101: # WM_KEYUP
print(f"🚫 已阻塞 Caps Lock 按键松开 #{self.capslock_blocked}")
# 调用 suppress_event() 阻止事件传递到系统
self.keyboard_listener.suppress_event()
return False
return True
return win32_event_filter
def on_mouse_click(self, _x, _y, _button, _pressed):
"""
鼠标点击回调函数(空实现,所有处理都在过滤器中)
Args:
_x: 鼠标 X 坐标(未使用)
_y: 鼠标 Y 坐标(未使用)
_button: 按钮类型(未使用)
_pressed: 是否按下(未使用)
Returns:
bool: 返回 False 则停止监听器
"""
# 标记参数为有意不使用
_ = _x, _y, _button, _pressed
# 不显示普通按键,所有处理都在 win32_event_filter 中完成
return True
def on_key_press(self, _key):
"""
键盘按下回调函数(空实现,所有处理都在过滤器中)
Args:
_key: 按下的键(未使用)
Returns:
bool: 返回 False 则停止监听器
"""
# 标记参数为有意不使用
_ = _key
# 不显示普通按键,所有处理都在 win32_event_filter 中完成
return True
def start(self):
"""启动监听器"""
print("=" * 60)
print("🛡️ 输入设备阻塞器已启动")
print("=" * 60)
print("✅ 鼠标前进侧键(X2)将被完全阻塞")
print("✅ 键盘 Caps Lock 键将被完全阻塞")
print("⚠️ 鼠标后退侧键(X1)将被记录但不阻塞")
print("📝 按 Ctrl+C 退出程序")
print("=" * 60)
print()
# 创建鼠标监听器
self.mouse_listener = mouse.Listener(
on_click=self.on_mouse_click,
win32_event_filter=self.create_mouse_filter()
)
# 创建键盘监听器
self.keyboard_listener = keyboard.Listener(
on_press=self.on_key_press,
win32_event_filter=self.create_keyboard_filter()
)
# 启动两个监听器
self.mouse_listener.start()
self.keyboard_listener.start()
try:
# 保持程序运行
self.mouse_listener.join()
self.keyboard_listener.join()
except KeyboardInterrupt:
print("\n" + "=" * 60)
print("👋 程序已退出")
print(f" 阻塞鼠标前进按键: {self.mouse_forward_blocked} 次")
print(f" 检测鼠标后退按键: {self.mouse_back_detected} 次")
print(f" 阻塞 Caps Lock 按键: {self.capslock_blocked} 次")
print("=" * 60)
finally:
self.stop()
def stop(self):
"""停止监听器"""
if self.mouse_listener and self.mouse_listener.running:
self.mouse_listener.stop()
if self.keyboard_listener and self.keyboard_listener.running:
self.keyboard_listener.stop()
print("🛑 监听器已停止")
def main():
"""主函数"""
blocker = InputBlocker()
# 设置控制台 UTF-8 编码(Windows 兼容)
if sys.platform == "win32":
import codecs
# 确保 Windows 控制台正确显示中文
try:
sys.stdout.reconfigure(encoding="utf-8")
except AttributeError:
# Python < 3.7 的回退方案
sys.stdout = codecs.getwriter("utf-8")(sys.stdout.buffer, "strict")
blocker.start()
if __name__ == "__main__":
main()