Пользовательская форма VBA запускается дважды при изменении .Caption

Я запускаю макрос VBA из SolidWorks. Форма удваивается как ввод для двух типов документов. В подпрограмме UserForm.Initialize я меняю имя Caption пользовательской формы в зависимости от того, какой тип документа открыт. Однако всякий раз, когда я это делаю, программа повторно запускает UserForm.Initialize, и когда все это делается, она продолжает с того места, где остановилась, фактически запустив дважды.

Кто-нибудь знает способ обойти это странное поведение? Я попытался поместить команду FormName.Caption в ее собственный Sub, но результат тот же.

Большое спасибо.


person Chris Day    schedule 25.07.2012    source источник
comment
Событие инициализации не должно происходить дважды. Вы выполнили код, чтобы убедиться, что обновление .caption вызывает повторение? Вы всегда можете переместить изменение заголовка в событие Activate. Технически это означало бы, что он будет отображаться с неправильной подписью, но время до его изменения будет почти неразличимо.   -  person Daniel    schedule 25.07.2012
comment
@DanielCook Но разве это не вызовет большего повторного запуска кода? (т.е. каждый раз, когда форма активируется/нажимается и выключается)   -  person Gaffi    schedule 25.07.2012
comment
Да, конечно. Но если бы вы сохранили заголовок в приватной строке для пользовательской формы, которая была определена во время события инициализации, практически не было бы накладных расходов. Но на самом деле я просто упомянул то, что может работать, не решая вашей проблемы. Вот почему я не указал это как ответ. :-)   -  person Daniel    schedule 25.07.2012


Ответы (2)


Я не могу воспроизвести проблему и не знаю, что такое SolidWorks, так что это может быть как-то связано с этим. Возможно, вы можете опубликовать вымышленный пример, который показывает, что Initialize вызывается дважды.

Я предполагаю, что это связано с автоматическим созданием экземпляров переменных. Когда вы используете UserForm1, вы создаете объектную переменную с именем UserForm1, которая указывает на объект, также называемый UserForm1. Это похоже на использование ключевого слова New в операторе Dim. Вы никогда не определяли UserForm1 (переменную), но это сделал VBA, и при первом использовании он создается автоматически.

Вы должны попытаться использовать ключевое слово Me при работе внутри модуля класса пользовательских форм (пользовательские формы — это классы, такие же, как и другие объекты, за исключением того, что они имеют элемент пользовательского интерфейса). В событии Initialize скажите

Me.Caption = "blah"

вместо

UserForm1.Caption = "blah"

Может быть (просто теория, которую я не смог доказать), что флаг, который устанавливается, чтобы сказать «Я указываю на реальный экземпляр», не установлен к тому времени, когда вы изменяете свойство Caption, и что используя переменную автоматического создания экземпляра UserForm1, вы принудительно создаете другой экземпляр.

Еще лучше, не используйте переменные с автоматическим созданием экземпляров, хотя они и удобны (и не используйте ключевое слово New в операторе Dim). Вы можете контролировать, когда ваши переменные создаются и уничтожаются, и это лучшая практика. Что-то подобное в стандартном модуле

Sub uftst()

    Dim uf As UserForm1

    Set uf = New UserForm1 'you control instantiation here

    'Now you can change properties before you show it
    uf.Caption = "blech"
    uf.Show

    Set uf = Nothing 'overkill, but you control destruction here

End Sub

Обратите внимание: если для свойства ShowModal установлено значение False, код будет продолжать выполняться, поэтому не уничтожайте переменную, если она выполняется без режима.

person Dick Kusleika    schedule 25.07.2012
comment
+1 за то, что полностью прав. Мне не нравится форматирование mini-Markdown, поэтому я публикую новый ответ, чтобы показать, как воспроизвести проблему. - person Daniel; 26.07.2012
comment
Потрясающе, это сработало. А так же спасибо за дополнительную информацию! - person Chris Day; 27.07.2012

Как предложил Дик, вы должны иметь возможность остановить такое поведение, убедившись, что используете me.caption вместо Userform1.caption.

Вот как вы можете воспроизвести проблему для тех, кому любопытно:

Создайте пользовательскую форму (Userform1), убедитесь, что для ShowModal установлено значение false, иначе вы не сможете это увидеть.

В модуле добавьте следующее:

Option Explicit
Sub ShowUserForm()
    Dim uf As UserForm1
    Set uf = New UserForm1
End Sub

В UserForm1 укажите следующий код:

Option Explicit
Private Sub UserForm_Initialize()
    UserForm1.Caption = "I'm UserForm1!" 'This will call the Initialize method of Userform1 not Me.
    Me.Caption = "I'm Me!" 
    Me.Show
End Sub

Запустите ShowUserForm. Теперь у вас есть две пользовательские формы с разными заголовками.

Между прочим, если у вас есть метод Initialize, как я показал, добавление Set uf = Nothing к подразделу ShowUserForm на самом деле не может закрыть ни одну из форм.

person Daniel    schedule 26.07.2012