VBA重绘Treeview时点击默认按钮触发MsgBox重复弹出问题咨询
问题根因
你当前的逻辑形成了递归调用链:
- 首次运行
TestUnloadUserform→加载窗体→用户点击Default按钮→卸载当前窗体→调用TestUnloadUserform→再次加载新窗体 - 每次调用
TestUnloadUserform都会在内存栈中保留当前过程的上下文,等最后一次窗体正常关闭后,所有栈中残留的TestUnloadUserform过程都会继续执行到MsgBox那行,所以点N次按钮就会多弹N次提示框。
最优解决方案:窗体内部实现重置逻辑
完全不需要卸载再重载窗体,把初始化Treeview勾选状态的逻辑抽成窗体公共方法,直接调用重置即可,代码改动最小也没有调用栈问题。
1. 调整窗体代码
Option Explicit ' 公共方法:重置Treeview节点为默认勾选状态 Public Sub ResetDefaultSelection() ' 把你原来SetupTestFrm里设置Treeview节点默认勾选的逻辑复制到这里 ' 例如遍历所有Nodes设置Checked属性为默认值,修改后Treeview会自动重绘,无需额外操作 End Sub Private Sub cmdDefaultSelect_Click() ' 直接调用重置方法,不需要卸载窗体 Call ResetDefaultSelection End Sub
2. 调整标准模块代码
Option Explicit Public Sub TestUnloadUserform() Dim frM As frmTest Set frM = SetupTestFrm() frM.Show vbModal If Not frM Is Nothing Then Set frM = Nothing End If MsgBox _ Prompt:="Test complete.", _ Buttons:=vbOKOnly + vbInformation, _ Title:="Great Job" End Sub Public Function SetupTestFrm() As frmTest Set SetupTestFrm = New frmTest ' 原来设置Treeview结构的逻辑保留 ' 初始化的时候直接调用一次重置方法加载默认勾选状态 Call SetupTestFrm.ResetDefaultSelection End Function
备选方案:必须卸载重载时用标记位控制
如果确有特殊需求必须重新实例化窗体,增加关闭标记判断是重置请求还是正常关闭,避免递归调用:
1. 调整窗体代码
Option Explicit ' 公共标记:判断用户点击的是重置按钮还是正常关闭 Public IsResetRequest As Boolean Private Sub cmdDefaultSelect_Click() IsResetRequest = True Unload Me End Sub ' 适配右上角叉号关闭的场景,避免误判 Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer) If CloseMode = vbFormControlMenu Then IsResetRequest = False End If End Sub
2. 调整标准模块代码
Option Explicit Public Sub TestUnloadUserform() Dim frM As frmTest Do Set frM = SetupTestFrm() frM.Show vbModal ' 拿到标记判断是要重置还是关闭 Dim isReset As Boolean isReset = frM.IsResetRequest Set frM = Nothing Loop While isReset ' 标记为重置就重新加载窗体,否则退出循环 MsgBox _ Prompt:="Test complete.", _ Buttons:=vbOKOnly + vbInformation, _ Title:="Great Job" End Sub Public Function SetupTestFrm() As frmTest Set SetupTestFrm = New frmTest ' 原来的Treeview初始化逻辑全部保留 End Function
内容的提问来源于stack exchange,提问作者SquirrelBait
相关产品推荐
相关产品推荐

