本文章是第一次更新,更新于 2022年4月4日
准备工作😀
方案设想
前面我们使用 Python
编写了快捷键自动剪贴板加水印小工具,昨天我又想到了一个问题。
在用 Typora
通过视频写学习笔记的时候,遇到没听懂的点,需要把视频往前拖几秒,这时候因为当前活动窗口是 Typora
所以需要先回到浏览器窗口,然后再拖动视频进度,十分麻烦。
于是我想能不能写一个全局快捷键,直接通过快捷键的形式拖动视频进度
程序流程
参考资料
下面是我参考过的资料
- How To Send Inputs to Multiple Windows and Minimized Windows with Python - LearnCodeByGaming.com
- SendMessage function (winuser.h) - Win32 apps | Microsoft Docs
- winapi - Python win32api SendMesage - Stack Overflow
- Send some keys to inactive window with python - Stack Overflow
- Virtual-Key Codes (Winuser.h) - Win32 apps | Microsoft Docs
- Handling the keyboard — pynput 1.7.6 documentation
- SetForegroundWindow,SetActiveWindow, or ShowWindow? - SegmentFault
代码下载
代码:WMDVideo.zip
如果文章字体过小,请调整浏览器页面缩放。Windows: Ctrl + 鼠标滚轮
本篇文章代码注释可能使用了 vscode 的 better-comments 拓展
视频演示
您的浏览器不支持 HTML5 video 标签。
多屏用户真是爽呆了!
程序编写
我们需要引入两个必备的库,一个是 win32api
,一个是 pynput
。前者负责窗口获取和发送信息,后者负责监控全局快捷键。
获取视频窗口
def list_window_names(keyword):
items = []
def winEnumHandler(hwnd, ctx):
if win32gui.IsWindowVisible(hwnd):
name = win32gui.GetWindowText(hwnd)
# print(hex(hwnd), \'\"\' + name + \'\"\')
if name.lower().find(keyword) != -1:
items.append(hwnd)
win32gui.EnumWindows(winEnumHandler, None)
print(\"find windows:\", len(items))
return items
这里使用了 win32gui
的枚举器。对可见窗口进行枚举,对每个窗口的名字进行匹配,如果匹配成功则将窗口句柄添加进入 items
数组。
获取旧窗口
def get_old_window():
oldhwnd = win32gui.GetForegroundWindow()
return oldhwnd
在切换窗口前先获取当前窗口,用于最后返回。
发送按键信息
def press_key(keyword, char, key):
newhwnds = list_window_names(keyword)
oldhwnd = get_old_window()
print(newhwnds, oldhwnd)
for hwnd in newhwnds:
hwnd = win32gui.GetWindow(hwnd, win32con.GW_CHILD)
try:
# if hwnd != oldhwnd:
sleep(0.1)
win32gui.SetForegroundWindow(hwnd)
if hwnd == oldhwnd:
print(\"not working\")
# pyautogui.press(key)
else:
win32api.SendMessage(hwnd, win32con.WM_KEYDOWN, char, 0)
sleep(0.1)
win32gui.SetForegroundWindow(oldhwnd)
except:
pass
-
如果此时窗口已经是视频窗口,则不会进行工作。这是一个bug,我用了两个库都没有效果。暂时不想解决。
-
sleep
函数是必须的,否则按键消息将发送不到具体窗口。 -
hwnd = win32gui.GetWindow(hwnd, win32con.GW_CHILD)
这部分其实是多余的,相当于获取子窗口句柄,去掉也能工作。 -
win32gui.SetForegroundWindow(hwnd)
将当前窗口提至最前。 -
win32api.SendMessage(hwnd, win32con.WM_KEYDOWN, char, 0)
对特定窗口发送按键信息。具体可以看微软的文档。
监控按键信息
def on_activate_VK_LEFT():
print(\'VK_LEFT\')
press_key(\"youtube\", VK_LEFT, \"left\")
def on_activate_VK_RIGHT():
print(\'VK_RIGHT\')
press_key(\"youtube\", VK_RIGHT, \"right\")
with keyboard.GlobalHotKeys({
\'<ctrl>+<alt>+,\': on_activate_VK_LEFT,
\'<ctrl>+<alt>+.\': on_activate_VK_RIGHT
}) as h:
h.join()
阻塞式多全局按键写法,具体可以看 pynput
的官方文档。
其他代码
获取当前窗口
import win32gui
# 获取窗口句柄
hwnd = win32gui.GetForegroundWindow()
# 获取窗口标题
win32gui.GetWindowText(hwnd)
查找窗口
import win32gui
# 根据标题查找窗口
title = \'文档\'
hwnd = win32gui.FindWindow(None, title)
设置当前窗口
import win32gui
# 根据句柄
hwnd = 5378992 #句柄应该是其他方法获取到的
win32gui.SetForegroundWindow(hwnd)
打包exe
在当前终端执行如下命令,film.ico 是我另外加的图标
pyinstaller -i film.ico --onefile work.py
设置键盘宏
这里我用了 via
,设置宏,比如 {KC_LCTL,KC_LALT,KC_COMM}
顺便炫一下我的小键盘
来源:https://www.cnblogs.com/linxiaoxu/p/16098314.html
本站部分图文来源于网络,如有侵权请联系删除。