È ansible mantenere le impostazioni di monitor multi monitor quando un monitor è "scollegato"?

Info di background

Recentemente ho completato una nuova impostazione 'Home Theatre' nella nostra nuova casa. Nel salotto ho un televisore e un bar acustico, e nel mio ufficio dall'altro lato del muro ho il mio PC (in esecuzione Plex), PS3, Xbox 360 e il router. Ho installato alcune nuove piastre frontali e ho eseguito un cavo HDMI, un cavo USB e un cavo cat6 tra le stanze. Nel mio ufficio ho il PC, PS3 e x360 collegati a uno splitter HDMI da 3 a 1, che poi corre verso il soggiorno TV.

Il mio problema è che posso get tutto il setup piacevole per utilizzare più monitor sul mio PC, get Plex setup per eseguire automaticamente sul televisore quando si avvia, e tutto quel tipo di cose. Tuttavia, se commuto l'interruttore HDMI sul PS3, effettivamente staccando il televisore come un monitor dal mio PC e quando tornerò è come se un nuovo monitor sia stato collegato e non conserva nessuna delle impostazioni precedenti. Questo è particolarmente frustrante per Plex / XBMC e Steam Big Picture che non ricordano di avviarsi su quel monitor.

La mia domanda

C'è un modo per mantenere tutte le impostazioni del monitor mutli per il televisore anche quando è effettivamente scollegato? La mia unica altra opzione è quella di acquistare e utilizzare un altro cavo HDMI attraverso la panetworking per dedicarsi al PC e utilizzare l'altro per passare da PS3 / X360. Quello functionrebbe bene, ma preferisco non spendere i soldi se non wheressi.

Grazie!

No, alless non senza utilità di terze parti; stai vedendo il comportmento previsto di Windows.

Controlla questa domanda SU: salva le posizioni di window delle applicazioni e / o Google per un'utilità che consente di salvare e ripristinare le pozioni di window / icone sul command. C'è un bel po 'di quelli che lo fanno, inclusi (possibilmente) i programmi di utilità del driver dello schermo.

Ho aperto un piccolo programma (due, in realtà) per risolvere questo problema.
Il primo per salvare le posizioni di tutte le windows:

 SaveWinPositions [NumMonitors] NumMonitors: (1 default) integer (positive) specifying the number of physical screens on the computer. The program will exit is at least this number of screens is not available. Zero (0) to ignore and save anyway. 

E il secondo per ripristinarli :

 RestoreWinPositions [NumMonitors] NumMonitors: (1 default) integer (positive) specifying the number of physical screens on the computer. The program will wait for this number of screens available to start restoring. Zero (0) to ignore and restore anyway. 

È ansible programmarli per eseguire a intervalli tramite Task Scheduler, eseguirli manualmente, tramite hotkey, eseguirli all'avvio / chiusura dello screensaver (questo è ciò che preferisco) … ecc.

Ecco i due eseguibili (e la fonte, ovviamente).

Aggiornamento: Non so perché, ma alcune persone riferiscono che SourceForge lo considera come malware, ecco qui il codice sorgente (script AHK ) per SaveWinPositions :

 ; SaveWinPositions ; Version v0.22 ; Obtiene el nombre, ID, posición y tamaño (x,y,w,h) de todas las ventanas. ; Incluídas las minimizadas. ; Crea un fichero "WinPos.txt" en %TEMP% conteniendo sus posiciones. ; Comprobamos que el programa no se ha activado por un disparo en falso (apagado/encendido casi simultáneo) del salvapantallas: FileGetTime, FechaOriginal, %TEMP%\WinPos.txt TiempoTranscurrido := A_Now-FechaOriginal If TiempoTranscurrido<=5 { ; Se grabaron datos de posiciones de ventanas hace 5 segundos o lesss. FileAppend, % "* " . A_YYYY . "-" . A_MM . "-" . A_DD . " " . A_Hour . ":" . A_Min . ":" . A_Sec . " --> " . "SaveWinPositions:-> Se grabaron datos de posiciones de ventanas hace " . TiempoTranscurrido . " segundos. Disparo en falso del salvapantallas. No se almacenarán posiciones de ventanas. Saliendo de SaveWinPositions. `n", %TEMP%\WinPositions-Log.txt TrayTip, SaveWinPositions, Se grabaron datos de posiciones de ventanas hace %TiempoTranscurrido% segundos. Disparo en falso del salvapantallas. Abortando., ,1 sleep 10000 Exit ; Disparo en falso del salvapantallas. Cancelando la ejecución del programa. } NumParametros = %0% Parametro1 = %1% NumeroDePantallasEsperado:=1 ; El sistema dispone de este número de pantallas en total. No se deben mover ventanas ni grabar sus posiciones si no están encendidas todas. ;Nótese que este será el valor por defecto de no ser especificado mediante parámetro en la línea de commands ni existir %A_WorkingDir%\screens.cfg. If ( NumParametros<1 ) ; Comprobamos el número de parámetros. { ; Si no hay parámetros, captubranchs el número de pantallas del fichero de configuración (por defecto en el directorio de ejecución del programa), si existe: IfExist, screens.cfg ; Si existe el fichero de configuración... { ; ... leemos de él el número de pantallas esperado. FileReadLine,NumeroDePantallasEsperado,%A_WorkingDir%\screens.cfg,1 FileAppend, % "* " . A_YYYY . "-" . A_MM . "-" . A_DD . " " . A_Hour . ":" . A_Min . ":" . A_Sec . " --> " . "SaveWinPositions:-> No se introdujeron parámetros, se utilizará el extraído del fichero de configuración.`n", %TEMP%\WinPositions-Log.txt } else { ; No existe el fichero de configuración: informamos en el log. FileAppend, % "* " . A_YYYY . "-" . A_MM . "-" . A_DD . " " . A_Hour . ":" . A_Min . ":" . A_Sec . " --> " . "SaveWinPositions:-> No existe el fichero de configuración.`n", %TEMP%\WinPositions-Log.txt } } else { ; Si hay parámetros... If ( Parametro1 = 0 ) ; si el parámetro es un 0... { ; Ignorar número de monitores IgnoreNumPantallas = 1 FileAppend, % "* " . A_YYYY . "-" . A_MM . "-" . A_DD . " " . A_Hour . ":" . A_Min . ":" . A_Sec . " --> " . "SaveWinPositions:-> Ignorando número de monitores: se ejecutará el programa sin esperarlos.`n", %TEMP%\WinPositions-Log.txt } else { ; si el parámetro es distinto de 0... ; ... el parámetro contiene el número de pantallas esperado: NumeroDePantallasEsperado = %1% } } If ( Parametro1 != 0 ) ; a lesss que se ignore el número de monitores... { ; ... añadimos una entrada al log con el número de pantallas necesarias. FileAppend, % "* " . A_YYYY . "-" . A_MM . "-" . A_DD . " " . A_Hour . ":" . A_Min . ":" . A_Sec . " --> " . "SaveWinPositions:-> Numero de monitores esperado: " . NumeroDePantallasEsperado ".`n", %TEMP%\WinPositions-Log.txt } ; Comprobamos que estén todos los monitores conectados: SysGet, m, MonitorCount If ( not IgnoreNumPantallas and m < NumeroDePantallasEsperado ) { FileAppend, % "* " . A_YYYY . "-" . A_MM . "-" . A_DD . " " . A_Hour . ":" . A_Min . ":" . A_Sec . " --> " . "SaveWinPositions:-> Número de pantallas actual: " . m . "; se esperaba al lesss " . NumeroDePantallasEsperado . ". Saliendo de SaveWinPositions. `n", %TEMP%\WinPositions-Log.txt TrayTip, SaveWinPositions, Número de pantallas actual: %m% (se esperaba al lesss %NumeroDePantallasEsperado%). Abortando., ,2 sleep 10000 Exit ; No están todas las pantallas. Cancelamos la ejecución del programa. } ; Comprobamos si el salvapantallas está activo: SalvaPantallas := WinExist("Protector de pantalla") FileAppend, % "* " . A_YYYY . "-" . A_MM . "-" . A_DD . " " . A_Hour . ":" . A_Min . ":" . A_Sec . " --> " . "SaveWinPositions:-> Grabando posiciones de las ventanas del Escritorio `n", %TEMP%\WinPositions-Log.txt FileDelete, %TEMP%\WindowsPositions.txt WinGet windows, List Loop %windows% { ContainsSpecialCharacter:=0 id := windows%A_Index% WinGetTitle wt, ahk_id %id% WinGet, WinStatus, MinMax, ahk_id %id% if (WinStatus=-1) { ; Esta ventana está minimizada. WinGetNormalPos(id, x, y, w, h) If (x+y+w+h=0) { ; Todas sus coordenadas parecen valer 0. Necesitamos restaurarla para capturarlas corréctamente. FileAppend, % "* " . A_YYYY . "-" . A_MM . "-" . A_DD . " " . A_Hour . ":" . A_Min . ":" . A_Sec . " --> " . "SaveWinPositions:-> Posible problema en ventana : " . wt . ". Es necesario restaurarla para detectar sus coordenadas." WinRestore, ahk_id %ID% WinGetPos, x,y,w,h,ahk_id %ID% WinMinimize, ahk_id %ID% WindowRestored:=1 } } else { ; Esta ventana no está minimizada. Recurrimos a captura normal de coordenadas. WinGetPos,x,y,w,h,ahk_id %id% } If (wt and wt!="Inicio") ; Ignore Windos Title null and "Inicio". { ; Añadir al fichero de datos: Coordenadas, dimensiones y título de la ventana. r .= ID . "," . x . "," . y . "," . w . "," . h . "," . wt . "`n" } FileAppend , %r%, %TEMP%\WindowsPositions.txt } ; Ordenamos por ID de ventana el fichero resultante: FileRead, OutputVar, %TEMP%\WindowsPositions.txt Sort, OutputVar, u ; Se producen duplicados de líneas, no sabemos aún porqué. :-P ; Duplicamos el fichero anteriormente existente de las posiciones de las ventanas, por si las moscas. FileDelete, %TEMP%\WinPos-.txt FileCopy, %TEMP%\WinPos--.txt, %TEMP%\WinPos---.txt FileCopy, %TEMP%\WinPos-.txt, %TEMP%\WinPos--.txt FileCopy, %TEMP%\WinPos.txt, %TEMP%\WinPos-.txt FileDelete, %TEMP%\WinPos.txt FileAppend, %OutputVar%,%TEMP%\WinPos.txt If (SalvaPantallas and WindowRestored) { ; El programa necesitó desactivar el salvapantallas. Procedemos a reactivarlo: FileAppend, % "* " . A_YYYY . "-" . A_MM . "-" . A_DD . " " . A_Hour . ":" . A_Min . ":" . A_Sec . " --> " . "SaveWinPositions:-> Estaba en funcionamiento el salvapantallas y hubo de ser desactivado. Reactivándolo..." ; Método alternativo para activación del salvapantallas (requiere NirSoft NirCmd en el path del sistema). Run, nircmdc screensaver } TrayTip, SaveWinPositions, Posiciones de ventanas grabadas para %NumeroDePantallasEsperado% pantalla(s)., ,1 ; Beeps report: correctly finished. SoundBeep 1500,100 SoundBeep 1000,100 SoundBeep 3500,100 sleep 10000 ; Funciones del programa WinGetNormalPos(hwnd, ByRef x, ByRef y, ByRef w="", ByRef h="") ; Devuelve la posición que tendría la ventana si no estuviera minimizada (posición restaurada). { VarSetCapacity(wp, 44), NumPut(44, wp) DllCall("GetWindowPlacement", "uint", hwnd, "uint", &wp) x := NumGet(wp, 28, "int") y := NumGet(wp, 32, "int") w := NumGet(wp, 36, "int") - x h := NumGet(wp, 40, "int") - y } 

E questo è il codice di RestoreWinPositions :

 FileDelete, %TEMP%\WinPosWorking.txt FileCopy, %TEMP%\WinPos.txt, %TEMP%\WinPosWorking.txt FileGetTime, FechaOriginal, %TEMP%\WinPos.txt TiempoTranscurrido := A_Now-FechaOriginal ArrayCount = 0 if TiempoTranscurrido>5 ; Disparo correcto del salvapantallas: activado/apagado no a la misma vez. { Loop, Read, %TEMP%\WinPosWorking.txt ; This loop retrieves each line from the file, one at a time. { ArrayCount += 1 ; Keep track of how many items are in the arrays. Array%ArrayCount% := A_LoopReadLine ; Store this line in the next arrays element. } FileAppend, % "# " . A_YYYY . "-" . A_MM . "-" . A_DD . " " . A_Hour . ":" . A_Min . ":" . A_Sec . " --> " . "RestoreWinPositions:--> Fichero de posiciones creado hace " . TiempoTranscurrido . " segundos (Correcto). Restaurando ventanas...." . " `n", %TEMP%\WinPositions-Log.txt TrayTip, RestoreWinPositions, Restaurando ventanas..., ,1 } if TiempoTranscurrido<=5 ; Disparo en falso del salvapantallas: activado/apagado (casi) a la misma vez. { FileAppend, % "# " . A_YYYY . "-" . A_MM . "-" . A_DD . " " . A_Hour . ":" . A_Min . ":" . A_Sec . " --> " . "RestoreWinPositions:--> Fichero de posiciones creado hace " . TiempoTranscurrido . " segundos (demasiado reciente): Salvapantallas activado en falso. Abortando..." . " `n", %TEMP%\WinPositions-Log.txt TrayTip, RestoreWinPositions, Fichero de posiciones crado hace %TiempoTranscurrido% segundos (demasiado reciente): Salvapantallas activado en falso. Abortando., ,2 sleep 10000 Exit 1 } NumParametros = %0% If ( NumParametros>0 ) { Parametro1 = %1% } NumeroDePantallasEsperado:=1 ; El sistema dispone de este número de pantallas en total. No se deben mover ventanas ni grabar sus posiciones si no están encendidas todas. ;Nótese que este será el valor por defecto de no ser especificado mediante parámetro en la línea de commands ni existir %A_WorkingDir%\screens.cfg. If ( NumParametros<1 ) ; Comprobamos el número de parámetros. { ; Si no hay parámetros, captubranchs el número de pantallas del fichero de configuración (por defecto en el directorio de ejecución del programa), si existe: IfExist, screens.cfg ; Si existe el fichero de configuración... { ; ... leemos de él el número de pantallas esperado. FileReadLine,NumeroDePantallasEsperado,%A_WorkingDir%\screens.cfg,1 FileAppend, % "# " . A_YYYY . "-" . A_MM . "-" . A_DD . " " . A_Hour . ":" . A_Min . ":" . A_Sec . " --> " . "RestoreWinPositions:--> No se introdujeron parámetros, se utilizará el extraído del fichero de configuración.`n", %TEMP%\WinPositions-Log.txt } else { FileAppend, % "# " . A_YYYY . "-" . A_MM . "-" . A_DD . " " . A_Hour . ":" . A_Min . ":" . A_Sec . " --> " . "RestoreWinPositions:--> No existe el fichero de configuración.`n", %TEMP%\WinPositions-Log.txt } } else { ; Si hay parámetros... If ( Parametro1 = 0 ) ; si el parámetro es un 0... { ; Ignorar número de monitores IgnoreNumPantallas = 1 FileAppend, % "# " . A_YYYY . "-" . A_MM . "-" . A_DD . " " . A_Hour . ":" . A_Min . ":" . A_Sec . " --> " . "RestoreWinPositions:-> Ignorando número de monitores: se ejecutará el programa sin esperarlos.`n", %TEMP%\WinPositions-Log.txt } else { ; si el parámetro es distinto de 0... ; ... el parámetro contiene el número de pantallas esperado: NumeroDePantallasEsperado = %1% } } If ( not IgnoreNumPantallas ) ; a lesss que se ignore el número de monitores... { ; ... añadimos una entrada al log con el número de pantallas necesarias. FileAppend, % "# " . A_YYYY . "-" . A_MM . "-" . A_DD . " " . A_Hour . ":" . A_Min . ":" . A_Sec . " --> " . "RestoreWinPositions:--> El sistema debe tener al lesss " . NumeroDePantallasEsperado " pantalla(s).`n", %TEMP%\WinPositions-Log.txt } ; Comprobamos que estén todos los monitores conectados: SysGet, m, MonitorCount If ( m < NumeroDePantallasEsperado ) ; Si no están todas las pantallas todavía activas... { ; ... espebranchs a que se enciendan. FileAppend, % "# " . A_YYYY . "-" . A_MM . "-" . A_DD . " " . A_Hour . ":" . A_Min . ":" . A_Sec . " --> " . "RestoreWinPositions:-> Esperando a que el sistema tenga al lesss " . NumeroDePantallasEsperado " pantalla(s).`n", %TEMP%\WinPositions-Log.txt InicioEspera := A_Now TrayTip, RestoreWinPositions, Esperando que estén encendidas %NumeroDePantallasEsperado% pantallas., ,1 } While ( not IgnoreNumPantallas and m < NumeroDePantallasEsperado ) { SysGet, m, MonitorCount Ahora := A_Now TiempoLimite := 180 ; Tiempo límite en segundos para esperar a que se enciendan todas las pantallas. If ( Ahora>InicioEspera+TiempoLimite ) { ; Superado tiempo de espera por pantallas. FileAppend, % "# " . A_YYYY . "-" . A_MM . "-" . A_DD . " " . A_Hour . ":" . A_Min . ":" . A_Sec . " --> " . "RestoreWinPositions:-> No están lists las " . NumeroDePantallasEsperado . " pantallas transcurrido el tiempo límite. Cancelando la ejecución del programa.`n", %TEMP%\WinPositions-Log.txt TrayTip, RestoreWinPositions, Transcurrido tiempo límite (%TiempoLimite% segundos) esperando que estén encendidas %NumeroDePantallasEsperado% pantallas. Abortando., ,2 sleep 10000 Exit ,3 ; No están todas las pantallas transcurridos 3 minutos. Cancelamos la ejecución del programa. } } ; Variable para comprobación de que todas las ventanas han sido corréctamente movidas: Checking := 0 IncorrectPositionWindows := 65536 ; Just to enter the While loop. ; Repetir hasta que ninguna ventana haya tenido que ser movida. While IncorrectPositionWindows>0 { If Checking>0 { FileAppend, % "# " . A_YYYY . "-" . A_MM . "-" . A_DD . " " . A_Hour . ":" . A_Min . ":" . A_Sec . " --> " . "RestoreWinPositions:--> Alguna(s) ventana(s) no estaban en su posición correcta. Revisando; pasada número " . Checking+1 . " ...." . " `n", %TEMP%\WinPositions-Log.txt } ; Inicializaciones de variables CorrectPositionWindows := 0 IncorrectPositionWindows := 0 ; Read from the arrays: Loop %ArrayCount% { ; Extraemos línea a línea los datos de cada ventana individual Ventana := Array%A_Index% ; Todos los datos de la ventana serán almacenados en esta variable. coma = , ; Extraemos el ID de la ventana. Position := InStr(Ventana, coma) StringMid, ID, Ventana, 0, Position-1 StringTrimLeft, Ventana, Ventana, Position ; Extraemos la coordenada X de la ventana. Position := InStr(Ventana, coma) StringMid, x, Ventana, 0, Position-1 StringTrimLeft, Ventana, Ventana, Position ; Extraemos la coordenada Y de la ventana. Position := InStr(Ventana, coma) StringMid, y, Ventana, 0, Position-1 StringTrimLeft, Ventana, Ventana, Position ; Extraemos el ancho W de la ventana. Position := InStr(Ventana, coma) StringMid, w, Ventana, 0, Position-1 StringTrimLeft, Ventana, Ventana, Position ; Extraemos el alto H de la ventana. Position := InStr(Ventana, coma) StringMid, h, Ventana, 0, Position-1 StringTrimLeft, Ventana, Ventana, Position ; Extraemos el título (lo que quede en el string) de la ventana. Titulo := Ventana WinGetPos,actualx,actualy,actualw,actualh,ahk_id %ID% WinGet, WinStatus, MinMax, ahk_id %ID% if WinStatus = -1 ; Si la ventana está minimizada... { ; Tratamos de obtener sus coordenadas restauradas sin tener que restaurarla. WinGetNormalPos(ID, actualx, actualy, actualw, actualh) } If (x=actualx and y=actualy and w=actualw and h=actualh) ; Si la ventana ya tiene sus coordenadas finales... { ; Incrementamos el contador de ventanas que ya estaban en su posición correcta (no ha sido necesario moverla). CorrectPositionWindows := ++CorrectPositionWindows } else { IfWinExist, ahk_id %ID% ; Actuaremos sobre la ventana tan solo si la ventana existe. { ; Incrementamos el contador de ventanas que no están en su posición correcta (es necesario moverla). IncorrectPositionWindows := ++IncorrectPositionWindows FileAppend, % "# " . A_YYYY . "-" . A_MM . "-" . A_DD . " " . A_Hour . ":" . A_Min . ":" . A_Sec . " --> " . "RestoreWinPositions:--> Moviendo ventana " . Titulo . " de coordenadas (X,Y,W,H): " . actualx . "," . actualy . "," . actualw . "," . actualh . " a coordenadas (X,Y,W,H): " . x . "," . y . "," . w . "," . h . "." . " `n", %TEMP%\WinPositions-Log.txt If WinStatus = -1 ; Si la ventana está minimizada... { ; No hay más remedio que restaurarla, moverla, y minimizarla de nuevo (No disponemos de métodos para cambiar las coordenadas de restauración para una ventana minimizada). WinRestore, ahk_id %ID% WinMove, ahk_id %ID%, , x, y, w, h WinMinimize, ahk_id %ID% } else { ; Si la ventana no está minimizada, nos basta con moverla. WinMove, ahk_id %ID%, , x, y, w, h } } else ; Si la ventana no existe... { ; prescindimos de actuar sobre esta ventana. FileAppend, % "# " . A_YYYY . "-" . A_MM . "-" . A_DD . " " . A_Hour . ":" . A_Min . ":" . A_Sec . " --> " . "RestoreWinPositions:--> Omitiendo ventana inexistente: " . Titulo . ". `n", %TEMP%\WinPositions-Log.txt } } } If Checking>=10 ; ¿Llevamos más de 10 pasadas intentando poner las ventanas en su sitio? { ; Cancelamos FileAppend, % "# " . A_YYYY . "-" . A_MM . "-" . A_DD . " " . A_Hour . ":" . A_Min . ":" . A_Sec . " --> " . "RestoreWinPositions:--> Demasiados intentos de ubicar ventanas. Abortando. :-( `n", %TEMP%\WinPositions-Log.txt TrayTip, RestoreWinPositions, Demasiados intentos de ubicar ventanas. Abortando. :-( , ,1 sleep 10000 Exit 2 } FileAppend, % "# " . A_YYYY . "-" . A_MM . "-" . A_DD . " " . A_Hour . ":" . A_Min . ":" . A_Sec . " --> " . "RestoreWinPositions:--> Ventanas que ya estaban en su posición correcta: " . CorrectPositionWindows . ". `n", %TEMP%\WinPositions-Log.txt FileAppend, % "# " . A_YYYY . "-" . A_MM . "-" . A_DD . " " . A_Hour . ":" . A_Min . ":" . A_Sec . " --> " . "RestoreWinPositions:--> Ventanas reubicadas: " . IncorrectPositionWindows . ". `n", %TEMP%\WinPositions-Log.txt Checking := ++Checking } FileAppend, % "# " . A_YYYY . "-" . A_MM . "-" . A_DD . " " . A_Hour . ":" . A_Min . ":" . A_Sec . " --> " . "RestoreWinPositions:--> Ventanas reubicadas corréctamente. Saliendo del programa. :-) `n", %TEMP%\WinPositions-Log.txt TrayTip, RestoreWinPositions, Ventanas reubicadas corréctamente. Saliendo del programa. :-), ,1 ; Beeps report: correctly finished. SoundBeep 1500,100 SoundBeep 1000,100 SoundBeep 3500,100 sleep 10000 ; Funciones utilizadas por el programa. WinGetNormalPos(hwnd, ByRef x, ByRef y, ByRef w="", ByRef h="") ; Devuelve la posición que tendría la ventana si no estuviera minimizada (posición restaurada). { VarSetCapacity(wp, 44), NumPut(44, wp) DllCall("GetWindowPlacement", "uint", hwnd, "uint", &wp) x := NumGet(wp, 28, "int") y := NumGet(wp, 32, "int") w := NumGet(wp, 36, "int") - x h := NumGet(wp, 40, "int") - y }