以编程方式断开和重新连接显示

时间:2014-10-02 20:39:00

标签: c# windows-7 multiple-monitors

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

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

我的尝试:

// 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中的屏幕分辨率属性中:

Windows 7 Screen Resolution Properties

注意:

  • 关闭所有显示器上的视频输出无法正常工作,因为我需要其他显示器继续使用。
  • "死"上的桌面区域显示屏关闭时无需使用。此外,如果窗户四处移动也没关系。

参考文献:

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

2 个答案:

答案 0 :(得分:1)

还有一个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()并传递特定路径,确保从DISPLAYCONFIG_PATH_ACTIVE结构标记整数中映射DISPLAY_PATH_INFO

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?

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

答案 1 :(得分:1)

1)从此处获取 MultiMonitorHelper https://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();