简体   繁体   English

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

[英]Disconnect and Reconnect Displays Programmatically

Question: What is the best way to programmatically disconnect and reconnect displays programmatically? 问题:以编程方式以编程方式断开连接和重新连接显示的最佳方法是什么?

The Goal: Kill the video output (black screen with no backlight) on a display and later turn it back on. 目标:在显示器上杀死视频输出(没有背光的黑屏),然后再将其重新打开。 Imagine unplugging the video cord from the monitor, then plugging it back in. 想象一下,从显示器上拔下视频线,然后将其重新插入。

My Attempt: 我的尝试:

// 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);

I can interact with each display, but I can't figure out how to disconnect one. 我可以与每个显示器进行交互,但我无法弄清楚如何断开连接。

It is similar to "Disconnect this display" in the Screen Resolution properties in Windows 7: 它类似于Windows 7中屏幕分辨率属性中的“断开此显示”:

Windows 7屏幕分辨率属性

Notes: 笔记:

  • Turning off video output on all displays won't work because I need the other monitors to stay on. 关闭所有显示器上的视频输出将无法工作,因为我需要其他显示器保持打开状态。
  • The desktop area on the "dead" display does NOT need to be usable when it is off. “死”显示屏上的桌面区域在关闭时无需使用。 Also, it is fine if windows move around. 此外,如果窗户四处移动也没关系。

References: 参考文献:

  1. SO: Enabling a Second Monitor SO:启用第二个监视器
  2. How to Turn Off a Monitor 如何关闭显示器

There's a github project that I STILL haven't got around, but it's a starting point. 有一个github项目,我仍然没有,但它是一个起点。 You need to use Win7 specific API in order to change settings . 您需要使用Win7特定的API才能更改设置 ChangeDisplaySettings won't work. ChangeDisplaySettings无效。

Have a look: https://github.com/ChrisEelmaa/MultiMonitorHelper 看看: https//github.com/ChrisEelmaa/MultiMonitorHelper

This is what you need to do: 这是你需要做的:

update the IDisplay interface to support TurnOff() method, 更新IDisplay接口以支持TurnOff()方法,

and then call it: 然后调用它:

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

How to implement TurnOff()? 如何实现TurnOff()? I WOULD imagine this is how(I might be wrong here now): 我想象这就是(我现在可能在这里错了):

You need to break the connection between GPU & monitor through breaking the "paths". 您需要通过打破“路径”来打破GPU和监视器之间的连接。 You can break path between source and target like this: 你可以像这样打破源和目标之间的路径:

Call SetDisplayConfig () and pass inside specific paths and make sure you map out the DISPLAYCONFIG_PATH_ACTIVE from the DISPLAY_PATH_INFO structure flags integer. 调用SetDisplayConfig ()并传递特定路径,并确保从DISPLAY_PATH_INFO结构标记整数中映射出DISPLAYCONFIG_PATH_ACTIVE

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

Sorry for not being more helpful, but this is pretty hardcore stuff, it took me quite a while to even understand the basics of that API. 很抱歉没有更多的帮助,但这是非常核心的东西,我花了很长时间甚至了解该API的基础知识。 It's a starting point :-), 这是一个起点:-),

take a look at the example how to rotate specific monitor in Win7: How do I set the monitor orientation in Windows 7? 看看如何在Win7中旋转特定监视器的示例: 如何在Windows 7中设置监视器方向?

In all honesty, just wrap the DisplaySwitch.exe for Win7, and pass /internal or /external(depending if you want to disable/enable first/second monitor), this might or might not work for >2 monitors. 老实说,只需将DisplaySwitch.exe包装为Win7,然后传递/ internal或/ external(取决于您是否要禁用/启用第一个/第二个监视器),这可能适用于> 2个监视器,也可能不适用。

1) Get MultiMonitorHelper from here: https://github.com/ChrisEelmaa/MultiMonitorHelper/tree/master 1)从这里获取MultiMonitorHelperhttps//github.com/ChrisEelmaa/MultiMonitorHelper/tree/master

2) Extend Win7Display to disconnect the display : 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) Extend Win7Display to reconnect the display using an answer from this post : 3)使用此帖子的答案扩展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) Update the methods in IDisplay . 4)更新IDisplay中的方法。

5) Implement the methods: 5)实施方法:

IDisplayModel displayModel = DisplayFactory.GetDisplayModel();
List<IDisplay> displayList = displayModel.GetActiveDisplays().ToList();

displayList[0].DisconnectDisplay(0);
displayList[0].ReconnectDisplays();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM