0

I am trying to link controls on a form that I have created in a Class Module and am having trouble getting it to work properly.

'Class Name is CustForm  

Option Explicit

Private WithEvents btnTest as CommandButton

Public Function showForm()  

    Dim tempForm as Form  
    Dim formName as String  
    Set tempForm = CreateForm  
    formName = tempForm.Name  
    Set btnTest = CreateControl(formName, 
    acCommandButton,acDetail,,,300,300,1000,500)
    Dim btnName As String  
    btnName = btnTest.Name  
    Docmd.RunCommand acCmdFormView  

End Function

Private Sub btnTest_Click()
    MsgBox "Test"
End Sub

In a separate form I create the object and call the showForm in a click event

Private Sub Command0_Click()
    Dim tstForm as CustForm
    set tstForm= New CustForm
    tstForm.showForm
End Sub

But nothing happens when I click the button created in the CustForm I have tried using a temporary CommandButton in the showForm and after the docmd.runcommand acCmdFormView

set btnTest = Forms(formName).Controls(btnName)

under the assumption that maybe the instance of the command button changes when the form goes to Form View. Again no joy.

However if I add this to the CustForm Class

Public Function init(lclBtn as CommandButton)
    set btnTest = lclBtn
    btnTest.OnClick = "[Event procedure]"
End Function

And then I delete the OnClick and add this code to the form's module

Option Explicit
Dim tester as CustForm

Private Sub Form_Open(Cancel as Integer)
    Set tester = new CustForm
    tester.init Me.Command0
End Sub

Then it fires the MsgBox when I click the button. But I need to be able to eventually build a form factory class that allows me to build forms for class objects dynamically and handle the events in the object class. I would rather not make a bunch of purpose built forms for each class and have the form instantiate the class. I want to do it the other way around. Class builds the form.

Can this be done?

1 Answer 1

0

As can be read in the documentation of the Form.HasModule property, there are two kinds of forms and reports: lightweight forms and reports that don't have a class module and don't support events, and full forms and reports that do have a class module and support events.

This means you still have to toggle this property for it to support events:

Private WithEvents btnTest as CommandButton

Public Function showForm()  
    Dim tempForm as Form  
    Dim formName as String  
    Set tempForm = CreateForm
    tempForm.HasModule = True
    formName = tempForm.Name  
    Set btnTest = CreateControl(formName, acCommandButton,acDetail,,,300,300,1000,500)
    btnTest.OnClick = "[Event Procedure]"
    Dim btnName As String  
    btnName = btnTest.Name  
    DoCmd.RunCommand acCmdFormView  
End Function

Private Sub btnTest_Click()
    MsgBox "Test"
End Sub

Do note that setting Form.HasModule modifies the VB Project part of the Access database (it adds a class module), and thus every time you do this, your database will need to be recompiled. Generally, you want to avoid that, as it might lead to problems.

Instead, I recommend having a single form with a module and all the controls you might want. Then, you can move around the controls, change their caption, and resize them, bind them to table fields, and set up event handlers, all without modifying the VB Project behind the database (note that you can't add controls to a full form or change the names of controls without modifying the VB Project).

Note that a second issue is the persistence of your class object. Currently, there are no references to the class so it's destroyed. You can easily make your class persist indefinitely by using code like this:

Private WithEvents btnTest as CommandButton
Private Myself As Object

Public Function showForm()
    Set Myself = Me 'Circular reference, object won't get destroyed until myself is set to nothing

For more information about gracefully handling classes with references to forms, you can see this answer by me. You should probably listen to the Form_Unload event and clean up when that occurs.

Sign up to request clarification or add additional context in comments.

1 Comment

Note that lightweight forms and reports without a class module actually can support events. Event handlers can call global VBA functions using the syntax =MyGlobalFunction(). You can also call macros.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.