My solution to minimizing/maximizing all "monitors" at once

Discussions related to using VirtualBox on Windows hosts.
Post Reply
dmittleider
Posts: 14
Joined: 18. Dec 2013, 21:34

My solution to minimizing/maximizing all "monitors" at once

Post by dmittleider »

It has always bothered me that if I am running a multi-monitor VM that VirtualBox can't just minimize the other monitors if I minimize one. I used AutoIt (a small little scripting automation language available at https://www.autoitscript.com/site/autoit/) to put this together. I'm attaching the code below if you want to tweak it or compile it yourself and I attempted to attach a zip with a compiled .exe file.

Just run this prior to starting up VirtualBox (it will leave an icon in the system tray if you want to kill it)

Code: Select all


#include <MsgBoxConstants.au3>
#include <Array.au3>
AutoItSetOption ( "WinTitleMatchMode", 2 )	; Default to match on partial name (anything that matches the pattern Oracle VM VirtualBox :)

; Declare 2D arrays to hold window state information
; The IS array holds the most current window state And
;  then compares it against the WAS array
Local $isState[0][2], $wasState[0][2]

; Get initial window data
GetVMWindows($isState, $wasState)

Dim $partial_title ; holds split up title that matches similar windows

; Loop indefinately looking for changes every quarter second, on every 10th loop, reinitialize the window data
$count = 0
While (1)

   For $i = 0 To _ArrayMaxIndex ($isState)

	  ; switch over to using the exact title of the window otherwise AutoIt just uses the most recent match
	  AutoItSetOption ( "WinTitleMatchMode", 3 )
	  ; get the minimize (16) and maximize (32) states of the window
	  $isState[$i][1] = BitAnd(WinGetState($isState[$i][0] ),16)+BitAnd(WinGetState($isState[$i][0] ),32)

	  ; if the window state has changed since the last check update the state of the other matching windows
	  ConsoleWrite ($isState[$i][1] & " = " & $wasState[$i][1] & @CRLF)
	  If ($isState[$i][1] <> $wasState[$i][1]) Then
		 $partial_title = StringSplit ( $isState[$i][0], " : ", 1) ; the title without the : 1, : 2, etc
		 SetWindowState($isState[$i][1], $isState, $wasState, $isState[$i][0], $partial_title[1])
	  EndIf
   Next

   ; If this is the 10th time through reset count and update window data in case new windows were added or changed titles
   If $count = 10 Then
	  $count = 1
		 GetVMWindows($isState, $wasState)
   Else
	  $count = $count + 1
   EndIF
   ; wait a quarter second
   Sleep(250)
WEnd


; Gets the title and state for windows that are multiple monitor VMs.  This is done for the "IS" and for the "WAS" arrays
Func GetVMWindows(ByRef $iState, ByRef $wState)

    ; Retrieve a list of window handles that match anything with "Oracle VM Virtual Box :"  (the semicolon is a giveaway that it's a multiple monitor VM
    AutoItSetOption ( "WinTitleMatchMode", 2 )

   ; Clean out anything in the array already from 0 to the size of the array
   _ArrayDelete($iState, "0-"&_ArrayMaxIndex ($iState)+1)
   _ArrayDelete($wState, "0-"&_ArrayMaxIndex ($wState)+1)

   ; Get any windows that are Virtual Box multiple monitor windows
	Local $vmWindows = WinList("Oracle VM VirtualBox :")

    ; Loop through the array displaying only visable windows with a title.
    For $i = 1 To $vmWindows[0][0]
        If $vmWindows[$i][0] <> "" And BitAND(WinGetState($vmWindows[$i][1]), 2) Then
			; get the minimize (16) and maximize (32) states of the window
			Local $simpleState = BitAnd(WinGetState($vmWindows[$i][0] ),16)+BitAnd(WinGetState($vmWindows[$i][0] ),32)
            ; add title into secondary index 0 and state into secondary index 1 of the array
			_ArrayAdd($iState, $vmWindows[$i][0]&"|"&    $simpleState    , 0)
			_ArrayAdd($wState, $vmWindows[$i][0]&"|"&    $simpleState    , 0)
        EndIf
	 Next

 EndFunc

; Determines if the windows all need to be minimized, maximized or restored (a size that isn't maximized but still visible)
Func SetWindowState($stateToSet, ByRef $IsStateArray, ByRef $WasStateArray, $windowTitle, $matchTitle)
   Local $partial_title
   ; Look through all windows in the array
   For $i = 0 to _ArrayMaxIndex ($IsStateArray)
	  $partial_title = StringSplit ( $IsStateArray[$i][0], " : ", 1)

	  ; if it's a window belonging to the set of windows for a particular VM
	  If $partial_title[1]=$matchTitle Then
		 ; Set the matching to be exact, otherwise it just grabs whatever window was last open
		 AutoItSetOption ( "WinTitleMatchMode", 3 )
		 ; If a window was maximized, maximize all windows
		 If BitAND ( $stateToSet, 32 ) Then
			WinSetState($IsStateArray[$i][0],"", @SW_MAXIMIZE)
			;WinActivate($IsStateArray[$i][0],"")
		 ; If a window was minimized, minimize all similar windows
		 ElseIf BitAND ( $stateToSet, 16 ) Then
			WinSetState($IsStateArray[$i][0],"", @SW_MINIMIZE)
		 ; If a window was restored (not maximized or minimized) restore the other windows (not the one you restored or it will go back to maximized)
		 ElseIf $stateToSet = 0 and $IsStateArray[$i][0] <> $windowTitle Then
			WinSetState($IsStateArray[$i][0],"", @SW_RESTORE)
		 EndIf
		 ; Update all the window states to the current state
		 $IsStateArray[$i][1] = $stateToSet
		 $WasStateArray[$i][1] = $stateToSet
	  EndIf
   Next

EndFunc



Attachments
VirtualBox MultiMonitor Workaround.zip
Executable file for workaround
(435.8 KiB) Downloaded 25 times
Post Reply