João Pedrosa
João Pedrosa

Reputation: 31

What's wrong with UserForm.Caption?

Can someone experienced with VBA coding please explain this madness!

Dim thisForm As MSForms.UserForm

Set thisForm = ACADProject.FormENU 
'FormENU is user form I have, with some controls in it, 
'with a little piece of data in the caption so that it's visible
'when the form is shown

'When I do this
Debug.Print thisForm.Caption
'I get ""

'When I do this
Debug.Print thisForm.Controls(1).Parent.Caption
'I get the actual caption of the Form

Why does thisForm not know its caption before I ask it to one of its controls? I'm executing this from a command button in the form that calls a procedure nested in a module

Upvotes: 2

Views: 401

Answers (1)

GSerg
GSerg

Reputation: 78134

It would appear that this is due to a bug where the base class'es property is not properly mapped to the child class property!

ACADProject.FormENU inherits from MSForms.UserForm. It has much more properties and methods than MSForms.UserForm, but it is a MSForms.UserForm, hence it can be stored in a variable of type MSForms.UserForm.

It would appear that internally MSForms.UserForm and its subclasses (the actual user forms designed by users) are implemented as different objects where the properties of the base dummy object return whatever the properties of the actual derived object return (which makes it look more of a has-a from the link above than of an is-a).
And it would appear that whoever mapped all the properties of MSForms.UserForm to return the respective values of the actual subclass, forgot to map the Caption property:

Dim FormAsSelf As UserForm1
Dim FormAsForm As MSForms.UserForm
Dim FormAsObject As Object

Set FormAsSelf = New UserForm1
Set FormAsForm = FormAsSelf
Set FormAsObject = FormAsSelf

Debug.Print "Caption from self: ", FormAsSelf.Caption, TypeName(FormAsSelf), ObjPtr(FormAsSelf), TypeOf FormAsSelf Is UserForm1
Debug.Print "Caption from form: ", FormAsForm.Caption, TypeName(FormAsForm), ObjPtr(FormAsForm), TypeOf FormAsForm Is UserForm1
Debug.Print "Caption from object: ", FormAsObject.Caption, TypeName(FormAsObject), ObjPtr(FormAsObject), TypeOf FormAsObject Is UserForm1

Unload FormAsSelf
Title Caption Type name Object address Is a UserForm?
Caption from self: UserForm1 UserForm1 4144272 True
Caption from form: UserForm1 96261568 True
Caption from object: UserForm1 UserForm1 4144272 True

The other properties appear to be mapped correctly, so if you design a form with a pink background and request .BackColor instead of .Caption in the code above, you will get the same answer from all three (actually two) "sides" of the form:

Title BackColor Type name Object address Is a UserForm?
Caption from self: 16744703 UserForm1 4144272 True
Caption from form: 16744703 UserForm1 96261568 True
Caption from object: 16744703 UserForm1 4144272 True

As noted in a comment under a related question, this entire inheritance situation is similar to the relationships between Sheet1 and Worksheet. Those, however, appear to be implemented differently internally, so there is only one "side" to begin with:

Dim SheetAsSelf As Sheet1
Dim SheetAsSheet As Excel.Worksheet
Dim SheetAsObject As Object

Set SheetAsSelf = ThisWorkbook.Worksheets(1)
Set SheetAsSheet = SheetAsSelf
Set SheetAsObject = SheetAsSelf

Debug.Print "Caption from self: ", SheetAsSelf.Name, TypeName(SheetAsSelf), ObjPtr(SheetAsSelf), TypeOf SheetAsSelf Is Sheet1
Debug.Print "Caption from sheet: ", SheetAsSheet.Name, TypeName(SheetAsSheet), ObjPtr(SheetAsSheet), TypeOf SheetAsSheet Is Sheet1
Debug.Print "Caption from object: ", SheetAsObject.Name, TypeName(SheetAsObject), ObjPtr(SheetAsObject), TypeOf SheetAsObject Is Sheet1
Title Name Type name Object address Is a Sheet1?
Caption from self: Sheet1 Worksheet 463669552 True
Caption from sheet: Sheet1 Worksheet 463669552 True
Caption from object: Sheet1 Worksheet 463669552 True

(Although, if you dig deep enough, you will find that Worksheets are into even crazier shenanigans!)

Upvotes: 4

Related Questions