Python 多屏时在浏览器外部(非活动窗口)通过按键控制视频播放、激活非活动窗口并发送模拟按键

本文章是第一次更新,更新于 2022年4月4日

准备工作😀

方案设想

前面我们使用 Python 编写了快捷键自动剪贴板加水印小工具,昨天我又想到了一个问题。

在用 Typora 通过视频写学习笔记的时候,遇到没听懂的点,需要把视频往前拖几秒,这时候因为当前活动窗口是 Typora 所以需要先回到浏览器窗口,然后再拖动视频进度,十分麻烦。

于是我想能不能写一个全局快捷键,直接通过快捷键的形式拖动视频进度


程序流程

image-20220404061309048


参考资料

下面是我参考过的资料


代码下载

代码:WMDVideo.zip

image-20220404061521526

如果文章字体过小,请调整浏览器页面缩放。Windows: Ctrl + 鼠标滚轮

本篇文章代码注释可能使用了 vscode 的 better-comments 拓展


视频演示

多屏用户真是爽呆了!


程序编写

我们需要引入两个必备的库,一个是 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

image-20220404061645230

设置键盘宏

image-20220404062812613

这里我用了 via ,设置宏,比如 {KC_LCTL,KC_LALT,KC_COMM}

顺便炫一下我的小键盘

image-20220404062942699


posted @ 2022-04-04 06:38  小能日记  阅读(90)  评论(0编辑  收藏  举报