I'm working in Access 2013 and have a number of controls (listboxes, buttons, etc.) that I want to keep centered, as a group, on a form when the form is resized.
Anchoring won't accomplish what I'm looking for because I don't want to lock the controls to the top/bottom/left/right. I want them to stay in the center.
Simply using code like this me.mycontrol.left = myform.Width/2 on the form's resize event doesn't do what I'm looking for because it aligns the individual controls to the center. I want the group of controls to be centered.
Is there a way to do this?
EDIT: Here's an example, which may make this clearer. Suppose I have a 100 x 100 form with two buttons on it. The buttons are 20 units tall and are spaced 10 units apart. They'd have the following positions:
Button1.Top = 25
(10 unit space starts at 45)
Button2.Top = 55
If the form is resized to 200 x 200, the controls would have the following positions:
Button1.Top = 75
(10 unit space starts at 95)
Button2.top = 105
Ideally, I'd love to turn this into a module, where I just pass it a form and it takes the original position of each control and calculates the new position.
Edit 2:
Here's one failed attempt at it, using my real code, based onthe idea from Krish:
Private Sub Form_Resize()
Dim resizeFactor As Double
resizeFactor = Me.WindowWidth / Me.Width
Me.lstModule.Left = Me.lstModule.Left * resizeFactor
Me.ctlSubform.Left = Me.ctlSubform.Left * resizeFactor
Me.Box6.Left = Me.Box6.Left * resizeFactor
End Sub
I think the anchoring actually is the answer. You simply create a layout grid around your controls and set anchoring like this:
_____________________|___stretch down____|___________________
stretch across top___|___your controls___|stretch across top
_____________________|___stretch down____|___________________
This way your controls will stay always in the middle of the form/subform.
EDIT: Screenshots
EDIT: Added info about borders
Adding borders can be quite a pain, but to some extent, it is possible. You can do this by setting gridline colors, setting the gridline style to solid to your buttons (default is transparent) and adding some padding. In the following example, I set the first button gridline style to solid for LEFT, RIGHT and TOP and set padding 0.1" for those sides as well. If you continue with a similar fashion, your result will look like this:
I could use meta code:
- mark all controls in group with text tag ('Tag' property)
- iterate through all controls on form and calculate leftmost, topmost, rightmost and bottommost position for controls on form (right=left+width, etc) for all controls with a matching tag
- this is the group 'window'
- now iterate through form again, offsetting the controls by an X/Y offset calculated in relation to the group 'window'
Or, I suppose, some real code :-)
Public Function GetControlsWindowSize(tag As String)
Dim f As Form
Dim c As Control
Dim GrpLeft As Long
Dim GrpRight As Long
Dim GrpTop As Long
Dim GrpBottom As Long
For Each c In f.Controls
If c.Properties.Item("tag") = tag Then
If GrpLeft = 0 Or GrpLeft > c.Left Then GrpLeft = c.Left
If GrpRight = 0 Or GrpRight < c.Left + c.Width Then GrpRight = c.Left + c.Width
If GrpTop = 0 Or GrpTop > c.Top Then GrpTop = c.Top
If GrpBottom = 0 Or GrpBottom < c.Top + c.Height Then GrpBottom = c.Top + c.Height
End If
Next
End Function
AFAIK there aren't any layout "containers" in MS Access (except the tabular/stacked view). Your best shot would be add a string to your components.Tag property and loop through that components that have to be re alighned
something like this:
Dim iCtl As control
For Each iCtl In Me.Form
If iCtl.Tag = "resize" Then
On Error Resume Next
Debug.Print "control resizing: " & iCtl.name
iCtl.width = iCtl.width * resizeFactor
iCtl.Height = iCtl.Height * resizeFactor
'left top whatever you want to re align
End If
Next iCtl
I realize this is many years late, but I have an alternate VBA solution for you. I wrote this out after trying many other people's code, but not being satisfied with how they worked.
What I wanted was to have ALL the controls to be centered within the form (pop-up form btw). However I didn't want them all mashed together right in the center, I wanted them to be "Grouped", and have the group of controls centered in the form rather than each individual control centered.
Another condition that I required was it needed to have the controls centered when the window was maximized, or in a smaller window. The controls needed to dynamically center in the form as the user adjusts the form size.
I made a sub procedure that needs to be called in the Private Sub Form_Resize() event and the Private Sub Form_Current() event. I'm using Access 2010.
Private Sub Form_Resize()
'Should run every time the form is resized
Call CenterControls
End Sub
And
Private Sub Form_Current()
'Will run when the form is completing its initialization
DoCmd.Maximize 'Maximizes the form when first initialized. Omit if required.
Call CenterControls
End Sub
Then this is where the magic happens.
Sub CenterControls()
'Find the control that has the farthest left position, and the one with the farthest right position.
'That will give us the total distance of our buttons. We will then have to compare that to the width of the form, and move our controls accordingly.
Dim Ctrl As Control
Dim ClosestLeft As Integer
Dim FurthestRight As Integer
Dim FurthestRightWidth As Integer
Dim GrandTotalWidth As Integer
Dim AmountToMove As Integer
Dim TypicalPosition As Integer
'Finds the furthest left position of all of our controls on the form.
For Each Ctrl In Me
If ClosestLeft > Ctrl.Left Or ClosestLeft = 0 Then
ClosestLeft = Ctrl.Left
End If
'Finds the furthest right control. Also takes the width of that furthest right control (necessary for the calculation)
If FurthestRight < Ctrl.Left Or FurthestRight = 0 Then
FurthestRight = Ctrl.Left
FurthestRightWidth = Ctrl.Width
End If
Next
'Now we find the grand total width of all of our controls. Furthest Right - Furthest Left + FurthestRightWidth
GrandTotalWidth = FurthestRight - ClosestLeft + FurthestRightWidth
'Finds the typical position of where the left side of the group of controls should sit on the form.
TypicalPosition = (Me.InsideWidth / 2) - (GrandTotalWidth / 2)
'Figures out the amount we'd have to move the group of controls to get them to sit in their typical position.
AmountToMove = TypicalPosition - ClosestLeft
For Each Ctrl In Me
If Not ClosestLeft + AmountToMove <= 0 Then
Ctrl.Left = Ctrl.Left + AmountToMove
End If
Next
End Sub
Now when you run your pop-up form, all the controls should be centered to the form as a group.