简介:
我知道--向UserForms展示--这是最好的做法
QueryClose )中处理QueryCloseUnload Me,只是一个胆小的Me.Hide指令(在防止x-腐蚀和最终通过Cancel = True自毁之后)。.IsCancelled=True)有用链接
杰出的概述"UserForm1.Show?“可以在https://rubberduckvba.wordpress.com/2017/10/25/userform1-show/找到,也可以在众多的例子中找到,所以答案(thx到Mathieu,Guindon,aka,Mat's Mug和RubberDuck)。
进一步选择(►编辑自2019年5月1日起)
1)模态UserForms的工作示例
据我所理解- -而且我确实试图学习-下面的代码对于UF来说应该是可以的:
案例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 With2)问题
使用MODELESS UserForm实例会出现问题。
好的,with块方法(参见。1b)应足以在x处理后销毁任何物体参考资料:
With New UserForm1
.Show vbModeless ' << show modeless uf
End With但是,如果我试着
Unload指令之后使用局部变量(例如"ufA")洗礼表单,由于表单为MODELESS,所有代码行都将同时执行:
3)问题
如何处理由MODELESS窗体的调用代码正确报告的UserForm取消,以及( b) a(必要)如果使用局部变量,则卸载?
发布于 2017-11-17 20:22:18
事实上,我一直非常关注模态形式,因为这是最常用的。谢谢你对那篇文章的反馈!
但是,对于非模态形式,原则是相同的:简单地扩展模型-视图-演示者模式,在链接文章和这里中大致概述。
不同之处在于,非模态形式需要一个范式转变:您不再响应预先设定的事件序列,而是需要响应某些可能在任何给定时间发生的异步事件,或者不响应。
让演示者类模块负责在模块级和WithEvents级别上保存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您的不希望表单实例是本地的,因此局部变量或a With块无法工作:对象将超出作用域,然后才是真正的对象。这就是为什么在模块级别将实例存储在私有字段中的原因:现在表单与演示者实例一样存在。
现在,您需要对演示者进行表单"talk“--最简单的方法是在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非模态形式通常不会有"ok“和"cancel”按钮。相反,您将公开一些功能,例如,一个弹出一些模式对话框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是一个单独的演示者类的关注点。
发布于 2017-11-17 19:25:42
我通常将非模态用户表单实例的生存期绑定到工作簿的生存期,方法是将代码放在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等。
发布于 2017-11-17 19:35:38
对于无模式表单,请使用DoEvents与自定义userform属性耦合。
Sub test()
Dim frm As New UserForm1
frm.Show vbModeless
Do
DoEvents
If frm.Cancelled Then
Unload frm
Exit Do
End If
Loop Until False
MsgBox "You closed the modeless form."
'/ Using With
With New UserForm1
.Show vbModeless
Do
DoEvents
If .Cancelled Then Exit Do
Loop Until False
End With
MsgBox "You closed the modeless form (with)"
End Sub'/用户表单
Private m_bCancelled As Boolean
Public Property Get Cancelled() As Boolean
Cancelled = m_bCancelled
End Property
Public Property Let Cancelled(ByVal bNewValue As Boolean)
m_bCancelled = bNewValue
End Property
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
Me.Cancelled = True
Cancel = 1
Me.Hide
End Subhttps://stackoverflow.com/questions/47357708
复制相似问题