MPV:获取窗口的位置和大小?还是窗口移动/调整大小的事件?

时间:2019-08-19 09:33:55

标签: mpv

是否可以获取MPV媒体播放器窗口的当前位置和大小(或更改它们时会触发的事件)?


我正在尝试创建一个脚本,该脚本自动保存窗口的最后位置,然后在播放器启动时加载它。可以使用geometry设置启动位置,但不能读取。

在日志中记录了移动窗口时的情况:

[  34.308][d][vo/gpu/win32] move window: 1953:48

并调整大小:

[  37.990][v][vo/gpu] Resize: 1810x1004
[  37.990][v][vo/gpu] Window size: 1810x1004

有没有办法在(javascript)脚本中获取这些值或回调?我很遗憾在文档中找不到该事件,或者只是想念它?

我只能找到dwidthdheight,但是它们仅代表视频的大小,而不代表整个窗口或位置。

谢谢!

注意:我也在mpv's github上提出了此要求,但尚未回复。我会在任何一个回复时更新另一个。

1 个答案:

答案 0 :(得分:0)

我想出了一种使用mp.utils.subprocess来运行某些powershell脚本的方法,因为mpv没有任何API可以直接获得该位置。有点慢,但是可以用:

(ps1脚本:)

Add-Type @"
using System;
using System.Runtime.InteropServices;
public class Window {
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
}
public struct RECT
{
    public int Left;
    public int Top;
    public int Right;
    public int Bottom;
}
"@

$Handle = (Get-Process -Id $Args[0]).MainWindowHandle
$WindowRect = New-Object RECT
$GotWindowRect = [Window]::GetWindowRect($Handle, [ref]$WindowRect)
ConvertTo-Json($WindowRect)

这将为您提供一个json对象,该对象具有窗口的位置和大小。然后,您可以类似的方式使用SetWindowRect重新设置位置。请注意,此rect与您在mpv本身中用geometry设置的内容不对应,因为该rect还包括标题栏等。

编辑:

我做了一个更好的版本。

现在,powershell脚本获得了可与geometry一起使用的client-rect,因此现在打开mpv更加顺畅。

因此,新的powershell脚本:

Add-Type @"
using System;
using System.Runtime.InteropServices;
public class Window {
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool ClientToScreen(IntPtr hWnd, ref POINT lpPoint);
}
public struct RECT
{
    public int Left;
    public int Top;
    public int Right;
    public int Bottom;
}
public struct POINT
{
    public int x;
    public int y;
}
"@

$Handle = (Get-Process -Id $Args[0]).MainWindowHandle
$WindowRect = New-Object RECT
$ClientRect = New-Object RECT
$TopLeft = New-Object POINT
$BottomRight = New-Object POINT

[Window]::GetClientRect($Handle, [ref]$ClientRect) | out-null
$TopLeft.x = $ClientRect.Left
$TopLeft.y = $ClientRect.Top
$BottomRight.x = $ClientRect.Right
$BottomRight.y = $ClientRect.Bottom

[Window]::ClientToScreen($Handle, [ref]$TopLeft) | out-null
[Window]::ClientToScreen($Handle, [ref]$BottomRight) | out-null

$WindowRect.Left = $TopLeft.x
$WindowRect.Top = $TopLeft.y
$WindowRect.Right = $BottomRight.x
$WindowRect.Bottom = $BottomRight.y

ConvertTo-Json($WindowRect)

然后我有一个JavaScript插件,可以在一个简单的javascript插件中调用此ps1:

// Some setup used by both reading and writing
var dir = mp.utils.split_path(mp.get_script_file())[0]
var rect_path = mp.utils.join_path(dir, "last_window_rect.txt")

// Read last window rect if present
try {
    var rect_json = mp.utils.read_file(rect_path)
    var rect = JSON.parse(rect_json)

    var width = rect.Right - rect.Left
    var height = rect.Bottom - rect.Top
    mp.set_property("screen", 0)
    mp.set_property("geometry", width + "x" + height + "+" + rect.Left + "+" + rect.Top)
}
catch (e) {
    dump(e)
}

// Save the rect at shutdown
function save_rect() {
    var ps1_script = mp.utils.join_path(dir, "Get-Client-Rect.ps1")
    var rect_json = mp.utils.subprocess({ args: ["powershell", "&(\"" + ps1_script + "\")", mp.utils.getpid()], cancellable: false }).stdout
    mp.utils.write_file("file://" + rect_path, rect_json)
}
mp.register_event("shutdown", save_rect)

您也可以在我的github上找到这些脚本:https://github.com/TheOddler/mpv-config/tree/master/scripts,但我不能保证它们会永远保持不变。