none
Resizing form controls when maximizing on different screens RRS feed

  • Question

  • I have a form that is formatted correctly when it opens. What I'm needing is for the controls, labels, and images to resize according to the current ratio when I maximize the screen. When I maximize, it just creates a lot of empty space as noted in location 3. What am I missing? 
    • Edited by Pilot160 Monday, February 26, 2018 9:28 PM Clarification
    Monday, February 26, 2018 9:17 PM

Answers

  • Hi Pilot160,

    I'm using this code:
    Private Sub Form1_SizeChanged(sender As Object, e As EventArgs) Handles MyBase.SizeChanged
    	Me.SuspendLayout()
    	' --- adjust size and location of Controls on this form
    	If Not (Me.WindowState = FormWindowState.Minimized) Then
    		' --- decide size factor
    		Dim sfWidth As Single = (Me.ClientSize.Width / Me.originalSize.Width)
    		Dim sfHeight As Single = (Me.ClientSize.Height / Me.originalSize.Height)
    		Dim sizeFactor As New SizeF(sfWidth, sfHeight)
    		' --- scaling
    		For Each ctrl As Control In Me.Controls
    			If (TypeOf ctrl Is ListBox) Then
    				DirectCast(ctrl, ListBox).IntegralHeight = False
    			End If
    			If (TypeOf ctrl Is ComboBox) Then
    				DirectCast(ctrl, ComboBox).IntegralHeight = False
    			End If
    			' --- Font scaling
    			Dim fntScale As Single = (ctrl.Font.Size * sizeFactor.Height)
    			ctrl.Font = New Font(ctrl.Font.FontFamily, fntScale, ctrl.Font.Style, ctrl.Font.Unit)
    			' --- Control scaling
    			ctrl.Scale(sizeFactor)
    		Next
    		' --- save as original size
    		Me.originalSize = Me.ClientSize
    	End If
    End Sub

    And I would like to suggest to make your program DPI-Aware.
    For that purpose you need to
    (1) make [AutoScaleMode = Dpi] in Windows Form  
    (2) menu [Project] > [Add New Item] > [Application Manifest File]
        > (in the file "app.manifest") change code like this:
    <!-- ▼ DPI Aware ▼ -->
    <application xmlns="urn:schemas-microsoft-com:asm.v3">
    	<windowsSettings>
    		<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
    	</windowsSettings>
    </application>

    Regards,

    Ashidacchi

    • Edited by Ashidacchi Tuesday, February 27, 2018 6:12 AM
    • Marked as answer by Pilot160 Wednesday, February 28, 2018 5:04 AM
    Tuesday, February 27, 2018 5:19 AM

All replies

  • Hi

    Here is some test code to try out. Try it as a separate test project. Start a new project and add a bunch of controls in the Designer. Then run it at the different screen resolution and see if it does as expected.

    Option Strict On
    Option Explicit On
    Public Class Form1
      Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    
      End Sub
      '  ==============================
      '            attribute  IronRazerz
      ' https://social.msdn.microsoft.com/Forums/vstudio/en-US/3e2bdf16-d3e1-47e7-94c5-b9219af2666a/if-i-maximize-and-minimize-the-form-means-automatically-the-controls-which-which-i-used-in-the-form?forum=vbgeneral#3028a508-f631-4db9-8e26-7be4acb24221
    
      Private DefaultControlSizes As New Dictionary(Of Control, CtrlInfo)
      Private FormDefaultClientSize As Size
    
      Public Sub New()
    	InitializeComponent()
    	Me.Text = "SpaceX Trajectory v1.03    " & Chr(169) & "LAH June 2017 (Scaling by IronRazerz)"
    	Me.WindowState = FormWindowState.Normal
    	Me.Size = New Size(890, 766)
    	Me.MinimumSize = New Size(650, 570)
    	FormDefaultClientSize = ClientSize
    
    	Dim ctrl As Control = Me.GetNextControl(Me, True)
    	While ctrl IsNot Nothing
    	  If TypeOf ctrl Is ListBox Then DirectCast(ctrl, ListBox).IntegralHeight = False
    	  DefaultControlSizes.Add(ctrl, New CtrlInfo(ctrl.Bounds, ctrl.Font.Size))
    	  ctrl = Me.GetNextControl(ctrl, True)
    	End While
    
      End Sub
    
      Private Sub ScaleControls()
    	If Me.WindowState <> FormWindowState.Minimized Then
    	  For Each kvp As KeyValuePair(Of Control, CtrlInfo) In DefaultControlSizes
    		Dim ctrl As Control = kvp.Key
    
    		Dim Xscl As Double = Me.ClientSize.Width / FormDefaultClientSize.Width
    		Dim Yscl As Double = Me.ClientSize.Height / FormDefaultClientSize.Height
    		Dim fntscl As Single = CSng(kvp.Value.cFontSize * Yscl)
    		If Xscl < Yscl Then
    		  fntscl = CSng(kvp.Value.cFontSize * Xscl)
    		End If
    
    		'comment out this line if you dont want the fonts to be scaled
    		ctrl.Font = New Font(ctrl.Font.FontFamily, fntscl, ctrl.Font.Style, ctrl.Font.Unit)
    
    		ctrl.Width = CInt(kvp.Value.cBounds.Width * Xscl)
    		ctrl.Height = CInt(kvp.Value.cBounds.Height * Yscl)
    		ctrl.Left = CInt(kvp.Value.cBounds.X * Xscl)
    		ctrl.Top = CInt(kvp.Value.cBounds.Y * Yscl)
    	  Next
    	End If
      End Sub
      Private Sub Form1_Resize(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Resize
    	ScaleControls()
      End Sub
    End Class
    Public Class CtrlInfo
      Public cBounds As Rectangle
      Public cFontSize As Single
      Public Sub New(ByVal Bnds As Rectangle, ByVal FntSize As Single)
    	cBounds = Bnds
    	cFontSize = FntSize
      End Sub
    End Class


    Regards Les, Livingston, Scotland

    Monday, February 26, 2018 10:35 PM
  • Hi Pilot160,

    I'm using this code:
    Private Sub Form1_SizeChanged(sender As Object, e As EventArgs) Handles MyBase.SizeChanged
    	Me.SuspendLayout()
    	' --- adjust size and location of Controls on this form
    	If Not (Me.WindowState = FormWindowState.Minimized) Then
    		' --- decide size factor
    		Dim sfWidth As Single = (Me.ClientSize.Width / Me.originalSize.Width)
    		Dim sfHeight As Single = (Me.ClientSize.Height / Me.originalSize.Height)
    		Dim sizeFactor As New SizeF(sfWidth, sfHeight)
    		' --- scaling
    		For Each ctrl As Control In Me.Controls
    			If (TypeOf ctrl Is ListBox) Then
    				DirectCast(ctrl, ListBox).IntegralHeight = False
    			End If
    			If (TypeOf ctrl Is ComboBox) Then
    				DirectCast(ctrl, ComboBox).IntegralHeight = False
    			End If
    			' --- Font scaling
    			Dim fntScale As Single = (ctrl.Font.Size * sizeFactor.Height)
    			ctrl.Font = New Font(ctrl.Font.FontFamily, fntScale, ctrl.Font.Style, ctrl.Font.Unit)
    			' --- Control scaling
    			ctrl.Scale(sizeFactor)
    		Next
    		' --- save as original size
    		Me.originalSize = Me.ClientSize
    	End If
    End Sub

    And I would like to suggest to make your program DPI-Aware.
    For that purpose you need to
    (1) make [AutoScaleMode = Dpi] in Windows Form  
    (2) menu [Project] > [Add New Item] > [Application Manifest File]
        > (in the file "app.manifest") change code like this:
    <!-- ▼ DPI Aware ▼ -->
    <application xmlns="urn:schemas-microsoft-com:asm.v3">
    	<windowsSettings>
    		<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
    	</windowsSettings>
    </application>

    Regards,

    Ashidacchi

    • Edited by Ashidacchi Tuesday, February 27, 2018 6:12 AM
    • Marked as answer by Pilot160 Wednesday, February 28, 2018 5:04 AM
    Tuesday, February 27, 2018 5:19 AM
  • What is the "integralheight" and "originalheight" in your code? It causes a build error because those are "not members of xxx"
    Tuesday, February 27, 2018 7:34 PM
  • Les,

    That does exactly what I want it to in my test form! But when I put it into my real form it says parts of the code are not members of frmRockaxeLanes. Any idea how to fix this?

    • Edited by Pilot160 Tuesday, February 27, 2018 8:21 PM
    Tuesday, February 27, 2018 8:20 PM
  • What is the "integralheight" and "originalheight" in your code? It causes a build error because those are "not members of xxx"

     The IntegralHeight property is only for ListBox and ComboBox controls.  This is done in the code above because if it is not set to False and you try to resize the Listbox it will snap to the closest size that fits full rows of text in the ListBox.  Notice how it jumps its height to fit full rows as i resize it in the gif image below.

     

     Now,  if you set the IntegralHeight to False,  notice how it can be set to any height even if it shows only a portion of a row...

     

      So,  if you use this code to adjust the height and the ListBox snaps to a bigger or smaller height to fit a full row,  the bottom of it would no longer be scaled to the correct height and may not line up correctly with other controls.

     

     EDIT:  You should also be aware that the code Les posted will work for forms that are not of a fixed size,  meaning you can resize the form by using the mouse or by maximizing/restoring the form.  However,  the code that Ashidacchi has posted will only work if you use a fixed size for the form and it is only resized by maximizing and restoring the form.  It is similar to the answer that i posted In This Thread and explained this limitation of using the Control.Scale Method.

     


    If you say it can`t be done then i`ll try it

    • Edited by IronRazerz Tuesday, February 27, 2018 8:59 PM
    Tuesday, February 27, 2018 8:20 PM
  • You probably won't like this answer, but it is the all-around best solution.

    Use nested panels, particularly in this case TableLayoutPanel, then set each control to fill the table cell using the Anchor and/or Dock properties.

    This way you can decide which portions of your form change size and which change position (or both).  This solution will also handle changes in DPI and/or Font size.

    You would probably have one main TableLayoutPanel with three rows and two columns.  The first cell (Row 0 Column 0) would have your logo picture and the PictureBox would be set to span 2 rows.  The first row in the second column would have Label 1 and the second row would in the second column would have label 2.  The first column of the third row would have another TableLayoutPanel set to span 3 columns.

    This inner TableLayoutPanel would then have 1 row with two columns.  Each of those two cells would contain yet another TableLayoutPanel.  Each of these would have 7 columns and 13 rows.  Each of the cells where the green boxes are located would contain a final TableLayoutPanel with two columns and 1 row so that you could place the two green boxes in each cell.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Tuesday, February 27, 2018 9:41 PM
    Moderator
  • Hi Pilot160,

    As for "originalSize", please add this line in Class Form1.
    Public Class Form1
    	Private originalSize As Size  ' <<---- add here
    	' ---
    	Private Sub Form1_SizeChanged(sender As Object, e As EventArgs) Handles MyBase.SizeChanged
    		......
    	End sib
    End Class

    "IntegralHeight" is a property of ListBox and ComboBox, so you don't have to define it.

    Regards,

    Ashidacchi

    Tuesday, February 27, 2018 10:03 PM
  • IroRazerz,

    I looked at that other thread and tried the code but still get the issue of anything that says "Me.ClientSize, Me.Controls, Me.FormBorderStyle, etc it shows as an error that those properties are not members of the form. Do I need to do something to add them?

    Tuesday, February 27, 2018 10:08 PM
  • IroRazerz,

    I looked at that other thread and tried the code but still get the issue of anything that says "Me.ClientSize, Me.Controls, Me.FormBorderStyle, etc it shows as an error that those properties are not members of the form. Do I need to do something to add them?


    Is this a Windows Forms project?

    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Tuesday, February 27, 2018 10:25 PM
    Moderator
  • Yes, a Windows forms project in visual studio 2017.
    Tuesday, February 27, 2018 10:36 PM
  • IroRazerz,

    I looked at that other thread and tried the code but still get the issue of anything that says "Me.ClientSize, Me.Controls, Me.FormBorderStyle, etc it shows as an error that those properties are not members of the form. Do I need to do something to add them?

     If you are actually using a VB.Net Windows Form project then I don't know why you would get that error unless you are putting the code in the wrong spot or doing something odd.  I guess you will need to show us the full code of your Form so we can see why it is giving this error.

     Every Windows Form has a ClientSize property and a Controls collection,  so I can only guess you are doing something wrong in the code,  or you are not actually creating a Vb.Net Windows Form application.


    If you say it can`t be done then i`ll try it

    Tuesday, February 27, 2018 11:09 PM
  • This is my sample:

    Ashidacchi

    Tuesday, February 27, 2018 11:20 PM
  • Ashidacchi,

     Just so you are aware...  using the Control.Scale method is is not reliable when the form is resized by the mouse.  This can be seen in the gif image below.  Notice the text size and the spaces between the controls when I first start the app,  then again after I resize the form's height and width at the same time and then set it back to its original size.

      This is why I came up with the code that Les has posted.  His is slightly modified from what I originally posted I think but,  it uses the same method to resize the controls as I did. Using the Control.Scale method only seems to be reliable if the form is a fixed size and is only resized by maximizing and restoring the form,  or you only resize it's height or width one at a time.  If you grab the corner of the form and resize it's height and width at the same time you get the flaws that i show above.  8)


    If you say it can`t be done then i`ll try it

    Wednesday, February 28, 2018 2:14 AM