Search code examples
vb6

How to automatically resize or reposition controls on a form when the form is resized?


So I'm trying to make my form fit to all monitors. Some have different display resolution and scale.

I can resize my form to fit to the display but all properties of its contents don't adjust to that new size.

What I want is if the form is scaled to fit to the display, the controls on the Form should adjust as well. Specifically properties like Left, Top, Width, Height, and so one, on every control.

The size could be scaled down or up.


Solution

  • It's possible to iterate through all of the controls on the form (mostly) programmatically, rather than having to explicitly adjust each control. You may have to put in some exceptions for some types of controls (such as timers, which I've put in the example), but generally you can use something like:

      Option Explicit
    
      Private Type ControlInfo_type
        Left As Single
        Top As Single
        Width As Single
        Height As Single
        FontSize As Single
      End Type
      Dim ControlInfos() As ControlInfo_type
    
    Private Sub Form_Load()
    
      Dim ThisControl As Control
      
      ReDim Preserve ControlInfos(0 To 0)
      ControlInfos(0).Width = Me.Width
      ControlInfos(0).Height = Me.Height
      For Each ThisControl In Me.Controls
        ReDim Preserve ControlInfos(0 To UBound(ControlInfos) + 1)
        On Error Resume Next  ' hack to bypass controls with no size or position properties
        With ControlInfos(UBound(ControlInfos))
          .Left = ThisControl.Left
          .Top = ThisControl.Top
          .Width = ThisControl.Width
          .Height = ThisControl.Height
          .FontSize = ThisControl.FontSize
        End With
        On Error GoTo 0
      Next
    
    End Sub
    
    Private Sub Form_Resize()
    
      Dim ThisControl As Control, HorizRatio As Single, VertRatio As Single, Iter As Integer
      
      If Me.WindowState = vbMinimized Then Exit Sub
      
      HorizRatio = Me.Width / ControlInfos(0).Width
      VertRatio = Me.Height / ControlInfos(0).Height
      
      Iter = 0
      For Each ThisControl In Me.Controls
        Iter = Iter + 1
        On Error Resume Next  ' hack to bypass controls
        With ThisControl
          .Left = ControlInfos(Iter).Left * HorizRatio
          .Top = ControlInfos(Iter).Top * VertRatio
          .Width = ControlInfos(Iter).Width * HorizRatio
          .Height = ControlInfos(Iter).Height * VertRatio
          .FontSize = ControlInfos(Iter).FontSize * HorizRatio
        End With
        On Error GoTo 0
      Next
      
    End Sub
    

    I tested this with the default form with a CommandButton, Frame, Timer, and TextBox, and it seemed to work OK. You'll probably want to tune the limits on the minimum and maximum sizes for appearance, and my handling of the font is very crude; this could be optimized also. But perhaps this could be a starting point.

    This code depends upon the controls iterating the same way each time, which could conceivably break. One way around this would be to use a Collection or other data structure with the name of the control as a key; when iterating in the .Resize event, each control would be looked up by name. Additional structure will be necessary if any of the controls are themselves arrays, and even more if controls are loaded or unloaded dynamically.