2008-11-08 51 views

回答

4

一个第一可能的解决方案是...通过GUI(但无需用户交互)

VB script(也described here但在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. 
; 
+8

请不要把这个投入生产代码 – 2008-11-09 05:57:29

3

这种操作不能从PowerShell直接访问,因为没有.NET接口这些设置。很多核心操作系统的东西都是非托管代码,只能通过win32 API调用进行操作。虽然您可能正在使用WMI进行某些操作,但我搜索了一段时间,但无法找到能够操作此设置的令人满意的WMI类。

下一步是直接修改注册表。它看起来像设置位于HKLM:\ system \ CurrentControlSet \ control \ video - 某处。我相信这是一个名为“Attach.ToDesktop”的人。

这是一个部分解决方案,所以我将其标记为社区wiki答案。

我不确定这是正确的注册表键,而且我没有可以在此刻测试多显示器的系统。这样做的目的是确定哪个是主控制器,然后输出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" 
0

我不得不做一些小的修改来让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}") 
2

我做了一个不使用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; 
    } 
} 

我只在新安装的计算机上测试过。 I created a a snippet here if you would like to make changes to it

1

这是我用于切换显示器的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的任何机器上运行的可执行文件。

14

Windows 7,8和10应该有一个小程序来完成这个工作:displayswitch.exe。 This page列出了以下参数:

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

对于一键式解决方案所提出的问题,只需创建一个*。包含单行的蝙蝠文件

call displayswitch.exe/extend 

并将其保存到桌面。

[我测试了在Windows 8.1中,它已被证实在Windows 10运行]

相关问题