5

Small AHK function to determine which monitor the focus window is on.

I was writing a script that needed context on which monitor the focus window was on. I found quite a few solutions, but none were too easy to follow, or were a little more complex than needed.

user4157124
  • 2,809
  • 13
  • 27
  • 42
Anu
  • 318
  • 1
  • 11

2 Answers2

1

Below will get you just that. The monitor Index in AHK so you can reference it.

GetFocusWindowMonitorIndex(){
    ;Get number of monitor
    SysGet, monCount, MonitorCount
    
    ;Iterate through each monitor
    Loop %monCount%{
        ;Get Monitor working area
        SysGet, workArea, Monitor, % A_Index
        
        ;Get the position of the focus window
        WinGetPos, X, Y, , , A
        
        ;Check if the focus window in on the current monitor index
        if (X >= workAreaLeft && X < workAreaRight && Y >= workAreaTop && Y < workAreaBottom ){
            ;Return the monitor index since its within that monitors borders.
            return % A_Index
        }
    }
}

Note Below is a modified version where the window is passed as an argument, and not the default; focus window

GetFocusWindowMonitorIndex(thisWindow){
    ;Get number of monitor
    SysGet, monCount, MonitorCount
    
    ;Iterate through each monitor
    Loop %monCount%{
        ;Get Monitor working area
        SysGet, workArea, Monitor, % A_Index
        
        ;Get the position of the focus window
        WinGetPos, X, Y, , , %thisWindow%
        
        ;Check if the focus window in on the current monitor index
        if (X >= workAreaLeft && X < workAreaRight && Y >= workAreaTop && Y < workAreaBottom ){
            ;Return the monitor index since it's within that monitors borders.
            return % A_Index
        }
    }
}

Even if this helps one more person, I'll call it a win.

EDIT:

Should you need the working area (exclude the tarkbar from the working area) use this functions.

GetFocusWindowMonitorIndex(){
    ;Get number of monitor
    SysGet, monCount, MonitorCount
    
    ;Iterate through each monitor
    Loop %monCount%{
        ;Get Monitor working area
        SysGet, workArea, MonitorWorkArea , % A_Index
        
        ;Get the position of the focus window
        WinGetPos, X, Y, , , A
        
        ;Check if the focus window in on the current monitor index
        if (X >= workAreaLeft && X < workAreaRight && Y >= workAreaTop && Y < workAreaBottom ){
            ;Return the monitor index since its within that monitors borders.
            return % A_Index
        }
    }
}
Community
  • 1
  • 1
Anu
  • 318
  • 1
  • 11
1

I would like to point out that the previous answer will not work if:

  1. You have a maximized window (the window will go beyond the monitor boundaries slightly, in my case by 10 pixels in every direction)
  2. The window overlaps multiple windows. In that case it would be most appropriate to see which monitor contains the largest portion of the active window.
GetFocusWindowMonitorIndex(){
    ;Get number of monitor
    SysGet, monCount, MonitorCount

    ;Get the position of the focus window
    WinGetPos, WindowX, WindowY, WindowWidth, WindowHeight, A

    ;Make an array to hold the sub-areas of the window contained within each monitor
    monitorSubAreas := []

    ;Iterate through each monitor
    Loop %monCount%{
        ;Get Monitor working area
        SysGet, Monitor, MonitorWorkArea , % A_Index
    
        ;Calculate sub-area of the window contained within each monitor
        xStart := max(WindowX,  MonitorLeft)
        xEnd :=  min(WindowX + WindowWidth,  MonitorRight)
        yStart := max(WindowY, MonitorTop)
        yEnd :=  min(WindowY + WindowHeight,  MonitorBottom)
        area := (xEnd - xStart) * (yEnd - yStart)
        
        ;Remember these areas, and which monitor they were associated with
        monitorSubAreas.push({"area": area, "index": A_Index})
    }
    ;If there is only one monitor in the array, then you already have your answer
    if(monitorSubAreas.length() == 1) {
        return monitorSubAreas[1].index
    }
    
    
    ;Otherwise, loop to figure out which monitor's recorded sub-area was largest
    winningMonitor := 0
    winningArea := 0
    for index, monitor in monitorSubAreas {
        winningMonitor := monitor.area > winningArea ? monitor.index : winningMonitor
        winningArea := monitor.area > winningArea ?  monitor.area : winningArea
    }
    return winningMonitor
}
GalacticWafer
  • 11
  • 1
  • 2