V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
gam2046
V2EX  ›  程序员

Sunshine & Moonlight 串流,在多物理显示器的情况下,如何优雅的切换? WIN32 API EnumDisplayDevices 如何判断监视器是否连接状态?

  •  
  •   gam2046 · 34 天前 · 604 次点击
    这是一个创建于 34 天前的主题,其中的信息可能已经有所发展或是发生改变。

    现状

    机器上连接有大于 1 个物理显示器,且分辨率不一致,串流时,无法简单的通过 displayswitch 切换扩展显示或复制显示,因为这样分辨率会被拉低到所有显示器中分辨率最低的那个。

    在这种情况下,即使通过虚拟显示器,有时候,游戏也会显示到物理显示器上,导致串流时什么都看不到。

    总结就是

    • 直接串流到物理显示器,分辨率无法与 moonlight 客户端匹配,手机、平板等,总是一些 PC 上不常见的分辨率
    • 虚拟监视器,可以任意自定义分辨率,但是在不断开其他监视器的情况下,无法确保游戏在虚拟监视器启动
    • 显示选项选择为复制的情况下,所有监视器分辨率会被降低到最低的监视器分辨率

    我的想法

    为了解决这个问题,我的思路是,在串流时,断开虚拟显示器以外的所有监视器,并将虚拟显示器设置到 moonlight 客户端分辨率。

    市面上,目前还没看到有类似的工具,但是好在写起来并不麻烦,只是简单的即使 WIN32 API 。

    但是这一步仍然遇到了问题。

    由于游戏时需要仅保留虚拟显示器,其他的均要断开,那么在游戏结束时就需要恢复监视器的原本连接状态。

    但是我发现通过EnumDisplayDevices(NULL, deviceIndex, &displayDevice, 0)返回的结构体PDISPLAY_DEVICEAStateFlags字段,无论是否已连接,值都是一样的。

    通过询问 Copilot ,告知可以通过EnumDisplaySettingsEx(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &devMode, 0),判断监视器的分辨率是否为 0 ,得值监视器是否已断开。

    但是,实际运行后发现,即使在设置中,将某个监视器 disconnect 后,此 API 依旧会正常返回其原先的分辨率。

    那么,这一步就卡死在这里了,因为我无法在开启虚拟监视器前,判断原本的状态,进而导致,无法在游戏后恢复原先的监视器连接状态。

    最后

    除了我想到的这个方法以外,在多个物理监视器的情况下,串流如何解决串流分辨率与客户端保持一致的问题?

    1 条回复    2025-01-10 16:23:14 +08:00
    Busby
        1
    Busby  
       20 天前
    试试 sunshine 基地版 https://github.com/qiin2333/Sunshine/releases/tag/alpha
    最近找到了这个。解决了我 4K+2K 物理显示器在使用虚拟显示器后需要黑屏的需求。另外串流分辨率能够自动跟客户端一致。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1741 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 82ms · UTC 05:21 · PVG 13:21 · LAX 21:21 · JFK 00:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.