patternMinor
Resizing the controls on an Access form dynamically
Viewed 0 times
resizingthedynamicallycontrolsformaccess
Problem
Below is a sub I wrote to dynamically resize all the controls on a form. It utilizes the
In the form resize event, I then call my procedure and pass the current form:
The
Here is the
Here are the bones of that sub with some comments on what I'm doing:
```
Public Sub RepositionControls(frm As Form) 'Pass in the form as a parameter
On Error Resume Next 'This is probably out of laziness, but it prevents issues when the width of the form gets wide enough to revert to a negative number.
Dim formDetailWidth As Long
Dim formDetailHeight As Long
Dim tagArray() As String
Const HEADER_HEIGHT_PERCENTAGE = 0.1
formDetailWidth = frm.WindowWidth
formDetailHeight = frm.WindowHeight - frm.Section(acHeader).Height - frm.Section(acFooter).Height
'Set the header to 10% of the forms height
frm.Section(acHeader).Height = formDetailHeight * HEADER_HEIGHT_PERCENTAGE
Dim ctl As Control
For Each ctl In frm.Section(acDetail).Controls 'Only looking at controls in the "Detail" section for now
If ctl.Tag <> "" Then
tagArray = Split(ctl.Tag, ":") 'Split the "Tag" property into an array
'Apply each number from the "Tag" property of the control to the Move method respectively
ctl.Move formDetailWidth * (CInt(tagArray(ControlTag.FromLeft)) / 100),
Tag property of each control. In that Tag property, I put four numbers separated by colons. So for instance, the Tag property of one particular control might be 03:10:20:10. These numbers represent Left, Top, Width, and Height (as percentages) respectively to match up to the parameters of the Move method.In the form resize event, I then call my procedure and pass the current form:
Private Sub Form_Resize()
RepositionControls Me
End SubThe
RepositionControls sub resides in a standard module named Utilities. (Not important, but may paint a better picture for you.)Here is the
enum used in the sub:Public Enum ControlTag
FromLeft = 0
FromTop
ControlWidth
ControlHeight
End EnumHere are the bones of that sub with some comments on what I'm doing:
```
Public Sub RepositionControls(frm As Form) 'Pass in the form as a parameter
On Error Resume Next 'This is probably out of laziness, but it prevents issues when the width of the form gets wide enough to revert to a negative number.
Dim formDetailWidth As Long
Dim formDetailHeight As Long
Dim tagArray() As String
Const HEADER_HEIGHT_PERCENTAGE = 0.1
formDetailWidth = frm.WindowWidth
formDetailHeight = frm.WindowHeight - frm.Section(acHeader).Height - frm.Section(acFooter).Height
'Set the header to 10% of the forms height
frm.Section(acHeader).Height = formDetailHeight * HEADER_HEIGHT_PERCENTAGE
Dim ctl As Control
For Each ctl In frm.Section(acDetail).Controls 'Only looking at controls in the "Detail" section for now
If ctl.Tag <> "" Then
tagArray = Split(ctl.Tag, ":") 'Split the "Tag" property into an array
'Apply each number from the "Tag" property of the control to the Move method respectively
ctl.Move formDetailWidth * (CInt(tagArray(ControlTag.FromLeft)) / 100),
Solution
So, I fiddled enough with the code that I think I found a solution that solves almost all the problems mentioned in the question.
UPDATE
I had the percentages of the heights for the header and footer sections set by a CONST variable, but realized it would be better to set those dynamically at run time, just like all the controls. Those elements now have one number in their
UPDATE 2:
I added in the ability to hold down the
Here is the code behind the form:
And here is the code that can be placed in a standard module:
```
Public Enum ControlTag
FromLeft = 0
FromTop
ControlWidth
ControlHeight
OriginalFontSize
OriginalControlHeight
End Enum
Public Sub SaveControlPositionsToTags(frm As Form)
On Error Resume Next
Dim ctl As Control
Dim ctlLeft As String
Dim ctlTop As String
Dim ctlWidth As String
Dim ctlHeight As String
Dim ctlOriginalFontSize As String
Dim ctlOriginalControlHeight As String
For Each ctl In frm.Controls
'Find the relative position of this control in design view
'e.g.- This control is 5% from the left, 10% from the top, etc.
'Those percentages can then be saved in the Tag property for this control
'and used later in the form's resize event
ctlLeft = CStr(Round(ctl.Left / frm.Width, 2))
ctlTop = CStr(Round(ctl.Top / frm.Section(ctl.Section).Height, 2))
ctlWidth = CStr(Round(ctl.Width / frm.Width, 2))
ctlHeight = CStr(Round(ctl.Height / frm.Section(ctl.Section).Height, 2))
'If this control has a FontSize property, then capture the
UPDATE
I had the percentages of the heights for the header and footer sections set by a CONST variable, but realized it would be better to set those dynamically at run time, just like all the controls. Those elements now have one number in their
Tag property which represents the percentage of their height at design time in comparison to the height of the entire form.UPDATE 2:
I added in the ability to hold down the
Shift key and press + or - to make the text in all the controls on the screen bigger or smaller. The fontZoom setting should probably be retrieved from a database instead of stored in the code. This way, each user could set their desired font zoom setting and then the form would continue to use that setting the next time they opened the form. In the code below, I added the fontZoom as a parameter to the RepositionControls sub and adjusted the other code accordingly. Here is the code behind the form:
Private fontZoom As Double
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
'Set an unchangeable variable to the amount (10% for example) to increase or
'decrease the font size with each change.
Const FONT_ZOOM_PERCENT_CHANGE = 0.1
'PURPOSE: Make the text on the form bigger if "Shift" and "+" are pressed
'at the same time and smaller if "Shift" and "-" are pressed at the same time.
'NOTE: Using the "Ctrl" key instead of the "Shift" key conflicts with Access's
'default behavior of using "Ctrl -" to delete a record, so "Shift" is used instead
'Was the "Shift" key being held down while the Key was pressed?
Dim shiftKeyPressed As Boolean
shiftKeyPressed = (Shift And acShiftMask) > 0
'If so, check to see if the user pressed the "+" or the "-" button at the
'same time as the "Shift" key. If so, then make the font bigger/smaller
'by the percentage specificed in the FONT_ZOOM_PERCENT_CHANGE variable.
If shiftKeyPressed Then
Select Case KeyCode
Case vbKeyAdd
fontZoom = fontZoom + FONT_ZOOM_PERCENT_CHANGE
RepositionControls Me, fontZoom
Case vbKeySubtract
fontZoom = fontZoom - FONT_ZOOM_PERCENT_CHANGE
RepositionControls Me, fontZoom
End Select
End If
End Sub
Private Sub Form_Load()
'Set the font zoom setting to the default of 100% (represented by a 1 below).
'This means that the fonts will appear initially at the proportional size
'set during design time. But they can be made smaller or larger at run time
'by holding the "Shift" key and hitting the "+" or "-" key at the same time.
fontZoom = 1
'When the form loads, we need to find the relative position of each control
'and save it in the control's "Tag" property so the resize event can use it
SaveControlPositionsToTags Me
End Sub
Private Sub Form_MouseWheel(ByVal Page As Boolean, ByVal Count As Long)
Debug.Print Page
Debug.Print Count
End Sub
Private Sub Form_Resize()
'Set the height of the header and footer before calling RepositionControls
'since it caused problems changing their heights from inside that sub.
'The Tag property for the header and footer is set inside the SaveControlPositionsToTags sub
Me.Section(acHeader).Height = Me.WindowHeight * CDbl(Me.Section(acHeader).Tag)
Me.Section(acFooter).Height = Me.WindowHeight * CDbl(Me.Section(acFooter).Tag)
'Call the RepositionControls Sub and pass this form as a parameter
'and the fontZoom setting which was initially set when the form loaded and then
'changed if the user holds the "Shift" key and hits the "+" or "-" key also.
RepositionControls Me, fontZoom
End SubAnd here is the code that can be placed in a standard module:
```
Public Enum ControlTag
FromLeft = 0
FromTop
ControlWidth
ControlHeight
OriginalFontSize
OriginalControlHeight
End Enum
Public Sub SaveControlPositionsToTags(frm As Form)
On Error Resume Next
Dim ctl As Control
Dim ctlLeft As String
Dim ctlTop As String
Dim ctlWidth As String
Dim ctlHeight As String
Dim ctlOriginalFontSize As String
Dim ctlOriginalControlHeight As String
For Each ctl In frm.Controls
'Find the relative position of this control in design view
'e.g.- This control is 5% from the left, 10% from the top, etc.
'Those percentages can then be saved in the Tag property for this control
'and used later in the form's resize event
ctlLeft = CStr(Round(ctl.Left / frm.Width, 2))
ctlTop = CStr(Round(ctl.Top / frm.Section(ctl.Section).Height, 2))
ctlWidth = CStr(Round(ctl.Width / frm.Width, 2))
ctlHeight = CStr(Round(ctl.Height / frm.Section(ctl.Section).Height, 2))
'If this control has a FontSize property, then capture the
Code Snippets
Private fontZoom As Double
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
'Set an unchangeable variable to the amount (10% for example) to increase or
'decrease the font size with each change.
Const FONT_ZOOM_PERCENT_CHANGE = 0.1
'PURPOSE: Make the text on the form bigger if "Shift" and "+" are pressed
'at the same time and smaller if "Shift" and "-" are pressed at the same time.
'NOTE: Using the "Ctrl" key instead of the "Shift" key conflicts with Access's
'default behavior of using "Ctrl -" to delete a record, so "Shift" is used instead
'Was the "Shift" key being held down while the Key was pressed?
Dim shiftKeyPressed As Boolean
shiftKeyPressed = (Shift And acShiftMask) > 0
'If so, check to see if the user pressed the "+" or the "-" button at the
'same time as the "Shift" key. If so, then make the font bigger/smaller
'by the percentage specificed in the FONT_ZOOM_PERCENT_CHANGE variable.
If shiftKeyPressed Then
Select Case KeyCode
Case vbKeyAdd
fontZoom = fontZoom + FONT_ZOOM_PERCENT_CHANGE
RepositionControls Me, fontZoom
Case vbKeySubtract
fontZoom = fontZoom - FONT_ZOOM_PERCENT_CHANGE
RepositionControls Me, fontZoom
End Select
End If
End Sub
Private Sub Form_Load()
'Set the font zoom setting to the default of 100% (represented by a 1 below).
'This means that the fonts will appear initially at the proportional size
'set during design time. But they can be made smaller or larger at run time
'by holding the "Shift" key and hitting the "+" or "-" key at the same time.
fontZoom = 1
'When the form loads, we need to find the relative position of each control
'and save it in the control's "Tag" property so the resize event can use it
SaveControlPositionsToTags Me
End Sub
Private Sub Form_MouseWheel(ByVal Page As Boolean, ByVal Count As Long)
Debug.Print Page
Debug.Print Count
End Sub
Private Sub Form_Resize()
'Set the height of the header and footer before calling RepositionControls
'since it caused problems changing their heights from inside that sub.
'The Tag property for the header and footer is set inside the SaveControlPositionsToTags sub
Me.Section(acHeader).Height = Me.WindowHeight * CDbl(Me.Section(acHeader).Tag)
Me.Section(acFooter).Height = Me.WindowHeight * CDbl(Me.Section(acFooter).Tag)
'Call the RepositionControls Sub and pass this form as a parameter
'and the fontZoom setting which was initially set when the form loaded and then
'changed if the user holds the "Shift" key and hits the "+" or "-" key also.
RepositionControls Me, fontZoom
End SubPublic Enum ControlTag
FromLeft = 0
FromTop
ControlWidth
ControlHeight
OriginalFontSize
OriginalControlHeight
End Enum
Public Sub SaveControlPositionsToTags(frm As Form)
On Error Resume Next
Dim ctl As Control
Dim ctlLeft As String
Dim ctlTop As String
Dim ctlWidth As String
Dim ctlHeight As String
Dim ctlOriginalFontSize As String
Dim ctlOriginalControlHeight As String
For Each ctl In frm.Controls
'Find the relative position of this control in design view
'e.g.- This control is 5% from the left, 10% from the top, etc.
'Those percentages can then be saved in the Tag property for this control
'and used later in the form's resize event
ctlLeft = CStr(Round(ctl.Left / frm.Width, 2))
ctlTop = CStr(Round(ctl.Top / frm.Section(ctl.Section).Height, 2))
ctlWidth = CStr(Round(ctl.Width / frm.Width, 2))
ctlHeight = CStr(Round(ctl.Height / frm.Section(ctl.Section).Height, 2))
'If this control has a FontSize property, then capture the
'control's original font size and the control's original height from design-time
'These will be used later to calculate what the font size should be when the form is resized
Select Case ctl.ControlType
Case acLabel, acCommandButton, acTextBox, acComboBox, acListBox, acTabCtl, acToggleButton
ctlOriginalFontSize = ctl.FontSize
ctlOriginalControlHeight = ctl.Height
End Select
'Add all this data to the Tag property of the current control, separated by colons
ctl.Tag = ctlLeft & ":" & ctlTop & ":" & ctlWidth & ":" & ctlHeight & ":" & ctlOriginalFontSize & ":" & ctlOriginalControlHeight
Next
'Set the Tag properties for the header and the footer to their proportional height
'in relation to the height of the whole form (header + detail + footer)
frm.Section(acHeader).Tag = CStr(Round(frm.Section(acHeader).Height / (frm.Section(acHeader).Height + frm.Section(acDetail).Height + frm.Section(acFooter).Height), 2))
frm.Section(acFooter).Tag = CStr(Round(frm.Section(acFooter).Height / (frm.Section(acHeader).Height + frm.Section(acDetail).Height + frm.Section(acFooter).Height), 2))
End Sub
Public Sub RepositionControls(frm As Form, fontZoom As Double)
On Error Resume Next
Dim formDetailHeight As Long
Dim tagArray() As String
'Since "Form.Section(acDetail).Height" usually returns the same value (unless the detail section is tiny)
'go ahead and calculate the detail section height ourselves and store it in a variable
formDetailHeight = frm.WindowHeight - frm.Section(acHeader).Height - frm.Section(acFooter).Height
Dim ctl As Control
'Loop through all the controls on the form
For Each ctl In frm.Controls
'An extra (probably unncessary) check to make sure the Tag property has a value
If ctl.Tag <> "" Then
'Split the Tag property into an Context
StackExchange Code Review Q#148785, answer score: 2
Revisions (0)
No revisions yet.