programing

프로그래밍 방식으로 "Windows 바탕 화면을 이 모니터로 확장"

skycolor 2023. 8. 25. 23:26
반응형

프로그래밍 방식으로 "Windows 바탕 화면을 이 모니터로 확장"

코드를 통해 "Windows 바탕 화면을 이 모니터로 확장"을 설정할 수 있습니다.PowerShell 스크립트가 이상적입니다.WMI는 앞으로 나아갈 길인 것 같지만 저는 WMI에 대한 지식이 전혀 없습니다.

Windows 7(윈도우 7), 8(윈도우 8) 및 10(윈도우 10)에는 정확히 이 기능을 수행하는 작은 프로그램인 displayswitch. 페이지에는 다음 매개 변수가 나열됩니다.

displayswitch.exe /internal  Disconnect projector (same as "Show only on 1" from the Display Properties dialog)
displayswitch.exe /clone     Duplicate screen
displayswitch.exe /extend    Extend screen
displayswitch.exe /external  Projector only (disconnect local) (same as "Show only on 2" from the Display Properties dialog)

원클릭으로 제기된 문제를 해결하려면 한 줄로 구성된 *.bat 파일을 생성하기만 하면 됩니다.

call displayswitch.exe /extend

바탕 화면에 저장할 수 있습니다.

윈도우즈 1122H2에서 displayswitch.exe는 매개 변수를 사용하지 않는 것 같습니다.자세한 내용은 이 링크를 참조하십시오.권장 솔루션은 기본 제공 버전 대신 displayswitch.exe의 Windows-10 버전 복사본을 사용하는 것입니다.

저는 송신 키를 사용하지 않는 더 깨끗한 버전을 만들었습니다.

public class DisplayHelper
{
    [DllImport("user32.dll")]
    static extern DISP_CHANGE ChangeDisplaySettings(uint lpDevMode, uint dwflags);
    [DllImport("user32.dll")]
    static extern bool EnumDisplayDevices(string lpDevice, uint iDevNum, ref DISPLAY_DEVICE lpDisplayDevice, uint dwFlags);

    enum DISP_CHANGE : int
    {
        Successful = 0,
        Restart = 1,
        Failed = -1,
        BadMode = -2,
        NotUpdated = -3,
        BadFlags = -4,
        BadParam = -5,
        BadDualView = -1
    }

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

    [Flags()]
    enum DisplayDeviceStateFlags : int
    {
        /// <summary>The device is part of the desktop.</summary>
        AttachedToDesktop = 0x1,
        MultiDriver = 0x2,
        /// <summary>The device is part of the desktop.</summary>
        PrimaryDevice = 0x4,
        /// <summary>Represents a pseudo device used to mirror application drawing for remoting or other purposes.</summary>
        MirroringDriver = 0x8,
        /// <summary>The device is VGA compatible.</summary>
        VGACompatible = 0x16,
        /// <summary>The device is removable; it cannot be the primary display.</summary>
        Removable = 0x20,
        /// <summary>The device has more display modes than its output devices support.</summary>
        ModesPruned = 0x8000000,
        Remote = 0x4000000,
        Disconnect = 0x2000000
    }

    public static void EnableSecondaryDisplay()
    {
        var secondaryIndex = 1;
        var secondary = GetDisplayDevice(secondaryIndex);
        var id = secondary.DeviceKey.Split('\\')[7];

        using (var key = Registry.CurrentConfig.OpenSubKey(string.Format(@"System\CurrentControlSet\Control\VIDEO\{0}", id), true))
        {
            using (var subkey = key.CreateSubKey("000" + secondaryIndex))
            {
                subkey.SetValue("Attach.ToDesktop", 1, RegistryValueKind.DWord);
                subkey.SetValue("Attach.RelativeX", 1024, RegistryValueKind.DWord);
                subkey.SetValue("DefaultSettings.XResolution", 1024, RegistryValueKind.DWord);
                subkey.SetValue("DefaultSettings.YResolution", 768, RegistryValueKind.DWord);
                subkey.SetValue("DefaultSettings.BitsPerPel", 32, RegistryValueKind.DWord);
            }
        }

        ChangeDisplaySettings(0, 0);
    }

    private static DISPLAY_DEVICE GetDisplayDevice(int id)
    {
        var d = new DISPLAY_DEVICE();
        d.cb = Marshal.SizeOf(d);
        if (!EnumDisplayDevices(null, (uint)id, ref d, 0))
            throw new NotSupportedException("Could not find a monitor with id " + id);
        return d;
    }
}

새로 설치한 컴퓨터에서만 테스트했습니다.

이 작업은 PowerShell에서 직접 액세스할 수 없기 때문에 가 없습니다.이 설정에 대한 NET 인터페이스.많은 핵심 OS 항목은 win32 API 호출을 통해서만 조작할 수 있는 관리되지 않는 코드입니다.WMI를 사용하여 작업을 수행하는 동안 잠시 검색했지만 이 설정을 조작할 수 있는 WMI 클래스를 찾을 수 없었습니다.

다음 단계는 레지스트리를 직접 수정하는 것입니다.설정이 HKLM 아래에 있는 것 같습니다:\system\CurrentControlSet\control\video -- 어딘가에 있습니다.저는 그것이 "첨부"라고 불리는 것이라고 믿습니다.데스크톱으로".

이것은 부분적인 해결책이므로 커뮤니티 위키 답변으로 표시합니다.

이것이 올바른 레지스트리 키인지 확신할 수 없으며, 현재 멀티 모니터를 테스트할 수 있는 시스템이 없습니다.이 작업의 목적은 기본 컨트롤러를 결정한 다음 연결 값을 출력하는 것입니다.바탕 화면 키로.

param ( 
    $ControllerName = "$( throw 'ControllerName is a mandatory parameter' )"
)
$regPath = "HKLM:\system\CurrentControlSet\control\video"
$devDescStr = "Device Description"

Set-Location -path $regPath
$regSubKey = Get-ChildItem -recurse -include 0000
$devDescProperty = $regSubKey | Get-ItemProperty -name $devDescStr -erroraction SilentlyContinue 
$priDescProperty = $devDescProperty | Where-Object { $_.$devDescStr -match $ControllerName }
Set-Location -path $priDescProperty.PSPath
Get-ItemProperty -path . -name "Attach.ToDesktop"

다음은 C#의 다른 솔루션입니다(Windows-7용 기본 모니터 설정 방법을 통해 C#에서).

[Flags]
public enum SetDisplayConfigFlags : uint
{
    SDC_TOPOLOGY_INTERNAL = 0x00000001,
    SDC_TOPOLOGY_CLONE = 0x00000002,
    SDC_TOPOLOGY_EXTEND = 0x00000004,
    SDC_TOPOLOGY_EXTERNAL = 0x00000008,
    SDC_APPLY = 0x00000080
}

[DllImport("user32.dll", CharSet = CharSet.Unicode)]
private static extern long SetDisplayConfig(uint numPathArrayElements,
    IntPtr pathArray, uint numModeArrayElements, IntPtr modeArray, SetDisplayConfigFlags flags);

static void CloneDisplays() {
    SetDisplayConfig(0, IntPtr.Zero, 0, IntPtr.Zero, SetDisplayConfigFlags.SDC_TOPOLOGY_CLONE | SetDisplayConfigFlags.SDC_APPLY);
}

static void ExtendDisplays() {
    SetDisplayConfig(0, IntPtr.Zero, 0, IntPtr.Zero, SetDisplayConfigFlags.SDC_TOPOLOGY_EXTEND | SetDisplayConfigFlags.SDC_APPLY);
}

static void ExternalDisplay() {
    SetDisplayConfig(0, IntPtr.Zero, 0, IntPtr.Zero, SetDisplayConfigFlags.SDC_TOPOLOGY_EXTERNAL | SetDisplayConfigFlags.SDC_APPLY);
}

static void InternalDisplay() {
    SetDisplayConfig(0, IntPtr.Zero, 0, IntPtr.Zero, SetDisplayConfigFlags.SDC_TOPOLOGY_INTERNAL | SetDisplayConfigFlags.SDC_APPLY);
}

첫번째 가능한 해결책은...GUI를 통해(단, 사용자 상호 작용 없음)

VB 스크립트(여기서도 설명하지만 Autoit 언어로 설명됨):

Option Explicit
Dim WshShell, Dummy, Splash

On Error Resume Next

Set WshShell = WScript.CreateObject("WScript.Shell")

'Main
Call DoIt
WScript.Quit

Sub DoIt
wshshell.Run("%systemroot%\system32\control.exe desk.cpl,@0,3")

' Give Display Properties time to load
WScript.Sleep 1000
WshShell.SendKeys "2"
WScript.Sleep 10
WshShell.SendKeys "%E"
WScript.Sleep 500
WshShell.SendKeys "%A"
WshShell.SendKeys "{TAB}"
WshShell.SendKeys "{TAB}"
WshShell.SendKeys "{TAB}"
WshShell.SendKeys "{TAB}"
WshShell.SendKeys "{TAB}"
WshShell.SendKeys "{TAB}"
WshShell.SendKeys "{TAB}"
WshShell.SendKeys "{TAB}"
WshShell.SendKeys "{TAB}"
WshShell.SendKeys "{TAB}"
WshShell.SendKeys "{ENTER}"
End Sub 'DoIt

Autoit에서는 다음과 같습니다.

;
; — toggle-screen.au3
;

; exec cpanel app `display settings`
Run(”C:\WINDOWS\system32\control.exe desk.cpl,@0,3?”)

; wait for window to be active
WinWaitActive(”Display Settings”)

; select 2nd display
Send(”{TAB}”)
Send(”{DOWN}”)

; work back to the ‘extend desktop’ control
Send(”+{TAB}”)
Send(”+{TAB}”)
Send(”+{TAB}”)
Send(”+{TAB}”)
Send(”+{TAB}”)
Send(”+{TAB}”)
Send(”+{TAB}”)
Send(”+{TAB}”)
Send(”+{TAB}”)

; toggle ‘extend desktop’ control and apply
Send(”{SPACE}”)
Send(”{ENTER}”)

; wait for window to be active
WinWaitActive(”Display Settings”)

; accept
Send(”{TAB}”)
Send(”{ENTER}”)

;
; — E.O.F.
; 

자동 단축키의 2줄

두 번째 디스플레이:

RunWait C:\Windows\System32\DisplaySwitch.exe /extend

두 번째 디스플레이 꺼짐:

RunWait C:\Windows\System32\DisplaySwitch.exe /internal

-

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
#Persistent 

Any1stKeyUWantToTurnOn::RunWait C:\Windows\System32\DisplaySwitch.exe /extend
Any2stKeyUWantToTurnOff::RunWait C:\Windows\System32\DisplaySwitch.exe /internal

또는

당신은 github / BNK3R-Boy / DisplaySwitch에서 제 도구를 확인하고 사용해 볼 수 있습니다.제가 지금 출판했습니다.

ATI 그래픽 카드에서는 모니터 3개를 동시에 활성화할 수 없기 때문에 모니터 전환을 위한 AutoI 스크립트가 여기 있습니다.모니터 2개와 TV 1개가 부착되어 있습니다.이 스크립트는 VonC의 스크립트가 수행하는 작업을 더 효과적이고 빠른 방식으로 수행하고 있습니다.

Run("C:\WINDOWS\system32\control.exe desk.cpl", "C:\Windows\system32\")
WinWait("Screen Resolution")
ControlCommand("Screen Resolution", "", "ComboBox1", "SetCurrentSelection", "SAMSUNG")

if (ControlCommand("Screen Resolution", "", "ComboBox3", "GetCurrentSelection", "") = "Disconnect this display") Then
    ControlCommand("Screen Resolution", "", "ComboBox1", "SetCurrentSelection", "2")
    ControlCommand("Screen Resolution", "", "ComboBox3", "SetCurrentSelection", "3")
    ControlCommand("Screen Resolution", "", "ComboBox1", "SetCurrentSelection", "0")
    ControlCommand("Screen Resolution", "", "ComboBox3", "SetCurrentSelection", "1")
    ControlClick("Screen Resolution", "", "Button4")
    WinWait("Display Settings")
    ControlClick("Display Settings", "", "Button1")
Else
    ControlCommand("Screen Resolution", "", "ComboBox3", "SetCurrentSelection", "3")
    ControlCommand("Screen Resolution", "", "ComboBox1", "SetCurrentSelection", "2")
    ControlCommand("Screen Resolution", "", "ComboBox3", "SetCurrentSelection", "1")
    ControlClick("Screen Resolution", "", "Button4")
    WinWait("Display Settings")
    ControlClick("Display Settings", "", "Button1")
EndIf

"SAMSUNG"을 세 번째 모니터/tvs 이름으로 바꾸기만 하면 모든 준비가 완료됩니다!AutoIt를 설치하지 않아도 어떤 컴퓨터에서도 실행되는 실행 파일로 변환할 수 있습니다.

저는 VonC의 스크립트가 제 기계에서 작동하도록 하기 위해 약간의 수정을 해야 했습니다.그것은 이제 조금 더 일반적입니다.

;
; — toggle-screen2.au3
;

#include <WinAPI.au3>
; exec cpanel app `display settings`
Run(_WinAPI_ExpandEnvironmentStrings("%windir%") & "\system32\control.exe desk.cpl,@0,3?")

; wait for window to be active
WinWaitActive("Display Properties")

; select 2nd display
Send("!d")
Send("{DOWN}")

; toggle the ‘extend desktop’ checkbox
Send("!e")

; close the dialog
Send("{ENTER}")

윈도우 키 + P 버튼은 동일한 기능을 수행합니다.

언급URL : https://stackoverflow.com/questions/275063/extend-my-windows-desktop-onto-this-monitor-programmatically

반응형