百木园-与人分享,
就是让自己快乐。

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

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

准备工作😀

方案设想

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

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

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

程序流程

image-20220404061309048

参考资料

下面是我参考过的资料

  • 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

image-20220404061521526

如果文章字体过小,请调整浏览器页面缩放。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

image-20220404061645230

设置键盘宏

image-20220404062812613

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

顺便炫一下我的小键盘

image-20220404062942699


来源:https://www.cnblogs.com/linxiaoxu/p/16098314.html
本站部分图文来源于网络,如有侵权请联系删除。

未经允许不得转载:百木园 » 多屏时在浏览器外部(非活动窗口)通过按键控制视频播放、激活非活动窗口并发送模拟按键

相关推荐

  • 暂无文章