【问题标题】:Disconnect and Reconnect Displays Programmatically以编程方式断开和重新连接显示器
【发布时间】:2014-10-02 20:39:00
【问题描述】:

问题:以编程方式断开和重新连接显示器的最佳方式是什么?

目标:关闭显示器上的视频输出(无背光的黑屏),然后再将其重新打开。想象一下从显示器上拔下视频线,然后重新插入。

我的尝试:

// Get the monitor to disable
uint iDevNum = 0;
DISPLAY_DEVICE displayDevice = new DISPLAY_DEVICE();
displayDevice.cb = Marshal.SizeOf(displayDevice);
EnumDisplayDevices(null, iDevNum, ref displayDevice, 0))

DEVMODE devMode = new DEVMODE();
EnumDisplaySettings(displayDevice.DeviceName, 0, ref devMode);

//
// Do something here to disable this display device!
//

// Save the display settings
ChangeDisplaySettingsEx(displayDevice.DeviceName, ref devMode, 
    IntPtr.Zero, ChangeDisplaySettingsFlags.CDS_NONE, IntPtr.Zero);

我可以与每个显示器交互,但我不知道如何断开一个。

类似于 Windows 7 的屏幕分辨率属性中的“断开此显示器”:

注意事项:

  • 关闭所有显示器上的视频输出不起作用,因为我需要其他显示器保持打开状态。
  • “死”显示器上的桌面区域在关闭时不需要可用。另外,窗户可以左右移动。

参考资料:

  1. SO: Enabling a Second Monitor
  2. How to Turn Off a Monitor

【问题讨论】:

    标签: c# windows-7 multiple-monitors


    【解决方案1】:

    1) 从此处获取 MultiMonitorHelperhttps://github.com/ChrisEelmaa/MultiMonitorHelper/tree/master

    2) 扩展Win7Display断开显示器

    using MultiMonitorHelper.DisplayModels.Win7.Enum;
    using MultiMonitorHelper.DisplayModels.Win7.Struct;
    
    /// <summary>
    /// Disconnect a display.
    /// </summary>
    public void DisconnectDisplay(int displayNumber)
    {
        // Get the necessary display information
        int numPathArrayElements = -1;
        int numModeInfoArrayElements = -1;
        StatusCode error = CCDWrapper.GetDisplayConfigBufferSizes(
            QueryDisplayFlags.OnlyActivePaths,
            out numPathArrayElements,
            out numModeInfoArrayElements);
    
        DisplayConfigPathInfo[] pathInfoArray = new DisplayConfigPathInfo[numPathArrayElements];
        DisplayConfigModeInfo[] modeInfoArray = new DisplayConfigModeInfo[numModeInfoArrayElements];
        error = CCDWrapper.QueryDisplayConfig(
            QueryDisplayFlags.OnlyActivePaths,
            ref numPathArrayElements,
            pathInfoArray,
            ref numModeInfoArrayElements,
            modeInfoArray,
            IntPtr.Zero);
        if (error != StatusCode.Success)
        {
            // QueryDisplayConfig failed
        }
    
        // Check the index
        if (pathInfoArray[displayNumber].sourceInfo.modeInfoIdx < modeInfoArray.Length)
        {
            // Disable and reset the display configuration
            pathInfoArray[displayNumber].flags = DisplayConfigFlags.Zero;
            error = CCDWrapper.SetDisplayConfig(
                pathInfoArray.Length,
                pathInfoArray,
                modeInfoArray.Length,
                modeInfoArray,
                (SdcFlags.Apply | SdcFlags.AllowChanges | SdcFlags.UseSuppliedDisplayConfig));
            if (error != StatusCode.Success)
            {
                // SetDisplayConfig failed
            }
        }
    }
    

    3) 使用this post 的回答将Win7Display 扩展到重新连接显示器

    using System.Diagnostics;
    
    /// <summary>
    /// Reconnect all displays.
    /// </summary>
    public void ReconnectDisplays()
    {
        DisplayChanger.Start();
    }
    
    private static Process DisplayChanger = new Process
    {
        StartInfo =
        {
            CreateNoWindow = true,
            WindowStyle = ProcessWindowStyle.Hidden,
            FileName = "DisplaySwitch.exe",
            Arguments = "/extend"
        }
    };
    

    4) 更新IDisplay中的方法。

    5) 实现方法:

    IDisplayModel displayModel = DisplayFactory.GetDisplayModel();
    List<IDisplay> displayList = displayModel.GetActiveDisplays().ToList();
    
    displayList[0].DisconnectDisplay(0);
    displayList[0].ReconnectDisplays();
    

    【讨论】:

    • CCDWrapper 现在只是 CCD 命名空间中的 Wrapper
    【解决方案2】:

    有一个 github 项目我还没有完成,但它是一个起点。 您需要使用 Win7 特定的 API 才能更改设置。 ChangeDisplaySettings 将不起作用。

    看看:https://github.com/ChrisEelmaa/MultiMonitorHelper

    这是你需要做的:

    更新IDisplay接口以支持TurnOff()方法,

    然后调用它:

    var displayModel = DisplayFactory.GetDisplayModel();
    var displayList = displayModel.GetActiveDisplays().ToList();
    var firstDisplay = displayList[0].TurnOff();
    

    如何实现 TurnOff()?我想这是怎么回事(我现在可能错了):

    您需要通过断开“路径”来断开 GPU 和显示器之间的连接。您可以像这样中断源和目标之间的路径:

    调用SetDisplayConfig() 并传入特定路径,确保从DISPLAY_PATH_INFO 结构flags 整数映射出DISPLAYCONFIG_PATH_ACTIVE

    http://msdn.microsoft.com/en-us/library/windows/hardware/ff553945(v=vs.85).aspx

    很抱歉没有提供更多帮助,但这是非常核心的东西,我花了很长时间才了解该 API 的基础知识。这是一个起点:-),

    看一下如何在Win7中旋转特定显示器的例子:How do I set the monitor orientation in Windows 7?

    老实说,只需为 Win7 包装 DisplaySwitch.exe,然后传递 /internal 或 /external(取决于您是否要禁用/启用第一个/第二个监视器),这可能适用于 >2监视器。

    【讨论】:

    • 你的github挂了,能重新打开吗
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多