Windows Forms重复打开子窗体时MaskedTextBox下划线消失问题
问题产生原因
- 你使用
ShowDialog打开的是模态窗体,这类窗体的标准关闭逻辑是通过设置DialogResult属性触发关闭,直接设置Me.Visible = False只是隐藏窗体,没有完成模态窗体的关闭生命周期,窗体的状态残留会导致下次打开时重绘逻辑异常。 - MaskedTextBox的输入下划线属于控件初始化时通过GDI绘制的掩码提示元素,隐藏窗体再重新调用
ShowDialog时,控件不会重新走初始化绘制流程,下划线就会丢失。 - 你当前的打开逻辑存在错误:
If Me._clsfrmChild.ShowDialog = False这行代码会直接触发窗体显示,判断返回值后再次调用ShowDialog属于冗余逻辑,也会加剧控件状态异常的概率。
解决方案
场景1:不需要保留子窗体的历史输入,每次打开都是全新状态
这是最推荐的方案,直接每次打开都实例化新的子窗体,避免所有状态残留问题,修改两处代码即可:
- 主窗体的打开逻辑,删除全局的
_clsfrmChild变量,改用Using块自动释放资源:
Private Sub btnSearchUser_Click(sender As Object, e As EventArgs) Handles btnSearchUser.Click ' 若需要传递主窗体的参数,可在实例化后赋值给子窗体的公共属性 Using _clsfrmChild As New clsFrmChild _clsfrmChild.ShowDialog(Me) End Using End Sub
- 子窗体的关闭逻辑,替换Visible设置为标准模态窗体关闭逻辑:
Private Sub btnAbort_Click(sender As Object, e As EventArgs) Handles btnAbort.Click Me.DialogResult = DialogResult.Cancel End Sub
场景2:必须复用同一个子窗体实例,保留历史输入
如果确实需要保留子窗体之前填写的内容,不想每次重新创建,按以下步骤修改:
- 同样先修改子窗体的关闭逻辑为标准模态关闭,不要使用Visible隐藏:
Private Sub btnAbort_Click(sender As Object, e As EventArgs) Handles btnAbort.Click Me.DialogResult = DialogResult.Cancel End Sub
- 给子窗体添加
Shown事件,每次窗体显示时强制所有MaskedTextBox重绘,恢复下划线:
Private Sub clsFrmChild_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown For Each ctrl As Control In Me.Controls If TypeOf ctrl Is MaskedTextBox Then CType(ctrl, MaskedTextBox).Refresh() End If ' 若MaskedTextBox放在Panel等容器内,需要递归遍历容器内的控件 Next End Sub
- 修正主窗体的打开逻辑,删除冗余的二次ShowDialog调用:
Private Sub btnSearchUser_Click(sender As Object, e As EventArgs) Handles btnSearchUser.Click If Me._clsfrmChild Is Nothing Then Me._clsfrmChild = New clsFrmChild End If Me._clsfrmChild.ShowDialog(Me) End Sub
内容的提问来源于stack exchange,提问作者Lionel Ronaldo
相关产品推荐
相关产品推荐

