Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations bkrike on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Add event to dynamic control

Status
Not open for further replies.

MisterC

IS-IT--Management
Apr 19, 2001
501
US
This is driving me crazy. I have added a command button to a form dynamically. The question is, how do I add a click event for that button?????
Code:
Set btnObj = Controls.Add("VB.CommandButton", "btnObj")
    With btnObj
        .Visible = True
        .Caption = "New Button"
        .Left = 240
        .Top = 480
        .Height = 240
    End With
Your help is greatly appreciated!
 
When you declare btnObj declare it with WithEvents

dim WithEvents btnObj as CommandButton

HTH

-Engi
 
Ok, then what?
Lets say I wanted to display a messagebox with the contents of that particular button's tag property?
 
Code:
Dim WithEvents btnObj As CommandButton
Private Sub AddButton()

Set btnObj = Controls.Add("VB.CommandButton", "btnObj")
    With btnObj
        .Visible = True
        .Caption = "New Button"
        .Left = 240
        .Top = 480
        .Height = 240
    End With
End Sub
Private Sub btnObj_Click()
 MsgBox "Hello"
End Sub
 
Yes but you have hard-coded the event. I want to add the event dynamically.
 
Please throw some light as what "event" you are talking about? Is it not among the native events to the button?
 
a button_click event is basicall the same as "btnObj.value=true"

Maybe you can trap that value?

_______
I love small animals, especially with a good brown gravy....
 
Is there some reason you prefer using the controls.add method instead of using a control array and adding to it?

Robert
 
No reason. Actually that appears to be the best way to handle it. I'll use a generic button click procedure that looks at the individual button's tag property to determine what to do.

Thanks all for your help.
 
Or even the button's Index property....

________________________________________________________________
If you want to get the best response to a question, please check out FAQ222-2244 first

'If we're supposed to work in Hex, why have we only got A fingers?'

for steam enthusiasts
 
This is how its done:

Step 1. Add a new class module name it clsControl
Step 2. Add the following code

Code:
'Public Property Variables
Private mobjInterface As IControl
Private miIndex As Integer
Private msArrayID As String
Private meControlType As ControlTypes

'A list of controls that require support
Private WithEvents mobjButton As CommandButton
Private WithEvents mobjTBox As TextBox

'The types of controls above
Public Enum ControlTypes
   ctInvalidType
   ctTextBox
   ctCommandButton
End Enum

'Remaining declarations are for GUID creation (AddControl Method)
Private Type GUID
   Data1 As Long
   Data2 As Integer
   Data3 As Integer
   Data4(0 To 7) As String * 1
End Type

Private Declare Function CoCreateGuid _
                Lib "ole32.dll" (tGUIDStructure As GUID) As Long
Private Declare Function StringFromGUID2 _
                Lib "ole32.dll" (rguid As Any, _
                                 ByVal lpstrClsId As Long, _
                                 ByVal cbMax As Long) As Long

Public Function AddControl(ByRef Frm As Form, _
                           ByRef CInterface As IControl, _
                           ByVal ControlType As ControlTypes, _
                           Optional ByVal ArrayName As String, _
                           Optional ByVal Index As Integer = -1, Optional Container As Control) As Control
   Static bHere As Boolean
   
   If Not bHere Then
      bHere = True
      
      Set mobjInterface = CInterface
      
      msArrayID = ArrayName
      miIndex = Index
      
      Select Case ControlType
         Case ControlTypes.ctTextBox
            If Container Is Nothing Then
            Set mobjTBox = Frm.Controls.Add("VB.TextBox", "c" & GenateID)
            Else
            Set mobjTBox = Frm.Controls.Add("VB.TextBox", "c" & GenateID, Container)
            End If
            meControlType = ctTextBox
            Set AddControl = mobjTBox
            
         Case ControlTypes.ctCommandButton
            If Container Is Nothing Then
            Set mobjButton = Frm.Controls.Add("VB.CommandButton", "c" & GenateID)
            Else
            Set mobjButton = Frm.Controls.Add("VB.CommandButton", "c" & GenateID, Container)
            End If
            meControlType = ctCommandButton
            Set AddControl = mobjButton
         
         Case Else
            meControlType = ctInvalidType
            Err.Raise 13
      End Select
   Else
      'Since this method can only be called once, raise an error
      Err.Raise 360, "AddControl", "Object Already Loaded"
   End If
   
End Function

Public Property Get ArrayID() As String
   ArrayID = msArrayID
End Property

Public Property Get ButtonObject() As CommandButton
   'Allows direct access to the commandbutton object
   Set ButtonObject = mobjButton
End Property

Public Property Get ControlObject() As Control
   'This property gives a way to get generic
   'control information without knowing
   'the type of control
   Select Case meControlType
      Case ctCommandButton
         Set ControlObject = mobjButton
      Case ctTextBox
         Set ControlObject = mobjTBox
   End Select
End Property

Public Property Get TextBoxObject() As TextBox
   'Allows direct access to the textbox object
   Set TextBoxObject = mobjTBox
End Property

Public Property Get ControlType() As ControlTypes
   ControlType = meControlType
End Property

Public Property Get Index() As Integer
   Index = miIndex
End Property

'Overhead code
Private Function GenateID() As String

   Const clLen As Long = 50

   Dim sGUID   As String       'store result here
   Dim tGUID   As GUID         'get into this structure
   Dim bGuid() As Byte         'get formatted string here
   Dim lRtn    As Long

   If CoCreateGuid(tGUID) = 0 Then                             'use API to get the GUID
      bGuid = String(clLen, 0)
      lRtn = StringFromGUID2(tGUID, VarPtr(bGuid(0)), clLen)  'use API to
      'Format it
      If lRtn > 0 Then                                        'truncate nulls
         sGUID = Mid$(bGuid, 1, lRtn - 1)
      End If
      'Strip extra stuff off of the GUID
      sGUID = Replace(sGUID, "{", "")
      sGUID = Replace(sGUID, "}", "")
      sGUID = Replace(sGUID, "-", "")
      GenateID = sGUID
   End If

End Function

Private Sub Class_Terminate()
   Set mobjButton = Nothing
   Set mobjTBox = Nothing
End Sub

'*************************************
'*****Command Button Events
'*************************************
Private Sub mobjButton_Click()
   Call mobjInterface.Click(Me)
End Sub

Private Sub mobjButton_GotFocus()
   Call mobjInterface.GotFocus(Me)
End Sub

Private Sub mobjButton_LostFocus()
   Call mobjInterface.LostFocus(Me)
End Sub

'*************************************
'*****Textbox Events
'*************************************
Private Sub mobjTBox_Change()
   Call mobjInterface.Change(Me)
End Sub

Private Sub mobjTBox_GotFocus()
   'Do some stuff to the control before running code in the form
   mobjTBox.BackColor = RGB(Rnd * 127, Rnd * 127, Rnd * 127)
   mobjTBox.ForeColor = vbWhite
   Call mobjInterface.GotFocus(Me)
End Sub

Private Sub mobjTBox_LostFocus()
   'Do some stuff to the control before running code in the form
   mobjTBox.BackColor = vbWindowBackground
   mobjTBox.ForeColor = vbWindowText
   Call mobjInterface.LostFocus(Me)
End Sub


Step 3: Add a second class module, name it IControl
Step 4: Paste the following code into it

Code:
Public Sub Change(ByVal EvtSource As clsControl)
   '
End Sub

Public Sub Click(ByVal EvtSource As clsControl)
   '
End Sub

Public Sub GotFocus(ByVal EvtSource As clsControl)
   '
End Sub

Public Sub LostFocus(ByVal EvtSource As clsControl)
   '
End Sub


step 5. Add a new form, in the declarations area paste the following code

Code:
Private mobjBut1Array() As clsControl
'Implements the control interface
Implements IControl

step 5. Add the following code to the form load event

Code:
'Instantiate the class
Set mobjBut1Array(0) = New clsControl

'Add the control to the form
Set cmd = mobjBut1Array(0).AddControl(Me, Me, ctCommandButton, "cmd", 0)
    
'Set cmd = Controls.Add("VB.CommandButton", "cmd" & iNoMessages, picMessage(0))
    cmd.Top = 1740
    cmd.Height = 255
    cmd.Width = 1065
    cmd.Left = 3405
    cmd.Caption = "Quote"

step 6. In the objects listbox in the VB IDE select IControl, then in the events listbox select the click event

step 7. Paste the following code

Code:
Private Sub IControl_Click(ByVal EvtSource As clsControl)


Msgbox "Hello World, I'm Back!!"

End Sub

Step 7. Thank Me!
 
Jakos: Wow that's a lot of coding. Thanks, but it still doesn't do what I had intended - You hard coded the IControl_Click event. What I was looking for was something like:

NewButton.AddEvent (Click, strEventText)
where strEventText is the actual code to run for the Click Event. (...but I guess I was dreaming.)

But I did solve the problem:
To put it in context, I have a disk with a multitude of application installation files on it, and I wanted a simple menu program that would have a button to launch each installation. I wanted to be able to configure the menu program on the fly to handle installation files and/or directory changes, so I wanted to be able to dynamically add buttons and commands.

My solution was to use a control array and a generic Click event that looks at the appropriate button's tag to determine what to do. When the menu app is loaded, it looks at a text file to get a list of buttons and their commands (and a few other odds and ends settings). It then adds the buttons dynamically to the form. When each button is clicked, it executes whatever command was loaded (into the button's tag event) from the text file.

It seems to work like a charm!
Thanks to everyone for your help.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top