说明:
我知道 - 显示UserForms - 这是
的最佳做法QueryClose
)If CloseMode = vbFormControlMenu ...
Unload Me
,只是胆小的Me.Hide
指令
(在通过Cancel = True
).IsCancelled=True
)有用的链接
可以在https://rubberduckvba.wordpress.com/2017/10/25/userform1-show/找到一个出色的概述" UserForm1.Show?" 以及许多示例性的答案(对Mathieu Guindon来说也是 Mat' Mug 和RubberDuck)。
进一步选择(►编辑自2019年5月1日起)
1)模态UserForms的工作示例
据我了解 - 我确实尝试学习 - ,以下代码应该适用于模态 UF&#39>:
案例1a) ..对于UF实例使用局部变量,如常见:
Public Sub ShowFormA
Dim ufA As UserForm1
Set ufA = New UserForm1
' show userform
ufA.Show ' equivalent to: ufA.Show vbModal
' handle data after user okay
If Not ufA.IsCancelled Then
' do something ...
End If
' >> object reference destroyed expressly (as seen in some examples)
unload ufA
End Sub
案例1b) ..没有局部变量,但使用With New
代码块:
' ----------------------------------------------------------
' >> no need to destruct object reference expressly,
' as it will be destroyed whenever exiting the with block
' ----------------------------------------------------------
With New UserForm1
.Show ' equivalent to: ufA.Show vbModal
' handle data after user okay
If Not .IsCancelled Then
' do something ...
End If
End With
2)问题
使用 MODELESS UserForm实例会出现问题。
好的,with block方法(参见1b)应足以在x-iting之后销毁任何对象引用:
With New UserForm1
.Show vbModeless ' << show modeless uf
End With
如果我尝试,
Unload
表格如果在Show
指令后使用本地变量(例如&#34; ufA&#34;)进行了接受,所有代码行都将立即执行,原因正是表单是MODELESS:
3)问题
我如何处理a)正确报告的UserForm取消了MODELESS表单的调用代码以及b)如果使用局部变量(必要的?)卸载?
答案 0 :(得分:7)
事实上,我一直非常关注模态形式 - 因为这是最常用的。感谢您对该文章的反馈!
非模态形式的原则是相同的:只需扩展链接文章和here中粗略概述的模型 - 视图 - 演示者模式。
不同之处在于非模态形式需要转变范式:您不再响应预设的事件序列 - 而是需要响应某些异步事件可能在任何特定时间发生,或不发生。
让您的演示者类模块负责在模块级和UserForm
保持WithEvents
实例:
Option Explicit
Private WithEvents myModelessForm As UserForm1
演示者的Show
方法将Set
表单实例并显示它:
Public Sub Show()
'If Not myModelessForm Is Nothing Then
' myModelessForm.Visible = True 'just to ensure visibility & honor the .Show call
' Exit Sub
'End If
Set myModelessForm = New UserForm1
'...
myModelessForm.Show vbModeless
End Sub
您不希望表单实例在此处的过程是本地的,因此本地变量或 With
块可以&#39 ; t work:在你指的是之前,对象将超出范围。这就是为什么你在模块级别将实例存储在私有字段中的原因:现在,只要演示者实例的存在,表单就会存在。
现在,您需要制作表格&#34; talk&#34;对于演示者 - 最简单的方法是在UserForm1
代码隐藏中公开事件 - 例如,如果我们希望用户确认取消,我们会在事件中添加ByRef
参数,所以演示者中的处理程序可以将信息传递回事件源(即返回到表单代码):
Option Explicit
'...private fields, model, etc...
Public Event FormConfirmed()
Public Event FormCancelled(ByRef Cancel as Boolean)
'returns True if cancellation was cancelled by handler
Private Function OnCancel() As Boolean
Dim cancelCancellation As Boolean
RaiseEvent FormCancelled(cancelCancellation)
If Not cancelCancellation Then Me.Hide
OnCancel = cancelCancellation
End Function
Private Sub CancelButton_Click()
OnCancel
End Sub
Private Sub OkButton_Click()
Me.Hide
RaiseEvent FormConfirmed
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = VbQueryClose.vbFormControlMenu Then
Cancel = Not OnCancel
End If
End Sub
现在,演示者可以处理FormCancelled
事件:
Private Sub myModelessForm_FormCancelled(ByRef Cancel As Boolean)
'setting Cancel to True will leave the form open
Cancel = MsgBox("Cancel this operation?", vbYesNo + vbExclamation) = vbNo
If Not Cancel Then
' modeless form was cancelled and is now hidden.
' ...
Set myModelessForm = Nothing
End If
End Sub
Private Sub myModelessForm_FormConfirmed()
'form was okayed and is now hidden.
'...
Set myModelessForm = Nothing
End Sub
非模态形式通常 &#34; ok&#34;和&#34;取消&#34;按钮虽然。更确切地说,您已经暴露了许多功能,例如,提供了一些其他功能的模态对话框UserForm2
- 再次,您只是为它公开一个事件,并在演示者中处理它:
Public Event ShowGizmo()
Private Sub ShowGizmoButton_Click()
RaiseEvent ShowGizmo
End Sub
主持人说:
Private Sub myModelessForm_ShowGizmo()
With New GizmoPresenter
.Show
End With
End Sub
请注意,模式UserForm2
是单独的演示者类的关注点。
答案 1 :(得分:3)
我通常将无模式用户表单实例的生命周期与工作簿相关联,方法是将代码放在ThisWorkbook后面的那些行中:
Option Explicit
Private m_MyForm As UserForm1
Private Sub Workbook_BeforeClose(Cancel As Boolean)
If Not m_MyForm Is Nothing Then
Unload m_MyForm
Set m_MyForm = Nothing
End If
End Sub
Friend Property Get MyForm() As UserForm1
If m_MyForm Is Nothing Then
Set m_MyForm = New UserForm1
End If
Set MyForm = m_MyForm
End Property
然后,您可以使用例如
在整个代码中引用无模式代码ThisWorkbook.MyForm.Show vbModeless
等
答案 2 :(得分:3)
对于无模式窗体,请使用DoEvents以及自定义userform属性。
2.0.1.RELEASE
&#39; /用户表单
2.0.x