para - "Extienda mi escritorio de Windows a este monitor" programáticamente
mostrar este equipo en escritorio windows 10 (6)
Me gustaría poder configurar "Extender mi escritorio de Windows en este monitor" a través del código. Un script de PowerShell sería ideal. WMI parece el camino a seguir, pero no tengo conocimiento en WMI.
Este tipo de operación no es directamente accesible desde PowerShell en el sentido de que no existe una interfaz .NET para estas configuraciones. Una gran cantidad de cosas del sistema operativo central es un código no administrado que solo puede ser manipulado a través de llamadas API de win32. Aunque es posible que tenga algo con WMI, busqué por un tiempo y no pude encontrar una clase WMI satisfactoria que pueda manipular esta configuración.
El siguiente paso sería modificar el registro directamente. Parece que la configuración se encuentra en HKLM: / system / CurrentControlSet / control / video - en algún lugar. Creo que es el llamado "Attach.ToDesktop".
Esta es una solución parcial, así que estoy marcando como respuesta wiki de la comunidad.
No estoy seguro de que esta sea la clave de registro correcta, y no tengo un sistema en el que pueda probar monitores múltiples en este momento. El propósito de esto es determinar cuál es el controlador primario y luego genera el valor de la clave 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"
Tuve que hacer algunas pequeñas modificaciones para que la secuencia de comandos de VonC funcionara en mi máquina. Ahora es un poco más genérico.
;
; — 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}")
He creado una versión más limpia que no usa 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;
}
}
Solo he probado esto en una computadora recién instalada. Creé un fragmento aquí si quieres hacer cambios en él
Aquí está mi AutoIt-Script para cambiar monitores ya que mi tarjeta de gráficos ATI no me permite tener 3 monitores activos al mismo tiempo. Tengo 2 monitores conectados y un televisor. Esta secuencia de comandos está haciendo lo que hace la secuencia de comandos de VonC, pero de una manera más efectiva y rápida.
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
¡Simplemente reemplace "SAMSUNG" con su tercer nombre de monitores / televisores y ya está listo! Como seguramente sabe, puede convertirlo en un ejecutable que se ejecuta en cualquier máquina, incluso sin AutoIt instalado.
Una primera posible solución es ... a través de la GUI (pero sin interacción del usuario)
Script VB (también descrito aquí pero en lenguaje 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
En Autoit, eso sería:
;
; — 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.
;
Se supone que Windows 7, 8 y 10 vienen con un pequeño programa que hace exactamente esto: displayswitch.exe. Esta página enumera los siguientes parámetros:
displayswitch.exe/internal Disconnect projector
displayswitch.exe/clone Duplicate screen
displayswitch.exe/extend Extend screen
displayswitch.exe/external Projector only (disconnect local)
Para una solución de un solo clic al problema planteado, simplemente cree un archivo * .bat que contenga la única línea
call displayswitch.exe/extend
y guárdalo en tu escritorio.
[Probé esto en Windows 8.1, y se ha confirmado que funciona en Windows 10.]