«Расширить рабочий стол Windows на этот монитор» программно - PullRequest
16 голосов
/ 08 ноября 2008

Я хотел бы иметь возможность установить «Расширить рабочий стол Windows на этот монитор» с помощью кода. Сценарий PowerShell был бы идеальным. WMI, кажется, путь вперед, но у меня нет знаний по WMI.

Ответы [ 8 ]

21 голосов
/ 02 августа 2014

Предполагается, что Windows 7, 8 и 10 поставляются с небольшой программой, которая делает именно это: displaywitch.exe. На этой странице перечислены следующие параметры:

displayswitch.exe/internal  Disconnect projector
displayswitch.exe/clone     Duplicate screen
displayswitch.exe/extend    Extend screen
displayswitch.exe/external  Projector only (disconnect local)

Для решения поставленной задачи одним щелчком мыши просто создайте * .bat-файл, содержащий одну строку

call displayswitch.exe/extend

и сохраните его на рабочем столе.

[Я протестировал это на Windows 8.1, и было подтверждено, что он работает на Windows 10.]

4 голосов
/ 08 ноября 2008

Одним из первых возможных решений является ... через графический интерфейс (но без взаимодействия с пользователем)

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.
; 
3 голосов
/ 17 марта 2010

Я сделал более чистую версию, не использующую sendkeys.

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;
    }
}

Я проверял это только на недавно установленном компьютере. Я создал фрагмент здесь, если вы хотите внести в него изменения

3 голосов
/ 09 ноября 2008

Операции такого типа не доступны напрямую из PowerShell в том смысле, что к этим настройкам нет интерфейса .NET. Большая часть ядра ОС - это неуправляемый код, которым можно манипулировать только через вызовы win32 API. Хотя вы можете что-то делать с WMI, я некоторое время искал и не смог найти удовлетворительный класс WMI, который мог бы манипулировать этим параметром.

Следующим шагом будет изменение реестра напрямую. Похоже, что настройка находится в HKLM: \ system \ CurrentControlSet \ control \ video - где-то. Я считаю, что это называется Attach.ToDesktop.

Это частичное решение, поэтому я отмечаю ответ сообщества вики.

Я не уверен, что это правильный ключ реестра, и у меня нет системы, на которой я могу протестировать мультимониторинг в данный момент. Цель этого состоит в том, чтобы определить, какой контроллер является основным, и затем он выводит значение ключа Attach.ToDesktop.

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"
1 голос
/ 18 апреля 2018

2 строки в автоотключении

2-й дисплей на:

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

2-й дисплей выключен:

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 . Я опубликовал это прямо сейчас.

1 голос
/ 14 августа 2010

Вот мой AutoIt-скрипт для переключения мониторов, так как моя видеокарта ATI не позволяет мне активировать 3 монитора одновременно. У меня есть 2 монитора и телевизор. Этот скрипт делает то же, что и скрипт 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» на ваше третье название монитора / телевизора, и все готово! Как вы наверняка знаете, вы можете преобразовать его в исполняемый файл, который работает на любой машине, даже если AutoIt не установлен.

0 голосов
/ 25 июля 2018

Windows + клавиша P сделает то же самое

0 голосов
/ 21 мая 2009

Мне пришлось сделать несколько небольших модификаций, чтобы скрипт 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}")
...