Determine Form Size from another Form

703 Views Asked by At

VB2012: In order to do some calculations in my main form I need to know the form size of a secondary form. The form size may change from user to user depending on OS and theme. I understand that the client size stays the same. However I think I am not doing something correctly as I get different numbers depending on where I call for the form size.

As an illustration here is my main form where on the load event I attempt to get the size of an Alert form

Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    'get the default width and height of an Alert form.
    Dim frmW As Integer = frmAlert.Width 'in pixels
    Dim frmH As Integer = frmAlert.Height 'in pixels
    Dim frCsW As Integer = frmAlert.ClientSize.Width 'in pixels
    Dim frmCsH As Integer = frmAlert.ClientSize.Height 'in pixels
    Debug.Print("frmW={0} frmH={1} frCsW={2} frmCsH={3}", frmW, frmH, frCsW, frmCsH)
End Sub

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    'set up a new alert form
    Dim frm As New frmAlert

    'show the alert form
    frm.StartPosition = FormStartPosition.CenterParent
    frm.Show()          'with this option the Alert Forms stay on the screen even if the Main form is minimized.
End Sub

Now the Alert form is set with FormBorderStyle=FixedDialog, ControlBox=False, MaximizeBox=False, and MinimizeBox=False and in the Alert form I have this on the load event:

Private Sub frmAlert_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Debug.Print("me.width={0} me.height={1} cs.width={2} cs.height={3}", Me.Width, Me.Height, Me.ClientSize.Width, Me.ClientSize.Height)
End Sub

and here is the debug output

frmW=380 frmH=168 frCsW=374 frmCsH=162
me.width=390 me.height=200 cs.width=374 cs.height=162

As expected the client size is the same but the total form size is different. I am trying to wrap my head around the differences in .Height and .Width. No other code exists to change the form properties. The second debug statement matches the form Size in the IDE designer. Why are the dimensions different? How would I properly query to get the form size from another form?

2

There are 2 best solutions below

0
On BEST ANSWER

Before the form is shown it will have a smaller size compared to when it is visible. This is because when you show the form Windows will do all kinds of stuff to it based on the user's screen and theme settings, such as:

  • Resize it if the user has different DPI settings.
  • Apply borders to it based on the user's selected window theme.
  • (etc.)

Your best bet is to show the form first, then get its size.

If you don't want the form to be visible right away you can set its Opacity property to 0 to make it invisible, then change it back to 1.0 once you need the form to be shown to the user.

0
On

Ok so based on @Visual Vincent's suggestion I created a constructor when creating a new form. This goes in frmAlert.Designer.vb

Partial Class frmAlert
    Private mIsProcessFormCode As Boolean = True

    Public Sub New()
        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        Me.mIsProcessFormCode = True
    End Sub

    Public Sub New(ByVal IsProcessFormCode As Boolean)
        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        Me.mIsProcessFormCode = IsProcessFormCode
    End Sub
End Class

Then on the frmMain I add this code:

Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Debug.Print("routine={0}", System.Reflection.MethodBase.GetCurrentMethod.Name)
    Dim frm As New frmAlert(False) 'create an instance of the form without any of the Form processes
    frm.Opacity = 0 'makes the form totally transparent
    frm.Visible = False
    frm.Show()
    Dim frmWidth As Integer = frm.Width
    Dim frHeight As Integer = frm.Height
    Dim frCsWidth As Integer = frm.ClientSize.Width
    Dim frCsHeight As Integer = frm.ClientSize.Height
    frm.Close()
    frm.Dispose()
    Debug.Print("frmWidth={0} frHeight={1} frCsWidth={2} frCsHeight={3}", frmWidth, frHeight, frCsWidth, frCsHeight)
End Sub

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Debug.Print("routine={0}", System.Reflection.MethodBase.GetCurrentMethod.Name)

    'set up the alert form normally
    Dim frm As New frmAlert

    'show the alert form
    frm.StartPosition = FormStartPosition.CenterParent
    frm.Show()          'with this option the Alert Forms stay on the screen even if the Main form is minimized.
End Sub

and in the frmAlert I add this code:

Private Sub frmAlert_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed
    Try
        'process the form code ONLY if required
        Debug.Print("routine={0} mIsProcessFormCode={1}", System.Reflection.MethodBase.GetCurrentMethod.Name, mIsProcessFormCode)
        If mIsProcessFormCode Then
            'do Closed stuff
        End If
    Catch ex As Exception
        Debug.Print(ex.ToString)
    End Try
End Sub

Private Sub frmAlert_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
    Try
        'process the form code ONLY if required
        Debug.Print("routine={0} mIsProcessFormCode={1}", System.Reflection.MethodBase.GetCurrentMethod.Name, mIsProcessFormCode)
        If mIsProcessFormCode Then
            'do Closing stuff
        End If
    Catch ex As Exception
        Debug.Print(ex.ToString)
    End Try
End Sub

Private Sub frmAlert_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Try
        'process the form code ONLY if required
        Debug.Print("routine={0} mIsProcessFormCode={1}", System.Reflection.MethodBase.GetCurrentMethod.Name, mIsProcessFormCode)
        Debug.Print("me.width={0} me.height={1} cs.width={2} cs.height={3}", Me.Width, Me.Height, Me.ClientSize.Width, Me.ClientSize.Height)
        If mIsProcessFormCode Then
            'process text file
        End If
    Catch ex As Exception
        Debug.Print(ex.ToString)
    End Try
End Sub

and the debug output:

routine=frmMain_Load
routine=frmAlert_Load mIsProcessFormCode=False
me.width=390 me.height=200 cs.width=374 cs.height=162
routine=frmAlert_FormClosing mIsProcessFormCode=False
routine=frmAlert_FormClosed mIsProcessFormCode=False
frmWidth=390 frHeight=200 frCsWidth=374 frCsHeight=162
routine=Button1_Click
routine=frmAlert_Load mIsProcessFormCode=True
me.width=390 me.height=200 cs.width=374 cs.height=162

I believe this is what I want. All frmAlert sizes match what I have in the IDE designer. If you can think of any modifications please let me know. Many thanks.