Processing Ajax...

Title

Message

Confirm

Confirm

Confirm

Confirm

Are you sure you want to delete this item?

Confirm

Are you sure you want to delete this item?

Confirm

Are you sure?

Turn off target monitor (requires monitor to support DDC)

Description
To turn off the target monitor, you can use a "lock screen" trigger to automatically turn off the secondary screen when the lock screen is pressed. Simply replace DP1 in the code with the name of the secondary screen that needs to be turned off. The secondary screen needs to support DDC.
Language
C#.net
Minimum Version
Created By
DubheBroken
Contributors
-
Date Created
2d ago
Date Last Modified
2d ago

Scripted Function (Macro) Code

using System;
using System.Collections.Generic;
using System.Management;
using System.Windows.Forms;
using System.Text;
using System.Runtime.InteropServices;
using System.Drawing;

public static class DisplayFusionFunction
{
    // =========================
    // 常量参数 - 要关闭的显示器名称
    // =========================
    private const string TARGET_MONITOR_NAME = "DP1";

    // 存储显示器真名到硬件ID的映射
    private static Dictionary<string, string> monitorHardwareIdMap = new Dictionary<string, string>();

    // =========================
    // DDC/CI 相关 Win32 API
    // =========================
    private const byte VCP_POWER_MODE = 0xD6;
    private const uint POWER_OFF = 0x05;

    [StructLayout(LayoutKind.Sequential)]
    struct PHYSICAL_MONITOR
    {
        public IntPtr hPhysicalMonitor;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        public string szPhysicalMonitorDescription;
    }

    [DllImport("dxva2.dll", SetLastError = true)]
    static extern bool GetNumberOfPhysicalMonitorsFromHMONITOR(
        IntPtr hMonitor,
        out uint pdwNumberOfPhysicalMonitors);

    [DllImport("dxva2.dll", SetLastError = true)]
    static extern bool GetPhysicalMonitorsFromHMONITOR(
        IntPtr hMonitor,
        uint dwPhysicalMonitorArraySize,
        [Out] PHYSICAL_MONITOR[] pPhysicalMonitorArray);

    [DllImport("dxva2.dll", SetLastError = true)]
    static extern bool SetVCPFeature(
        IntPtr hMonitor,
        byte bVCPCode,
        uint dwNewValue);

    [DllImport("dxva2.dll", SetLastError = true)]
    static extern bool DestroyPhysicalMonitors(
        uint dwPhysicalMonitorArraySize,
        PHYSICAL_MONITOR[] pPhysicalMonitorArray);

    [DllImport("user32.dll")]
    static extern IntPtr MonitorFromPoint(Point pt, uint dwFlags);

    // =========================
    // 枚举显示设备(用于获取设备描述和设备ID)
    // =========================
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    static extern bool EnumDisplayDevices(string lpDevice, uint iDevNum, ref DISPLAY_DEVICE lpDisplayDevice, uint dwFlags);

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    struct DISPLAY_DEVICE
    {
        public int cb;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string DeviceName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        public string DeviceString;
        public uint StateFlags;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        public string DeviceID;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        public string DeviceKey;
    }

    // =========================
    // 主逻辑
    // =========================
    public static void Run()
    {
        List<string> monitorNames = new List<string>();
        bool hasTargetMonitor = false;
        monitorHardwareIdMap.Clear();

        try
        {
            using (var searcher = new ManagementObjectSearcher(@"Root\WMI", "SELECT * FROM WmiMonitorID"))
            {
                foreach (ManagementObject mo in searcher.Get())
                {
                    // 获取显示器真名
                    ushort[] nameArray = (ushort[])mo["UserFriendlyName"];
                    string displayName = null;
                    if (nameArray != null)
                    {
                        char[] chars = new char[nameArray.Length];
                        for (int i = 0; i < nameArray.Length; i++)
                            chars[i] = (char)nameArray[i];
                        displayName = new string(chars).Trim('\0', ' ', '\n', '\r');
                    }

                    // 获取实例名称(包含硬件ID)
                    string instanceName = mo["InstanceName"]?.ToString();
                    string hardwareId = null;
                    if (!string.IsNullOrEmpty(instanceName))
                    {
                        // 解析硬件ID:从 InstanceName 中提取第二个字段
                        int firstSlash = instanceName.IndexOf('\\');
                        if (firstSlash >= 0)
                        {
                            int secondSlash = instanceName.IndexOf('\\', firstSlash + 1);
                            if (secondSlash >= 0)
                                hardwareId = instanceName.Substring(firstSlash + 1, secondSlash - firstSlash - 1);
                            else
                                hardwareId = instanceName.Substring(firstSlash + 1);
                        }
                    }

                    if (!string.IsNullOrEmpty(displayName))
                    {
                        monitorNames.Add(displayName);

                        if (displayName == TARGET_MONITOR_NAME)
                            hasTargetMonitor = true;

                        if (!string.IsNullOrEmpty(hardwareId))
                            monitorHardwareIdMap[displayName] = hardwareId;
                    }
                }
            }

            int monitorCount = monitorNames.Count;

            // =========================
            // 条件判断
            // =========================
            if (monitorCount > 1 && hasTargetMonitor)
            {
                try
                {
                    TurnOffMonitorByName(TARGET_MONITOR_NAME);
                }
                catch
                {
                    // 静默失败
                }
            }
        }
        catch
        {
            // 静默失败
        }
    }

    // =========================
    // 根据显示器名称(真名)关闭对应的物理显示器(通过硬件ID匹配)
    // =========================
    static void TurnOffMonitorByName(string targetName)
    {
        if (!monitorHardwareIdMap.TryGetValue(targetName, out string targetHwId))
            return;

        foreach (Screen screen in Screen.AllScreens)
        {
            IntPtr hMonitor = MonitorFromPoint(
                new Point(screen.Bounds.Left + 1, screen.Bounds.Top + 1),
                2); // MONITOR_DEFAULTTONEAREST

            if (hMonitor == IntPtr.Zero)
                continue;

            DISPLAY_DEVICE dd = new DISPLAY_DEVICE();
            dd.cb = Marshal.SizeOf(dd);
            if (!EnumDisplayDevices(screen.DeviceName, 0, ref dd, 0))
                continue;

            // 从 DeviceID 中提取硬件ID
            string screenHwId = ExtractHardwareIdFromDeviceID(dd.DeviceID);

            if (!string.IsNullOrEmpty(screenHwId) && screenHwId.Equals(targetHwId, StringComparison.OrdinalIgnoreCase))
            {
                // 获取物理监视器数量
                if (!GetNumberOfPhysicalMonitorsFromHMONITOR(hMonitor, out uint count) || count == 0)
                    return;

                PHYSICAL_MONITOR[] monitors = new PHYSICAL_MONITOR[count];
                if (!GetPhysicalMonitorsFromHMONITOR(hMonitor, count, monitors))
                    return;

                // 遍历并发送关机指令
                for (int i = 0; i < monitors.Length; i++)
                {
                    SetVCPFeature(monitors[i].hPhysicalMonitor, VCP_POWER_MODE, POWER_OFF);
                }

                // 释放资源
                DestroyPhysicalMonitors(count, monitors);
                break;
            }
        }
    }

    // 从 DeviceID 中提取硬件ID(例如:从 "MONITOR\DELA0D2\{...}" 提取 "DELA0D2")
    private static string ExtractHardwareIdFromDeviceID(string deviceID)
    {
        if (string.IsNullOrEmpty(deviceID)) return null;
        int firstSlash = deviceID.IndexOf('\\');
        if (firstSlash >= 0)
        {
            int secondSlash = deviceID.IndexOf('\\', firstSlash + 1);
            if (secondSlash >= 0)
                return deviceID.Substring(firstSlash + 1, secondSlash - firstSlash - 1);
            else
                return deviceID.Substring(firstSlash + 1);
        }
        return null;
    }
}