T.M*_*.M. 7 excel vba excel-vba userform
介绍:
我知道 - 显示UserForms - 这是最好的做法
QueryCloseuserform代码(If CloseMode = vbFormControlMenu ...)Unload Me其中不做,只是一个胆小的Me.Hide指令(在阻止[x] -it和最终的自毁之后Cancel = True).IsCancelled=True) 有用的链接
一个出色的概述"UserForm1.Show?" 可以在https://rubberduckvba.wordpress.com/2017/10/25/userform1-show/ 以及许多示例性的SO答案中找到(thx到@ Mats'Mug和RubberDuck).
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
Run Code Online (Sandbox Code Playgroud)
情况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
Run Code Online (Sandbox Code Playgroud)
2)问题
使用MODELESS UserForm实例会出现问题.
好吧,with block方法(参见1b)应该足以在x-iting之后销毁任何对象引用:
With New UserForm1
.Show vbModeless ' << show modeless uf
End With
Run Code Online (Sandbox Code Playgroud)
如果我尝试,但是
Unload如果在Show指令后使用局部变量(例如"ufA")进行洗礼,则表格为所有代码行都将立即执行,因为表单是MODELESS的原因:
3)问题
我如何处理a)正确报告的UserForm取消了MODELESS表单的调用代码以及b)(必要的?)卸载如果使用局部变量?
确实,我已经将很多注意力集中在模态形式上-因为这是最常用的形式。感谢您对该文章的反馈!
但是,原理与非模式形式相同:只需在链接的文章和此处大致概述的Model-View-Presenter模式上进行扩展。
区别在于,非模态形式需要进行范式转换:您不再响应预设的事件序列-而是需要响应可能在任何给定时间发生的某些异步事件。
使您的presenter类模块负责UserForm在模块级别和以下位置保存实例WithEvents:
Option Explicit
Private WithEvents myModelessForm As UserForm1
Run Code Online (Sandbox Code Playgroud)
演示者的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
Run Code Online (Sandbox Code Playgroud)
你不想要的形式实例是本地这里的程序,所以局部变量或一个With块不能工作:对象将是范围从你的意思是它之前。这就是为什么将实例存储在模块级别的私有字段中的原因:现在,该窗体的寿命与presenter实例的寿命相同。
现在,您需要与演示者进行“交谈”形式-最简单的方法是在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
Run Code Online (Sandbox Code Playgroud)
现在演示者可以处理该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
Run Code Online (Sandbox Code Playgroud)
非模式形式通常不会有“确定”和“取消”按钮。相反,您将拥有许多功能,例如,其中一个功能会弹出一个模式对话框UserForm2,该对话框将执行其他操作-同样,您只需公开一个事件,然后在演示者中处理它:
Public Event ShowGizmo()
Private Sub ShowGizmoButton_Click()
RaiseEvent ShowGizmo
End Sub
Run Code Online (Sandbox Code Playgroud)
演示者去:
Private Sub myModelessForm_ShowGizmo()
With New GizmoPresenter
.Show
End With
End Sub
Run Code Online (Sandbox Code Playgroud)
请注意,模式UserForm2是单独的presenter类的关注点。
| 归档时间: |
|
| 查看次数: |
3391 次 |
| 最近记录: |