B4J Question Help needed to center form on extended monitor

rfresh

Well-Known Member
Licensed User
In the showOn event I am trying to center the form on my extended monitor but the form is positioned at the top of the extended monitor.
The extended monitor height is 1080 and the WindowTop calculates to 140 but the form is at the top so it would seem the WindowTop is 0?


B4X:
#Region Project Attributes
    #MainFormWidth: 600
    #MainFormHeight: 600
#End Region

Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Private xui As XUI
    Private btnFileDialog As Button
    Private fc As FileChooser
    Private f As String
    Private ParsedData As Map

    Private fx As JFX
    Private MainForm As Form
    Dim desktop(fx.Screens.Size) As Double
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("Layout1")
    MainForm.Show
    MainForm.Title = "Convert .fpl To *.fms"

    Dim sc As List = fx.Screens
    Dim cnt As Int = 0
    For Each o As JavaObject In sc
        Dim bounds As JavaObject = o.RunMethodjo("getBounds",Null)' required
        Dim minX As Double = bounds.RunMethod("getMinX",Null)'required
        Dim minY As Double = bounds.RunMethod("getMinY",Null)' optional
        Dim width As Double = bounds.RunMethod("getWidth",Null)' optional
        Dim height As Double = bounds.RunMethod("getHeight",Null)'optional
        If cnt == 1 Then
            Dim width1 As Double = bounds.RunMethod("getWidth",Null)' optional
            Dim height1 As Double = bounds.RunMethod("getHeight",Null)'optional
        End If
        'Log($"Screen is ${width} x ${height} pixels"$)' optional
        'Log($"minimum X: ${minX}  minimum Y: ${minY}"$)' optional
        desktop(cnt) = minX ' required
        cnt = cnt + 1  ' required
    Next
    Log(cnt)
    'MainForm.WindowHeight = 800
    'MainForm.WindowWidth = 1200
    'MainForm.WindowTop = (height-MainForm.WindowHeight)/2
    'Dim d5 As Double = (height-MainForm.WindowHeight)/2
    'Log(height)
    'Log(MainForm.WindowHeight)
    'Log(d5)
    'Log(MainForm.WindowTop)
    showOn(1,MainForm,height1,width1)' form must be shown before this or has no values for left,top etc
End Sub
'Return true to allow the default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
    Return True
End Sub

Sub showOn(Screen As Int, what As Form, height1 As Double, width1 As Double)
    Dim maxScreen As Int = desktop.Length-1 ' maximum number of screens
    If Screen > maxScreen Then ' if trying to display on non existant screen show on last one
        Screen = maxScreen
    End If
    what.WindowHeight = 800
    what.WindowWidth = 1200
    what.WindowLeft = what.WindowLeft + desktop(Screen) ' modify form co-ords to go on new screen
    what.WindowTop = (height1-what.WindowHeight)/2
    Log(what.WindowTop)
    Log(height1)
    Log(what.WindowHeight)
End Sub

Sub btnFileDialog_Click
    fc.Initialize
    fc.InitialDirectory = "C:\Users\rfresh1011\Documents\3DGarmin430\"
    fc.setExtensionFilter("ForeFlight2", Array As String("*.fpl"))
    f = fc.ShowOpen(MainForm)
    'Log(f)

    Dim x2m As Xml2Map
    x2m.Initialize
    ParsedData = x2m.Parse(File.ReadString(f, ""))
    'Log(m)
    'easier to understand the structure with:
    'Dim jg As JSONGenerator
    'jg.Initialize(m)
    'Log(jg.ToPrettyString(4))

    Dim flightplan As Map = ParsedData.Get("flight-plan")
    Dim waypointtable As Map = flightplan.Get("waypoint-table")
    Dim waypoints As List = waypointtable.Get("waypoint")
    For Each item As Map In waypoints
        Dim identifier As String = item.Get("identifier")
        Log(identifier)
        'Dim link As String = item.Get("link")
        'ListView1.AddSingleLine2(title, link)
    Next
End Sub
 

stevel05

Expert
Licensed User
Javafx stage has a centerOnSreen method which you can call:

B4X:
    Dim Stage As JavaObject = MainForm
    Stage = Stage.GetField("stage")
    Stage.RunMethod("centerOnScreen",Null)

But it also puts the form nearer the top and the form has to be completely in the second screen to be positioned there..

I think the issue you are having is caused by using getBounds from the screen, where you need to use getVisualBounds, (which are the values that are stored in the screen object).

I have done some work on this for the replacement titlebar Library, i would implement it as attached. It also has the call to the Stage.centerOnScreen method for comparison.

I use a small rectangle in the middle of the form to get the current screen as this avoids the issue mentioned above of the form having to be completely in the second screen to be positioned there.
 

Attachments

  • CenterOnScreen.zip
    2.6 KB · Views: 50
Upvote 0

rfresh

Well-Known Member
Licensed User
I get this error: Parameter name cannot hide global variable name

with this line:

Public Sub GetRectDblFromForm(F As Form) As RectDbl

and message that Sub 'CenterOnScreen' is not used.
 

Attachments

  • code.txt
    3.7 KB · Views: 45
Last edited:
Upvote 0

stevel05

Expert
Licensed User
If you are moving it into your own code and have a global variable called F, then you will need to rename the Parameter and it's uses in the getrectdoublefromform sub.
 
Upvote 0

oparra

Well-Known Member
Licensed User
??
Very Nice:
 
Upvote 0

rfresh

Well-Known Member
Licensed User
Yes I did have an F defined. I wasn't using it so I commented it out and the error went away.

My form still shows on my main monitor instead of my extended monitor.

I'm now just seeing this msg:

Main - 81: Sub 'CenterOnScreen' is not used.
 
Upvote 0

stevel05

Expert
Licensed User
You need to call it when you want to position the window. Presumably straight after mainform.show if you want it to start there. You will also have to change the sub to accept the screen you want it to display on and pass the appropriate screen.

Try this.

B4X:
Sub CenterOnScreen(Scr As Screen)
    
    Dim ScrWidth As Double = Scr.MaxX - Scr.MinX
    Dim ScrHeight As Double = Scr.MaxY - Scr.MinY
    
    MainForm.WindowTop = Scr.MinY +  (ScrHeight - MainForm.WindowHeight) / 2
    MainForm.WindowLeft = Scr.MinX + (ScrWidth - MainForm.WindowWidth) / 2
End Sub
 
Upvote 0

stevel05

Expert
Licensed User
Just made a small amendment to the example in post#2 that handles the form being mostly off the right of the last screen, or bottom of the screen.
 
Upvote 0
Top