Search code examples
excelvbauserformmousedown

Detect mouse down event on dynamic objects in a userform


I have a dynamic range of OptionButtons within a frame in a Userform. The number of OptionButtons vary according to number of columns in a table. Each button is labeled according the column label. When a person selects an option I need a ListBox to be populated with the items found within that table column. Populating the option buttons and ListBox is easy enough. I know how to detect mouse down events on known Userformobjects. But the buttons exist only through coding and vary. How do I detect MouseDown on an object that doesn't actually exist? I have tried the code for creating a MouseDown Class for a Frame


Solution

  • You need to wrap your controls in a class module - say, DynamicOptionButton:

    Option Explicit
    Private WithEvents ControlEvents As MSForms.OptionButton
    
    Public Sub Initialize(ByVal ctrl As MSForms.OptionButton)
        If Not ControlEvents Is Nothing Then ThrowAlreadyInitialized
        Set ControlEvents = ctrl
    End Property
    
    Private Property Get AsControl() As MSForms.Control
        Set AsControl = ControlEvents
    End Property
    
    Private Sub ThrowAlreadyInitialized()
        Err.Raise 5, TypeName(Me), "Invalid Operation: This control is already initialized."
    End Sub
    
    Private Sub ControlEvents_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
        Dim parentForm As UserForm1 'todo: use your actual UserForm subtype
        Set parentForm = AsControl.Parent 
        'handle mousedown here.
    End Sub
    

    When you create the dynamic controls, you'll want a module-level Collection to hold the DynamicOptionButton instances - otherwise they'll go out of scope when End Sub is reached, and you'll never be able to handle any of their events.

    Private DynamicControls As Collection
    
    Private Sub Class_Initialize()
        Set DynamicControls = New Collection
        'todo invoke CreateOptionButton
    End Sub
    
    Private Sub CreateOptionButton() 'todo parameterize
        Dim ctrl As MSForms.OptionButton
        Set ctrl = Me.Controls.Add(...)
    
        Dim wrapper As DynamicOptionButton
        Set wrapper = New DynamicOptionButton
        wrapper.Initialize ctrl
    
        DynamicControls.Add wrapper
    End Sub