Page 1 of 1

Adjust Control's Size/Position With Screen Resolution Rate Topic: -----

#1 ricardosms  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 74
  • View blog
  • Posts: 301
  • Joined: 02-April 10

Posted 18 April 2011 - 01:51 PM

Hello!

I was experimenting with an idea I had and I came out with a control to resize and reposition all the other controls on the form.
In this example I have two projects, the first one is a regular windows form with several controls and containers that will adjust automatically to another screen resolution. It also contains on the tools menu and on one button a code to check if it is really working. You could adapt the functions to your particular situation.

The other project is a DLL, based on the same code. It only needs to be dropped on the form and it will do all the job. I didn't allow for adjusting the font.size property of the controls because it is read-only and you need to create new fonts at runtime, and they could be of any font family of your choice, and the sizes discrete.

For the project #1:

I created an arraylist that will contain all the controls as object, not the controls names. And variables to contain the "WIDTH" and "HEIGHT" resolution of the screen, and to contain the ratios of the resolution change between two different computers.

Imports System.Collections 'For arraylist

Public Class Form1
    Private CtlArray As New ArrayList
    Dim intX, intY As Integer
    Dim Xratio, Yratio As Single
.
.
.



Then these variables are filled in the form load event.

Also in the form load event, we will add to the arraylist the primary controls in the form. And then call a subroutine that will check for the container controls that might have children of their own.
This subroutine, "GetTheChildren()" will call other subroutines.

After all the controls have been accounted for then the resize subroutine is called.

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'Screen Resolution values on running computer
        intX = Screen.PrimaryScreen.Bounds.Width
        intY = Screen.PrimaryScreen.Bounds.Height

        'These are design screen resolutions, but should work with other resolutions too
        'You should design at low resolution, so components will grow and not shrink when taken
        'to other computers. I haven't check for font size, but by growing the components you won't have
        'a problem.
        Xratio = intX / 1152
        Yratio = intY / 864

        'Get the controls on the form, including menus, but not the controls in other containers
        For Each Cnt As Control In Me.Controls
            CtlArray.Add(Cnt)
        Next

        'Get the children controls
        GetTheChildren()

        'Adjust New size and position
        ResizeThem()
    End Sub



This subroutine:

    Private Sub GetTheChildren()
        'Gets the controls inside containes like panels or tabcontrols
        'For Each ctl As Control In GetAllControls(Me.Parent)
        For Each ctl As Control In GetAllControls(Me)
            If ctl.Parent IsNot Me Then
                If TypeOf ctl.Parent Is TabPage Then
                    If ctl.Name = "" Then
                        CtlArray.Add(ctl)
                    Else
                        CtlArray.Add(ctl)
                    End If
                Else
                    If Not TypeOf (ctl) Is TabPage Then
                        If ctl.Name = "" Then
                            CtlArray.Add(ctl)
                        Else
                            CtlArray.Add(ctl)
                        End If
                    End If
                End If
            End If
        Next
    End Sub


calls a function, "GetAllControls" that will cycle through the controls and will find the controls of type container.

    Function GetAllControls(ByVal container As Control) As Control()
        Dim al As New ArrayList
        Dim ctl As Control
        For Each ctl In container.Controls
            GetControlsWithChildren(ctl, al)
        Next
        Return al.ToArray(GetType(Control))
    End Function



GetAllcontrols calls a recursive subroutine "GetControlsWithChildren" that will find all the other controls embedded on a container, IE: panel, tabcontrol, splitcontainer:

    Sub GetControlsWithChildren(ByVal container As Control, ByVal al As ArrayList)
        ' add this control to the ArrayList
        al.Add(container)
        ' add all its child controls, by calling this routine recursively
        Dim ctl As Control

        For Each ctl In container.Controls
            'A TabPage is a Panel; SplitContainer is a Panel
            GetControlsWithChildren(ctl, al)
        Next

    End Sub



At the end of form load "ResizeThem". This subroutine will look at the controls on the arraylist and, after checking it's type, will adjust the LEFT, TOP, WIDTH, HEIGHT, DOCK and AUTOSIZE of the control.

    Private Sub ResizeThem()
        Dim i As Integer
        For i = 0 To CtlArray.Count - 1
            If TypeOf CtlArray.Item(i) Is MenuStrip Then
            Else
                If TypeOf CtlArray.Item(i) Is Panel And CtlArray.Item(i).parent IsNot Me Then
                    'SplitPanel for instance
                Else
                    CtlArray.Item(i).autosize = False
                    CtlArray.Item(i).dock = 0
                    CtlArray.Item(i).width = CtlArray.Item(i).width * Xratio
                    CtlArray.Item(i).left = CtlArray.Item(i).left * Xratio
                    CtlArray.Item(i).height = CtlArray.Item(i).height * Yratio
                    CtlArray.Item(i).top = CtlArray.Item(i).top * Yratio
                End If
            End If
        Next
    End Sub



In this example I provided and extra subroutine, with a button and also in the menu, that will adjust size and position by 5%. This is just like a test to show that it really works.

   Private Sub ToolStripMenuItem1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripMenuItem1.Click, Button1.Click
        'This subroutine is just to check if the resizing will actually take effect.
        Dim i As Integer
        For i = 0 To CtlArray.Count - 1
            If TypeOf CtlArray.Item(i) Is MenuStrip Then
            Else
                If TypeOf CtlArray.Item(i) Is Panel And CtlArray.Item(i).parent IsNot Me Then
                    'SplitPanel for instance
                Else
                    CtlArray.Item(i).autosize = False
                    CtlArray.Item(i).dock = 0
                    CtlArray.Item(i).width = CtlArray.Item(i).width * 1.05
                    CtlArray.Item(i).left = CtlArray.Item(i).left * 1.05
                    CtlArray.Item(i).height = CtlArray.Item(i).height * 1.05
                    CtlArray.Item(i).top = CtlArray.Item(i).top * 1.05

                End If
            End If
        Next

    End Sub




The second project is the DLL. It is the same code. Except that instead of calling the routines with "ME", it calls them with "ME.PARENT" and doesn't have the resizing subroutine:

Project #2:

Imports System.Collections
Imports System.Windows.Forms

Public Class Size
    Private CtlArray As New ArrayList
    Dim intX, intY As Integer
    Dim Xratio, Yratio As Single

    Private Sub SizeNPos_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        intX = Windows.Forms.Screen.PrimaryScreen.Bounds.Width
        intY = Screen.PrimaryScreen.Bounds.Height
        'These are my design screen resolutions, but should work with other resolutions too
        Xratio = intX / 1152
        Yratio = intY / 864
        'Gets the controls on the form, including menus, but not the controls in other containers
        For Each Cnt As Control In Me.Parent.Controls
            CtlArray.Add(Cnt)
        Next
        'Get the children controls
        GetTheChildren()
        'Adjust New size and position
        ResizeThem()
    End Sub

    Function GetAllControls(ByVal container As Control) As Control()
        Dim al As New ArrayList
        Dim ctl As Control
        For Each ctl In container.Controls
            GetControlsWithChildren(ctl, al)
        Next
        Return al.ToArray(GetType(Control))
    End Function

    Sub GetControlsWithChildren(ByVal container As Control, ByVal al As ArrayList)
        ' add this control to the ArrayList
        al.Add(container)
        ' add all its child controls, by calling this routine recursively
        Dim ctl As Control

        For Each ctl In container.Controls
            'A TabPage is a Panel; SplitContainer is a Panel
            GetControlsWithChildren(ctl, al)
        Next

    End Sub

    Private Sub GetTheChildren()
        'Gets the controls inside containes like panels or tabcontrols
        'For Each ctl As Control In GetAllControls(Me.Parent)
        For Each ctl As Control In GetAllControls(Me.Parent)
            If ctl.Parent IsNot Me Then
                If TypeOf ctl.Parent Is TabPage Then
                    If ctl.Name = "" Then
                        CtlArray.Add(ctl)
                    Else
                        CtlArray.Add(ctl)
                    End If
                Else
                    If Not TypeOf (ctl) Is TabPage Then
                        If ctl.Name = "" Then
                            CtlArray.Add(ctl)
                        Else
                            CtlArray.Add(ctl)
                        End If
                    End If
                End If
            End If
        Next
    End Sub

    Private Sub ResizeThem()
        Dim i As Integer
        For i = 0 To CtlArray.Count - 1
            If TypeOf CtlArray.Item(i) Is MenuStrip Then
            Else
                If TypeOf CtlArray.Item(i) Is Panel And CtlArray.Item(i).parent IsNot Me Then
                    'SplitPanel for instance
                Else
                    CtlArray.Item(i).autosize = False
                    CtlArray.Item(i).dock = 0
                    CtlArray.Item(i).width = CtlArray.Item(i).width * Xratio
                    CtlArray.Item(i).left = CtlArray.Item(i).left * Xratio
                    CtlArray.Item(i).height = CtlArray.Item(i).height * Yratio
                    CtlArray.Item(i).top = CtlArray.Item(i).top * Yratio
                End If
            End If
        Next
    End Sub


End Class



Please check the code and give me some feedback.

Thank you,

ricardosms.

Attached File  Adjust Control's Size-Position With Screen Resolution.zip (185.99K)
Number of downloads: 4281

Is This A Good Question/Topic? 1
  • +

Replies To: Adjust Control's Size/Position With Screen Resolution

#2 _HAWK_  Icon User is offline

  • Master(Of Foo)
  • member icon

Reputation: 1162
  • View blog
  • Posts: 4,444
  • Joined: 02-July 08

Posted 05 May 2011 - 10:17 PM

What about taking into account the taskbar's size and location. I dock mine on the right, and it is larger.
Was This Post Helpful? 0
  • +
  • -

#3 ricardosms  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 74
  • View blog
  • Posts: 301
  • Joined: 02-April 10

Posted 07 May 2011 - 03:09 PM

View Posthawkvalley1, on 05 May 2011 - 10:17 PM, said:

What about taking into account the taskbar's size and location. I dock mine on the right, and it is larger.


Hello!

You could modify the code to use working area instead of screen bounds and limit the size of the form to this maximum

Me.MaximumSize = Screen.PrimaryScreen.WorkingArea.Size



Where you put the windows taskbar is a matter of preference, but I think you are taking a big chunk on the width of the screen because the captions will have at least a full word, don't you think so?
Was This Post Helpful? 0
  • +
  • -

#4 _HAWK_  Icon User is offline

  • Master(Of Foo)
  • member icon

Reputation: 1162
  • View blog
  • Posts: 4,444
  • Joined: 02-July 08

Posted 11 June 2011 - 02:09 PM

Well I'm using Windows 7 and it makes a more even sized screen for me. Instead of it being a long narrow(height) screen it looks more symmetrical when I make the Taskbar grow, and it's only just over an inch. I am familiar with the working area, just thought we would mention that. Nice work!
Was This Post Helpful? 0
  • +
  • -

#5 ricardosms  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 74
  • View blog
  • Posts: 301
  • Joined: 02-April 10

Posted 17 June 2011 - 08:04 AM

Thank you. I am still stuck on vista, I haven't try 7 yet. I am kind of backwards, I still do things on DOS some thimes.
Was This Post Helpful? 0
  • +
  • -

#6 ErJavis  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 01-March 14

Posted 01 March 2014 - 06:07 AM

You are awesome!!!
Can you implement de font size please? :)

Thank you very much
Was This Post Helpful? 0
  • +
  • -

#7 ricardosms  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 74
  • View blog
  • Posts: 301
  • Joined: 02-April 10

Posted 09 March 2014 - 07:35 AM

Hey.

The font size is a read only property. You can't change it on runtime. If you want a different font or different size, you need to create a new font every time, like this:

Dim FontName As String = "Arial"
Dim FontSize As Integer = 14
Dim FS As New Font(FontName, FontSize, FontStyle.Regular)
Label1.Font = FS



Due to the fact that the monitor display of your users could be of any size and any resolution choice, you can't have a single font. A workaround would be to create few fonts of the same style, but different sizes, and depending on your resizing ratio you could choose one of them. You could set an "if block" or a "select case block" and apply the new font, depending on the ranges.
Was This Post Helpful? 0
  • +
  • -

#8 oqapsking  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 6
  • Joined: 25-April 15

Posted 02 May 2017 - 03:44 AM

hello

your code works great with all the controls but the fonts size and the image list size

i know you said that we are gonna need to change it one by one

Dim FontName As String = "Arial"
Dim FontSize As Integer = 14
Dim FS As New Font(FontName, FontSize, FontStyle.Regular)
Label1.Font = FS



maybe since then you came up with new way to automatically do it
i need that because i have lots of labels and controls that read values

with thanks
Was This Post Helpful? 0
  • +
  • -

#9 maceysoftware  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 348
  • View blog
  • Posts: 1,491
  • Joined: 07-September 13

Posted 02 May 2017 - 04:19 AM

Hello There,

This tutorial is quite old being written 6 years ago and last commented on 3 years ago, If you have a question about a tutorial that is this sort of age you should really raise a question in the correct forum and post a link to the tutorial as reference.

However that being said:

Quote

maybe since then you came up with new way to automatically do it


Rather sadly the properties on a Font is still read-only, so you will need to create a new font whenever you need to update the font on a control or even batch of controls.

However I would like to mention here that if you are doing things with the font you have to remember to dispose of them afterwards.

So for example if your creating a new font and then setting that font to a labels, you should then dispose of the font afterwards, I personally like to do this with a using block.

        ' I don't need to say regular here because the default if regular
        Using newFont As New Font("Arial", 14)
            Label1.Font = newFont
        End Using


Also keep in mind if your setting a few labels to the a same font you don't need to create a new font for each label you can use the same font.

        Using newFont As New Font("Arial", 14)
            Label1.Font = newFont
            Label2.Font = newFont
            Label3.Font = newFont
            Label4.Font = newFont
        End Using


Now your question was is there a better way to automate it? what exactly do you mean by this, so far I have said you still need to create a font if you want to change the font but are you trying to reduce the amount of code you have to write so that you don't have to do:

      Label1.Font = newFont
            Label2.Font = newFont
            Label3.Font = newFont
            Label4.Font = newFont


If so, then yes there are better ways if you want all (or learn how to limit to set ones) labels (for example) to change there font to the same font.

From Framework 3.5 you can now use lambda expressions of collections so that you can filter them down, So as you have a arrayList of controls you could filter it down to a set type/types and then set the font that way.

Personally I wouldn't use a arrayList and therefore my example will just be using the ControlCollection straight off of a form. This should give you a example of how you can do this.

        ' I don't need to say regular here because the default if regular
        Using newFont As New Font("Arial", 14)
' Here i am just getting the immediate label controls (which is what the OfType does) on the form, so not controls that are sitting on parent controls like panels or splitpanels
' Sticking them into a list and then basically doing a foreach, this will loop around each label and only update the label's font
            Me.Controls.OfType(Of Label).ToList.ForEach(Sub(label) label.Font = newFont)
        End Using


Obviously there are other ways if you want to do Labels and Textbox but not DataGridView or Checkboxes for example.

This is in C# rather than VB however its worth while reading.
How you use Lambda Expressions

Here is a different example in VB however, but there is alot of information on that page and it may be worth reading the first link first:
https://msdn.microso...8.aspx#Anchor_0

And here a link to the OfType method i was actually using
https://msdn.microsoft.com/en-us/library/bb360913(v=vs.110).aspx

This post has been edited by maceysoftware: 02 May 2017 - 04:20 AM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1