Что не так с UserForm.Caption?

Может кто-нибудь, кто имеет опыт кодирования VBA, объясните это безумие!

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

Почему thisForm не знает своего заголовка до того, как я задам его одному из его элементов управления? Я выполняю это с помощью командной кнопки в форме, которая вызывает процедуру, вложенную в модуль.


person João Pedrosa    schedule 29.01.2021    source источник
comment
Вы уверены, что это vba, который используется в Excel, Word и других офисных продуктах, а не VB.net, который используется в Visual Studio?   -  person Scott Craner    schedule 29.01.2021
comment
Возможно, нет, но можно воспроизвести подобное поведение в Excel.   -  person Storax    schedule 29.01.2021
comment
Это происходит из-за Dim thisForm As MSForms.UserForm и исправлено Dim thisForm As ACADProject.FormENU, но я не знаю почему. неявное создание экземпляра формы не является виновником, поскольку то же самое поведение воспроизводится с правильным Set thisForm = New ACADProject.FormENU.   -  person GSerg    schedule 29.01.2021
comment
Нет, это происходит из-за Dim thisForm As MSForms.UserForm.   -  person Storax    schedule 29.01.2021
comment
Отвечает ли это на ваш вопрос? Разница между объявлением пользовательской формы как объекта и MSForms.Userform?   -  person Storax    schedule 29.01.2021
comment
@Storax Это связано, но я бы не назвал это дубликатом. Здесь у нас есть различное наблюдаемое поведение при использовании UserForm.Caption и UserForm1.Caption вне одного и того же фактического экземпляра формы. У обоих есть Caption в интеллектуальном смысле.   -  person GSerg    schedule 29.01.2021
comment
@ScottCraner Да, это VBA.   -  person GSerg    schedule 29.01.2021


Ответы (1)


Похоже, что это связано с ошибкой, из-за которой свойство базового класса неправильно отображается на свойство дочернего класса!

ACADProject.FormENU наследуется от MSForms.UserForm. У него гораздо больше свойств и методов, чем у MSForms.UserForm, но он является MSForms.UserForm, поэтому он может храниться в переменной типа MSForms.UserForm.

Может показаться, что внутри MSForms.UserForm и его подклассы (фактические пользовательские формы, разработанные пользователями) реализованы как разные объекты, в которых свойства базового фиктивного объекта возвращают те же свойства, что возвращают свойства фактического производного объекта (что делает его более похожим на < em>has-a из ссылки выше, чем is-a).
И может показаться, что тот, кто сопоставил все свойства MSForms.UserForm, чтобы вернуть соответствующие значения фактический подкласс, забыл отобразить свойство Caption:

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

Другие свойства отображаются правильно, поэтому, если вы создадите форму с розовым фоном и запросите .BackColor вместо .Caption в приведенном выше коде, вы получите одинаковый ответ со всех трех (на самом деле двух) сторон формы:

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

Как отмечено в комментарии под связанный с этим вопрос, вся эта ситуация с наследованием похожа на отношения между Sheet1 и Worksheet. Однако они, по-видимому, реализованы по-разному внутри, поэтому для начала есть только одна сторона:

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

(Хотя, если вы копнете достаточно глубоко, вы обнаружите, что рабочие листы даже в более безумных махинациях!)

person GSerg    schedule 29.01.2021