Reputation: 1
I am trying to swap windows on my screen. The MsgBox
es work but WinMove
doesn't:
{
...
; Move from Monitor 1 to Monitor 2
if (WinX >= Monitor1X && WinX < Monitor1EndX) {
SwapToScreen(thisID, Monitor2X, WinX, WinY, Monitor1X)
MsgBox , 1 to 2, %Title%
}
; Move from Monitor 2 to Monitor 1
else if (WinX >= Monitor2X && WinX < Monitor2EndX) {
SwapToScreen(thisID, Monitor1X, WinX, WinY, Monitor2X)
MsgBox, 2 to 1, %Title%
}
; Handle fullscreen cases (X = -9)
else if (WinX < 0 || WinY < 0) {
WinGet, IsMaximized, MinMax, ahk_id %thisID%
if (IsMaximized) {
SwapToScreen(thisID, Monitor2X, Monitor1X, WinY, Monitor1X)
WinRestore, ahk_id %thisID%
}
if (IsMaximized) {
WinMaximize, ahk_id %thisID%
}
}
else {
MsgBox, Active window is not within defined screen boundaries.
}
}
}
SwapToScreen(ActiveWinID, TargetMonitorX, CurrentX, CurrentY,
SourceMonitorX) {
NewX := TargetMonitorX + (CurrentX - SourceMonitorX)
WinGetPos, OldX, OldY, OldWidth, OldHeight, ahk_id %ActiveWinID%
; Adjust size based on scaling factor
if (TargetMonitorX = 0) {
ScaleFactor := 1 ; Moving to Monitor 1
} else {
ScaleFactor := 1 ; Moving to Monitor 2
}
NewWidth := OldWidth * ScaleFactor
NewHeight := OldHeight * ScaleFactor
; Move the window and report success
MsgBox, Moving Window ID: %ActiveWinID% to X: %NewX%, Y: %CurrentY%, Width: %NewWidth%, Height: %NewHeight%
WinMove, ahk_id %ActiveWinID% , %NewX% , %CurrentY% , %NewWidth%, %NewHeight%
MsgBox, Window moved successfully to X: %OldX%,%NewX%, Y: %OldY%,%CurrentY%, Width: %OldWidth%,%NewWidth%, Height: %OldHeight%,%NewHeight%.
}
I also need to resize it because of difference between resolutions.
Upvotes: 0
Views: 82
Reputation: 11
#7 will be useful:
;;∙============================================================∙
/* 🔥∙HOTKEYS∙🔥
∙--------------------------------------------------------------------∙
Ctrl+Alt+Numpad1 ;;∙------∙Monitor of active window.
Ctrl+Alt+1
∙--------------------------------------------------------------------∙
Ctrl+Alt+Numpad2 ;;∙------∙Detects monitor under current mouse cursor.
Ctrl+Alt+2
∙--------------------------------------------------------------------∙
Ctrl+Alt+Numpad3 ;;∙------∙Detects monitor with largest intersection with a custom rectangle.
Ctrl+Alt+3
∙--------------------------------------------------------------------∙
Ctrl+Alt+Numpad4 ;;∙------∙ENHANCED: Monitor of active window with Resolution & DPI.
Ctrl+Alt+4
∙--------------------------------------------------------------------∙
Ctrl+Alt+Numpad5 ;;∙------∙ENHANCED: Detects monitor under current mouse cursor with Resolution & DPI.
Ctrl+Alt+5
∙--------------------------------------------------------------------∙
Ctrl+Alt+Numpad6 ;;∙------∙ENHANCED: Detects monitor with largest intersection with a custom rectangle.
Ctrl+Alt+6
∙--------------------------------------------------------------------∙
Ctrl+Alt+Numpad7 ;;∙------∙Move active window to the opposite monitor.
Ctrl+Alt+7
∙--------------------------------------------------------------------∙
Ctrl+Alt+Numpad8 ;;∙------∙Shows monitor information with Primary monitor listed first.
Ctrl+Alt+8
∙--------------------------------------------------------------------∙
*/
;;∙============================================================∙
#MaxThreadsPerHotkey 3
#NoEnv
#Persistent
#SingleInstance, Force
Menu, Tray, Icon, imageres.dll, 291
SetBatchLines -1
SetTitleMatchMode 2
SetWinDelay 0
;;∙-----------------------∙
Monitors := MDMF_Enum() ;;∙------∙Retrieves All relevant monitor information. **
;;∙------∙🔥∙--------------------------------------------------------------------------------∙
^!Numpad1:: ;;∙------∙Monitor of active window.
^!1::
ActiveWindow := WinExist("A") ;;∙------∙Determines hwnd of active window.
ActiveMonitor := Monitors[MDMF_FromHWND(ActiveWindow)] ;;∙------∙Retrieves display monitor that has largest area of intersection with this window.
MsgBox,,,% ActiveMonitor.Num "`n" ActiveMonitor.Name, 5 ;;∙------∙Shows active monitor's Number & Name.
Return
;;∙------∙🔥∙--------------------------------------------------------------------------------∙
^!Numpad2:: ;;∙------∙Detects monitor under current mouse cursor.
^!2::
ActiveMonitor := Monitors[MDMF_FromPoint()] ;;∙------∙Retrieves the monitor containing the cursor.
MsgBox,,,% "Monitor with Mouse Cursor: `n" ActiveMonitor.Num "`n" ActiveMonitor.Name, 5 ;;∙------∙Shows monitor number & name.
Return
;;∙------∙🔥∙--------------------------------------------------------------------------------∙
^!Numpad3:: ;;∙------∙Detects monitor with largest intersection with a custom rectangle.
^!3::
InputBox, X, Enter X Coordinate, Please enter the X coordinate., , 200, 120
InputBox, Y, Enter Y Coordinate, Please enter the Y coordinate., , 200, 120
InputBox, W, Enter Width, Please enter the width of the rectangle., , 200, 120
InputBox, H, Enter Height, Please enter the height of the rectangle., , 200, 120
ActiveMonitor := Monitors[MDMF_FromRect(X, Y, W, H)] ;;∙------∙Retrieves monitor that intersects most with custom rectangle.
MsgBox,,,% "Monitor for Custom Rectangle: `n" ActiveMonitor.Num "`n" ActiveMonitor.Name, 5 ;;∙------∙Shows monitor number & name.
Return
;;∙------∙🔥∙--------------------------------------------------------------------------------∙
^!Numpad4:: ;;∙------∙ENHANCED: Monitor of active window with Resolution & DPI.
^!4::
ActiveWindow := WinExist("A") ;;∙------∙Determines hwnd of active window.
If !ActiveWindow {
MsgBox,,, Error, Active window not found., 7
Return
}
ActiveMonitor := Monitors[MDMF_FromHWND(ActiveWindow)] ;;∙------∙Retrieves display monitor.
If !ActiveMonitor {
MsgBox,,, Error, No monitor found for the active window., 7
Return
}
DisplayMonitorInfo(ActiveMonitor, "Monitor of Active Window")
Return
;;∙------∙🔥∙--------------------------------------------------------------------------------∙
^!Numpad5:: ;;∙------∙ENHANCED: Detects monitor under current mouse cursor with Resolution & DPI.
^!5::
ActiveMonitor := Monitors[MDMF_FromPoint()] ;;∙------∙Retrieves the monitor containing the cursor.
If !ActiveMonitor {
MsgBox,,, Error, No monitor found under the mouse cursor., 7
Return
}
DisplayMonitorInfo(ActiveMonitor, "Monitor with Mouse Cursor")
Return
;;∙------∙🔥∙--------------------------------------------------------------------------------∙
^!Numpad6:: ;;∙------∙ENHANCED: Detects monitor with largest intersection with a custom rectangle.
^!6::
InputBox, X, Enter X Coordinate, Please enter the X coordinate., , 200, 120
InputBox, Y, Enter Y Coordinate, Please enter the Y coordinate., , 200, 120
InputBox, W, Enter Width, Please enter the width of the rectangle., , 200, 120
InputBox, H, Enter Height, Please enter the height of the rectangle., , 200, 120
ActiveMonitor := Monitors[MDMF_FromRect(X, Y, W, H)] ;;∙------∙Retrieves monitor that intersects most with the custom rectangle.
If !ActiveMonitor {
MsgBox,,, Error, No monitor found for the custom rectangle., 7
Return
}
DisplayMonitorInfo(ActiveMonitor, "Monitor for Custom Rectangle")
Return
;;∙------∙🔥∙--------------------------------------------------------------------------------∙
^!Numpad7:: ;;∙------∙Move active window to the opposite monitor
^!7::
Soundbeep, 1200, 200
ActiveWindow := WinExist("A") ;;∙------∙Determine the hwnd of the active window
If !ActiveWindow {
MsgBox,,, Error, Active window not found., 7
Return
}
ActiveMonitor := Monitors[MDMF_FromHWND(ActiveWindow)] ;;∙------∙Find the active window's monitor
If !ActiveMonitor {
MsgBox,,, Error, No monitor found for the active window., 7
return
}
;;∙------∙Get the list of monitors, sorted to ensure the primary is first
SortedMonitors := []
For HMON, M In Monitors {
If M.Primary
SortedMonitors.InsertAt(1, {HMON: HMON, M: M}) ;;∙------∙Insert primary monitor at the beginning
Else
SortedMonitors.Push({HMON: HMON, M: M})
}
;;∙------∙Find the current monitor's index
CurrentMonitorIndex := 0
For Index, Monitor In SortedMonitors {
If (Monitor["HMON"] = ActiveMonitor["HMON"]) {
CurrentMonitorIndex := Index
Break
}
}
;;∙------∙Calculate the opposite monitor based on position.
OppositeMonitor := ""
MaxDistance := 0
For Index, Monitor In SortedMonitors {
If (Index != CurrentMonitorIndex) {
;;∙------∙Calculate distance between current monitor and each other monitor
Distance := Abs(ActiveMonitor["Left"] - Monitor["M"]["Left"]) + Abs(ActiveMonitor["Top"] - Monitor["M"]["Top"])
If (Distance > MaxDistance) {
MaxDistance := Distance
OppositeMonitor := Monitor
}
}
}
If OppositeMonitor {
;;∙------∙Get the current window's size and position before moving.
WinGetPos, X, Y, Width, Height, ahk_id %ActiveWindow%
;;∙------∙Get the current monitor's position. (relative to the screen)
CurrentMonitorLeft := ActiveMonitor["Left"]
CurrentMonitorTop := ActiveMonitor["Top"]
;;∙------∙Get the opposite monitor's position. (relative to the screen)
OppositeMonitorLeft := OppositeMonitor["M"]["Left"]
OppositeMonitorTop := OppositeMonitor["M"]["Top"]
;;∙------∙Calculate the new position on the opposite monitor.
NewX := X - CurrentMonitorLeft + OppositeMonitorLeft
NewY := Y - CurrentMonitorTop + OppositeMonitorTop
;;∙------∙ *DEBUGGING* Show current position, size, and new calculated position. *DEBUGGING*
;;∙------∙ MsgBox,,, % "Current Window Position: " X ", " Y "`nWidth: " Width "`nHeight: " Height, 5
;;∙------∙ MsgBox,,, % "Opposite Monitor: " OppositeMonitor["M"]["Name"] "`nNew Position: " NewX ", " NewY, 5
;;∙------∙Move the active window to the opposite monitor's calculated position, preserving the size.
WinMove, ahk_id %ActiveWindow%, , NewX, NewY, Width, Height
} Else {
MsgBox,,, Error, No opposite monitor found., 7
}
Return
;;∙------∙🔥∙--------------------------------------------------------------------------------∙
^!Numpad8:: ;;∙------∙Shows monitor information with Primary monitor listed first.
^!8::
Gui, Margin, 20, 20
Gui, +OwnDialogs
Gui, Add, ListView, w660 r10 Grid, HMON|Num|Name|Primary|Left|Top|Right|Bottom|WALeft|WATop|WARight|WABottom
SortedMonitors := [] ;;∙------∙Sort monitors to bring primary one to the top.
For HMON, M In Monitors {
If M.Primary
SortedMonitors.InsertAt(0, {HMON: HMON, M: M})
Else
SortedMonitors.Push({HMON: HMON, M: M})
}
For Index, Monitor In SortedMonitors {
LV_Add("", Monitor.HMON, Monitor.M.Num, Monitor.M.Name, Monitor.M.Primary, Monitor.M.Left, Monitor.M.Top, Monitor.M.Right, Monitor.M.Bottom, Monitor.M.WALeft, Monitor.M.WATop, Monitor.M.WARight, Monitor.M.WABottom)
}
Loop, % LV_GetCount("Column")
LV_ModifyCol(A_Index, "AutoHdr")
Gui, Show, ,Monitors
Return
;;∙============================================================∙
;;∙============================================================∙
;;∙-----------------∙FUNCTIONS∙--------------------------------------------------------∙
;;∙============================================================∙
;;∙-----------------------∙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 display monitor that has largest area of intersection with a specified rectangle.
;;∙------∙Parameters consistent with common AHK definition of a rectangle, which is X, Y, W, H. (not... 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")
;;∙------∙Retrieve Monitor's DPI settings (Windows 8.1+)
If (A_OSVersion >= "6.3") {
VarSetCapacity(DPI, 8, 0)
If (DllCall("Shcore.dll\GetDpiForMonitor", "Ptr", HMON, "UInt", 0, "UInt*", dpiX, "UInt*", dpiY) = 0) {
dpiX := dpiX
dpiY := dpiY
} Else {
dpiX := dpiY := 96 ;;∙------∙Default DPI if function fails.
}
} Else {
dpiX := dpiY := 96 ;;∙------∙Default DPI for older Windows.
}
;;∙------∙Get the resolution from monitor bounds
resWidth := NumGet(MIEX, 12, "Int") - NumGet(MIEX, 4, "Int")
resHeight := NumGet(MIEX, 16, "Int") - NumGet(MIEX, 8, "Int")
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") ;;∙------∙"
, ResWidth: resWidth
, ResHeight: resHeight
, DPI_X: dpiX
, DPI_Y: dpiY
, 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
}
;;∙-----------------------∙Displays monitor information in a GUI with an Edit control.
DisplayMonitorInfo(MonitorInfo, Title) {
global EditControl ;; Declare EditControl as global to avoid the variable scope error.
Gui, New, +AlwaysOnTop +HwndGuiHwnd
Gui, Add, Edit, w600 r12 ReadOnly vEditControl, % "Monitor Number: " MonitorInfo.Num "`n"
. "Monitor Name: " MonitorInfo.Name "`n"
. "Resolution: " MonitorInfo.ResWidth " x" MonitorInfo.ResHeight "`n"
. "DPI: " MonitorInfo.DPI_X " x " MonitorInfo.DPI_Y "`n"
. "Coordinates: (" MonitorInfo.Left ", " MonitorInfo.Top ") - (" MonitorInfo.Right ", " MonitorInfo.Bottom ")`n"
. "Work Area: (" MonitorInfo.WALeft ", " MonitorInfo.WATop ") - (" MonitorInfo.WARight ", " MonitorInfo.WABottom ")`n"
. "Primary: " (MonitorInfo.Primary ? "Yes" : "No")
Gui, Show, , % Title
GuiControlGet, CurrentContent, , EditControl
GuiControl,, EditControl, % CurrentContent . "`n`n`t*END*"
}
Return
;;∙============================================================∙
Upvotes: 1
Reputation: 1
WinMove, WinTitle, WinText, X, Y [, Width, Height, ExcludeTitle, ExcludeText]
If I don't want to specify WinText
it still needs the extra comma.
Upvotes: 0