Multimonitor window management. (Move window between multimonitor)

Post your working scripts, libraries and tools
sobuj53
Posts: 35
Joined: 19 Mar 2015, 16:08

Multimonitor window management. (Move window between multimonitor)

13 Jul 2018, 23:39

Hi,

I use below script everyday to move window between multimonitor. Thought I'd share it here, if anyone needs it.
Credit. All credit goes to this awesome community without their help it was not possible.

Use: Ctrl+Shift+M

Code: Select all

#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. ; #Warn ; Enable warnings to assist with detecting common errors. SendMode Input ; Recommended for new scripts due to its superior speed and reliability. SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. ;Move selected window to swap monitor ^+M:: DetectHiddenWindows, Off WindArray := {} SysGet, OutputVar, MonitorCount ; This will be the GUI name WinName = Move Window Between Monitor WinGet, OpenWindow, List If OutputVar = 1 { MsgBox, 4112, No multimonitor connected, Minimum 2 display unit is required to execute this script. Please connect to another display., 4 Exit } If !WinExist(WinName) { Gui,+AlwaysOnTop Gui, Font, s11, Arial Gui, Add, DropDownList, gShowToolTip x7 y9 w260 vWindowMove,Pick a Window|| Gui, Add, Button, x282 y8 w50 h28 gPosChoice, Swap } Else { Gui, Destroy Gui,+AlwaysOnTop Gui, Font, s11, Arial Gui, Add, DropDownList, gShowToolTip x7 y9 w260 vWindowMove,Pick a Window|| Gui, Add, Button, x282 y8 w50 h28 gPosChoice, Swap } Loop, %OpenWindow% { id := OpenWindow%A_Index% WinGetTitle Title, ahk_id %id% WinGet, style, style, ahk_id %id% WinGet, ClsID, ID, ahk_id %id% If !(style & 0xC00000) or (title = "") continue WinGetClass class, ahk_id %id% If (class = "ApplicationFrameWindow") { WinGetText, text, ahk_id %id% If (text = "") { WinGet, style, style, ahk_id %id% If !(style = "0xB4CF0000") ; the window isn't minimized continue } } GuiControl,,WindowMove, %Title% WindArray.Insert(Title, ClsID) } Gui, Show, h45 w345, %WinName% hwnd:=WinExist(WinName) Return ShowToolTip: Gui,Submit,NoHide ;remove any previous tooltip GoSub RemoveToolTip if (InStr(WindowMove, "Pick a Window", true) = 0 and WindowMove!="") { ControlGetPos,x,y,w,h,ComboBox1,ahk_id %hwnd% ToolTip %WindowMove%,x,y+h,10 SetTimer,RemoveToolTip,-3000 } Return PosChoice: Gui, Submit, NoHide if (InStr(WindowMove, "Pick a Window", true) = 0 and WindowMove!="") { ;return Associative array value IDValue:= WindArray[WindowMove] if WinExist("ahk_id " IDValue) { ;WinActivate, Ahk_ID %IDValue% MoveIt(IDValue) } else { GoSub ^+M ; Recall it again to refresh status } GoSub RemoveToolTip } Return RemoveToolTip: ToolTip,,,,10 Return GuiClose: Gui, Destroy Return /* Function to move a given window from 1 monitor to another. use WinGet, activeWindowHwnd, ID, A or ahk_class Notepad++ MoveIt(activeWindowHwnd) */ MoveIt(activeWindowHwnd) { ; Count number of active monitor. SysGet, OutputVar, MonitorCount if OutputVar > 1 { ;WinGet, activeWindowHwnd, ID, A WinActivate, Ahk_ID %activeWindowHwnd% activeMonitorHwnd := MDMF_FromHWND(activeWindowHwnd) monitors := MDMF_Enum() monitorHwndList := [] For currentMonitorHwnd, info In monitors monitorHwndList[A_Index] := currentMonitorHwnd nextMonitorHwnd := "" For currentMonitorHwnd, info In monitors If (currentMonitorHwnd = activeMonitorHwnd) nextMonitorHwnd := (A_Index=monitorHwndList.MaxIndex() ? monitorHwndList[1] : monitorHwndList[A_Index+1]) activeMonitor := MDMF_GetInfo(activeMonitorHwnd) nextMonitor := MDMF_GetInfo(nextMonitorHwnd) WinGetPos, x, y, w, h, ahk_id %activeWindowHwnd% activeWindow := {Left:x, Top:y, Right:x+w, Bottom:y+h} relativePercPos := {} relativePercPos.Left := (activeWindow.Left-activeMonitor.Left)/(activeMonitor.Right-activeMonitor.Left) relativePercPos.Top := (activeWindow.Top-activeMonitor.Top)/(activeMonitor.Bottom-activeMonitor.Top) relativePercPos.Right := (activeWindow.Right-activeMonitor.Left)/(activeMonitor.Right-activeMonitor.Left) relativePercPos.Bottom := (activeWindow.Bottom-activeMonitor.Top)/(activeMonitor.Bottom-activeMonitor.Top) ;MsgBox % activeWindow.Top "`n" activeWindow.Left " - " activeWindow.Right "`n" activeWindow.Bottom ;MsgBox % relativePercPos.Top*100 "`n" relativePercPos.Left*100 " - " relativePercPos.Right*100 "`n" relativePercPos.Bottom*100 activeWindowNewPos := {} activeWindowNewPos.Left := nextMonitor.Left+(nextMonitor.Right-nextMonitor.Left)*relativePercPos.Left activeWindowNewPos.Top := nextMonitor.Top+(nextMonitor.Bottom-nextMonitor.Top)*relativePercPos.Top WinMove, Ahk_ID %activeWindowHwnd%,, activeWindowNewPos.Left, activeWindowNewPos.Top } winmaximize, Ahk_ID %activeWindowHwnd% Return } ;Credits to "just me" for the following code: ; ====================================================================================================================== ; Multiple Display Monitors Functions -> msdn.microsoft.com/en-us/library/dd145072(v=vs.85).aspx ======================= ; ====================================================================================================================== ; Enumerates display monitors and returns an object containing the properties of all monitors or the specified monitor. ; ====================================================================================================================== MDMF_Enum(HMON := "") { Static EnumProc := RegisterCallback("MDMF_EnumProc") Static Monitors := {} If (HMON = "") ; new enumeration Monitors := {} If (Monitors.MaxIndex() = "") ; enumerate If !DllCall("User32.dll\EnumDisplayMonitors", "Ptr", 0, "Ptr", 0, "Ptr", EnumProc, "Ptr", &Monitors, "UInt") Return False Return (HMON = "") ? Monitors : Monitors.HasKey(HMON) ? Monitors[HMON] : False } ; ====================================================================================================================== ; Callback function that is called by the MDMF_Enum function. ; ====================================================================================================================== MDMF_EnumProc(HMON, HDC, PRECT, ObjectAddr) { Monitors := Object(ObjectAddr) Monitors[HMON] := MDMF_GetInfo(HMON) Return True } ; ====================================================================================================================== ; Retrieves the display monitor that has the largest area of intersection with a specified window. ; ====================================================================================================================== MDMF_FromHWND(HWND) { Return DllCall("User32.dll\MonitorFromWindow", "Ptr", HWND, "UInt", 0, "UPtr") } ; ====================================================================================================================== ; Retrieves the display monitor that contains a specified point. ; If either X or Y is empty, the function will use the current cursor position for this value. ; ====================================================================================================================== MDMF_FromPoint(X := "", Y := "") { VarSetCapacity(PT, 8, 0) If (X = "") || (Y = "") { DllCall("User32.dll\GetCursorPos", "Ptr", &PT) If (X = "") X := NumGet(PT, 0, "Int") If (Y = "") Y := NumGet(PT, 4, "Int") } Return DllCall("User32.dll\MonitorFromPoint", "Int64", (X & 0xFFFFFFFF) | (Y << 32), "UInt", 0, "UPtr") } ; ====================================================================================================================== ; Retrieves the display monitor that has the largest area of intersection with a specified rectangle. ; Parameters are consistent with the common AHK definition of a rectangle, which is X, Y, W, H instead of ; Left, Top, Right, Bottom. ; ====================================================================================================================== MDMF_FromRect(X, Y, W, H) { VarSetCapacity(RC, 16, 0) NumPut(X, RC, 0, "Int"), NumPut(Y, RC, 4, Int), NumPut(X + W, RC, 8, "Int"), NumPut(Y + H, RC, 12, "Int") Return DllCall("User32.dll\MonitorFromRect", "Ptr", &RC, "UInt", 0, "UPtr") } ; ====================================================================================================================== ; Retrieves information about a display monitor. ; ====================================================================================================================== MDMF_GetInfo(HMON) { NumPut(VarSetCapacity(MIEX, 40 + (32 << !!A_IsUnicode)), MIEX, 0, "UInt") If DllCall("User32.dll\GetMonitorInfo", "Ptr", HMON, "Ptr", &MIEX) { MonName := StrGet(&MIEX + 40, 32) ; CCHDEVICENAME = 32 MonNum := RegExReplace(MonName, ".*(\d+)$", "$1") Return {Name: (Name := StrGet(&MIEX + 40, 32)) , Num: RegExReplace(Name, ".*(\d+)$", "$1") , Left: NumGet(MIEX, 4, "Int") ; display rectangle , Top: NumGet(MIEX, 8, "Int") ; " , Right: NumGet(MIEX, 12, "Int") ; " , Bottom: NumGet(MIEX, 16, "Int") ; " , WALeft: NumGet(MIEX, 20, "Int") ; work area , WATop: NumGet(MIEX, 24, "Int") ; " , WARight: NumGet(MIEX, 28, "Int") ; " , WABottom: NumGet(MIEX, 32, "Int") ; " , Primary: NumGet(MIEX, 36, "UInt")} ; contains a non-zero value for the primary monitor. } Return False }
User avatar
elModo7
Posts: 36
Joined: 01 Sep 2017, 02:38

Re: Multimonitor window management. (Move window between multimonitor)

26 Jul 2018, 06:35

Hey man, greatly appreciated!
:beer:

Return to “Scripts and Functions”

Who is online

Users browsing this forum: No registered users and 59 guests