2008-11-08 222 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運行]

相關問題