Control Arrays (1 Viewer)

ddcessex

Registered User.
Local time
Yesterday, 22:41
Joined
Jan 14, 2016
Messages
23
In days gone by you could use a wonderful object called the Control Array in VB.

This would you allow you to, say, have 30 buttons on the form all called "Command" but indexed from 0 to 29.

This meant that you could trap any event for all 30 buttons with one procedure (eg: Sub Command_Click(Index) ) for each event.

Can anyone tell me how to emulate this in Access VBA?

Thanks
 

CJ_London

Super Moderator
Staff member
Local time
Today, 06:41
Joined
Feb 19, 2013
Messages
16,612
write a public function in a module (called say btnClick)

note that in the function you refer to the button as screen.activecontrol

then in your form, highlight all the buttons and type into the click event (where you would normally see '[event procedure]')

=btnClick()
 

MarkK

bit cruncher
Local time
Yesterday, 22:41
Joined
Mar 17, 2004
Messages
8,181
You can also set this programmatically by setting the OnClick property of the control, so if you have 30 command buttons and you want to Assign each one to call a function AND pass ITSELF into that function, do . . .
Code:
dim cmd as Access.CommandButton
dim name as string

for i = 0 to 29
   name = "cmd" & i
   me.controls(name).OnClick = "=CommandClick([" & name & "])"
next
And the function that will be called . . .
Code:
Function CommandClick(cmd as Access.CommandButton)
In this way you can programmatically alter or remove event handling in VBA.
 

ddcessex

Registered User.
Local time
Yesterday, 22:41
Joined
Jan 14, 2016
Messages
23
write a public function in a module (called say btnClick)

note that in the function you refer to the button as screen.activecontrol

then in your form, highlight all the buttons and type into the click event (where you would normally see '[event procedure]')

=btnClick()

OH Thank you so much!

It took a little sorting but eventually got this to work - this is so helpful, thank you.

You showed me two things: first the structure of how to trap an event for multiple objects and secondly that one can set the event of more than one object at a time.

I will use this in many of my forms and will always be indebted to you.

THANK YOU

Raymond
 

MarkK

bit cruncher
Local time
Yesterday, 22:41
Joined
Mar 17, 2004
Messages
8,181
Wow, very kind words. Glad to be able to help,
 

ddcessex

Registered User.
Local time
Yesterday, 22:41
Joined
Jan 14, 2016
Messages
23
write a public function in a module (called say btnClick)

note that in the function you refer to the button as screen.activecontrol

then in your form, highlight all the buttons and type into the click event (where you would normally see '[event procedure]')

=btnClick()

CJ This is so great and thanks again. I have a question which is puzzling me...

OK so I'm trapping the click event on multiple objects and would like to pass a property of the control that was actually clicked (the Tag property to be precise) to the function somewhat in the fashion...

=btnClick(TheButtonClicked.Tag)

A guru answer would be much appreciated.

Thanks in advance

ps. The objective is simple in that I am trapping the click event of each of the Field Labels in a continuous form where the labels are placed in the Header and the Fields are placed in the Detail. I'm trying to devise a simple interface whereby the user can identify which column is to be used when he later wishes to find records in that column. Each label has it's Tag property set so that the module function can decide what to do when a particular label is clicked - hope this makes sense
 

CJ_London

Super Moderator
Staff member
Local time
Today, 06:41
Joined
Feb 19, 2013
Messages
16,612
you either pass the control as suggested by mark or use the screen.activecontrol object

so within your btnclick code

dim mystr as string
mystr=screen.activecontrol.tag
 

ddcessex

Registered User.
Local time
Yesterday, 22:41
Joined
Jan 14, 2016
Messages
23
Just a short note to thank you guys for tirelessly helping others.

I have been developing for some 16 years and never known how helpful your responses are.

A BIG THANK YOU on behalf of myself and all others who are busy learning and don't have the time with thanks
 

wengang1

New member
Local time
Today, 01:41
Joined
Nov 3, 2022
Messages
2
Hi. I see that this was over 6 years ago, but I stumbled across it today. I have successfully used the solution posted by MarkK before ( me.controls(name).OnClick = "=CommandClick([" & name & "])"). But now I'm stumped. I need to do a MouseUp event on the array items and capture which Button was clicked. The normal click/mouseup event would tell which button, but by sending the event to a function, how/where do I insert the part that captures which Button was clicked? I don't think I can just pass Button to the function as a parameter because it wouldn't mean anything (it would be a null value). Thanks for any help here.
 

theDBguy

I’m here to help
Staff member
Local time
Yesterday, 22:41
Joined
Oct 29, 2018
Messages
21,473
Hi. I see that this was over 6 years ago, but I stumbled across it today. I have successfully used the solution posted by MarkK before ( me.controls(name).OnClick = "=CommandClick([" & name & "])"). But now I'm stumped. I need to do a MouseUp event on the array items and capture which Button was clicked. The normal click/mouseup event would tell which button, but by sending the event to a function, how/where do I insert the part that captures which Button was clicked? I don't think I can just pass Button to the function as a parameter because it wouldn't mean anything (it would be a null value). Thanks for any help here.
Hi. Welcome to AWF!

Consider posting a sample db to demonstrate the problem.
 

CJ_London

Super Moderator
Staff member
Local time
Today, 06:41
Joined
Feb 19, 2013
Messages
16,612
The normal click/mouseup event would tell which button, but by sending the event to a function, how/where do I insert the part that captures which Button was clicked?
I don't believe you can use that method, you would need to create a class and assign the button to it.

@MajP is our expert on classes - he has probably posted an example somewhere

Just found this which may be of help
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 01:41
Joined
May 21, 2018
Messages
8,529
I actually have an example where I trap a couple hundred image controls, mouse move, mouse up, mouse down. The problem is that it is inside a very complicated form. Something I doubt you seen done in Access before. This form allows you to "dynamically" place images on a form and drag and drop them into position. Supposed to allow you to create restaurant floor layouts.
If I have time I will chop this down to be a generic "control array".
If @wengang1 you post your db, I can provide a "less generic" solution to solve your problem. It takes a lot more time to make a generic solution that works for all cases.

See example of trapping the mouse events in a class, but as I said it is hard to see how that works since there is so much other code to do other things in the form.
 

CJ_London

Super Moderator
Staff member
Local time
Today, 06:41
Joined
Feb 19, 2013
Messages
16,612
Actually, thinking about it, I have a class for providing some datasheet functionality to a continuous form (primarily move and resize columns), a .accde example here

I'll see if I can strip out the relevant parts tomorrow
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 01:41
Joined
May 21, 2018
Messages
8,529
Here is a control Array. I only coded it to handle Labels and Textboxes and to handle Mouse Move, Mouse Up, and Mouse Down. If you want more types of controls and more types of event, you have to add more repetitive code in the class. Unfortunately access requires you to repeat the code for each type of control.

You declare a variable of ControlArray then load it with your controls. Then you can trap the events of the ControlArray.

Code:
'Declare a variable
Private WithEvents CA As ControlArray

'Load your controls
Private Sub Form_Load()
  Dim ctl As Access.Control
  Set CA = New ControlArray
  For Each ctl In Me.Controls
    If ctl.Tag = "CA" Then
      CA.Add ctl
    End If
  Next ctl
End Sub
'-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
'---------------------------------------------------------------------------- Trap the Array Events ---------------------------------------------------------------------------------


Private Sub CA_MouseDown(ControlItem As Control, Button As Integer, Shift As Integer, x As Single, y As Single)
  MsgBox "Mouse down from control: " & ControlItem.Name & " Button: " & Button & " Shift: " & Shift & " X: " & x & " Y: " & y
End Sub

Private Sub CA_MouseMove(ControlItem As Control, Button As Integer, Shift As Integer, x As Single, y As Single)
  Debug.Print "Mouse Move from control: " & ControlItem.Name & " Button: " & Button & " Shift: " & Shift & " X: " & x & " Y: " & y
End Sub

Private Sub CA_MouseUp(ControlItem As Control, Button As Integer, Shift As Integer, x As Single, y As Single)
   MsgBox "Mouse up from control: " & ControlItem.Name & " Button: " & Button & " Shift: " & Shift & " X: " & x & " Y: " & y
End Sub

FYI, I call it control array, but it is really a custom collection.
 
Last edited:

MajP

You've got your good things, and you've got mine.
Local time
Today, 01:41
Joined
May 21, 2018
Messages
8,529
I have updated the above class to create a "Control Array" that handles MouseUp, MouseDown, MouseMove, KeyUp, KeyDown, KeyPress. Works for labels and textboxes. These are the important events I can think of because they have returned parameters that you usually need to work with.
Keycode, button, shift, x, y, keyascii
The normal solution as others previously mentioned for building a single function as an event handler does not work in this case.
If you want to handle additional controls or events you unfortunately need to replicated the code within the class for each type of control. This is because you cannot trap events of a generic access control because a generic Control exposes no events. Events are defined in the subclasses for each specific control type.

Again, this is only needed in the cases where the event is parameterized. If not simply build a common function.
 

Attachments

  • MajP_ControlArrayV2.accdb
    536 KB · Views: 89

arnelgp

..forever waiting... waiting for jellybean!
Local time
Today, 13:41
Joined
May 7, 2009
Messages
19,243
i also found
But now I'm stumped. I need to do a MouseUp event on the array items and capture which Button was clicked.
i found a simple code, does not need for a custom Class.
but this time using MouseDown event.
 

Attachments

  • Mouse_Click.accdb
    560 KB · Views: 86
Last edited:

Users who are viewing this thread

Top Bottom