Find out which display is a given Window opened on

Hello:

Does the Xojo Framework provide the capability of knowing which display (in a multi-monitor setup) a given Window is currently displayed on for Mac, Windows, and Linux or should I look into using OS-specific APIs for that via Declare statement?

The framework doesn’t provide a “which screen” function, but it’s relatively simple math that has been done so many times on here that if you ask an AI I’m sure it will regurgitate stolen code you can use.

1 Like

It’s relatively simple. There are two schools of thought to deciding which screen a Windows is visible on, since there can be multiple answers. The simpler is deciding based on the top left corner, and the other is majority overlap. Majority overlap is the technique I use.

The idea is you get your window bounds, get the bounds for each screen, and see which screen has the largest amount of intersection.

Function GetCurrentDisplay (Extends Win As DesktopWindow) As DesktopDisplay
  Var WinBounds As Xojo.Rect = Win.Bounds
  Var LargestScreen As DesktopDisplay
  Var LargestArea As Double
  For ScreenIndex As Integer = 0 To DesktopDisplay.LastDisplayIndex
    Var Screen As DesktopDisplay = DesktopDisplay.DisplayAt(ScreenIndex)
    Var ScreenBounds As New Xojo.Rect(Screen.Left, ScreenTop, Screen.Width, Screen.Height)
    Var Overlap As Xojo.Rect = ScreenBounds.Intersection(WinBounds)
    Var Area As Double = Overlap.Width * Overlap.Height
    If Area > LargestArea Then
      LargestArea = Area
      LargestScreen = Screen
    End If
  Next
  Return LargestScreen
End Function
2 Likes

Thanks for everyone’s assistance with this. I finally figured it out. Here’s the code:

I created a Structure with the following elements:

LeftX As integer

TopY As integer

MonitorNumber As integer

I created the following Method:

Private Function GetWindowCoordinates() As structWindowCoordinates

Var LeftX As Integer = Self.Left
Var TopY As Integer = Self.Top
Var monitorNum As Integer = 0
var coordinates As structWindowCoordinates

For i As Integer = 0 To DesktopDisplay.DisplayCount - 1
  Var dd As DesktopDisplay = DesktopDisplay.DisplayAt(i)
  
  If LeftX >= dd.AvailableLeft And _
    LeftX < dd.AvailableLeft + dd.AvailableWidth And _
    TopY >= dd.AvailableTop And _
    TopY < dd.AvailableTop + dd.AvailableHeight Then
    
    monitorNum = i
    
    Exit
  End If
Next

coordinates.LeftX = LeftX
coordinates.TopY = TopY
coordinates.MonitorNumber = monitorNum

return coordinates

Once I retrieve the coordinates and the monitor number where the Window is displayed, I can then pretty much do whatever I want. In this case, I simply center the Window on that particular monitor like this:

Var c As structWindowCoordinates = GetWindowCoordinates()
Var dd As DesktopDisplay = DesktopDisplay.DisplayAt(c.MonitorNumber)

// Move the window to center of the monitor where it is being displayed
Self.Left = dd.AvailableLeft + (dd.AvailableWidth - Self.Width) / 2
Self.Top = dd.AvailableTop + (dd.AvailableHeight - Self.Height) / 2

I have tested it with 1-3 monitors and thus far, it’s working well. I’ll likely roll this into a library and create it as an Extension Method.