在WinForms应用程序中将按钮样式设置为FlatStyle.System时发生System.ObjectDispos

本文关键字:System FlatStyle ObjectDispos 设置 应用程序 WinForms 样式 按钮 | 更新日期: 2023-09-27 18:24:26

System.ObjectDisposedException当WinForms应用程序中的按钮样式设置为FlatStyle.System

我有一个子窗体,它在单击父窗体中的按钮时显示。代码如下所示。

Public Class Parent
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    End Sub
    Private Sub btnOpenChild_Click(sender As Object, e As EventArgs) Handles btnOpenChild.Click
        Child.Show()
    End Sub
End Class

子窗体又有一个关闭自身的按钮。

Public Class Child
    Private Sub btnCloseMe_Click(sender As Object, e As EventArgs) Handles btnCloseMe.Click
        Me.Close()
    End Sub
End Class

获取异常的步骤:

  • 在调试模式下,在Me.Close()上设置一个断点
  • 然后单击子项的关闭按钮
  • 点击断点打开记事本
  • 回到解决方案,然后继续

例外:

System.ObjectDisposedException was unhandled
  HResult=-2146232798
  Message=Cannot access a disposed object.
Object name: 'Button'.
  Source=System.Windows.Forms
  ObjectName=Button
  StackTrace:
       at System.Windows.Forms.Control.CreateHandle()
       at System.Windows.Forms.Control.get_Handle()
       at System.Windows.Forms.Control.PointToScreen(Point p)
       at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
       at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ButtonBase.WndProc(Message& m)
       at System.Windows.Forms.Button.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(ApplicationContext context)
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
       at WindowsApplication2.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:line 81
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

有人知道吗,当按钮样式设置为FlatStyle.System

在WinForms应用程序中将按钮样式设置为FlatStyle.System时发生System.ObjectDispos

时,就会出现这种情况

很快,它就变成了一个bug。Button/ButtonBase内部实现维护一些与鼠标状态相关的标志,在这种情况下这些标志没有被正确清除。FlatStyle.System似乎是一个特殊情况,涉及源代码中的许多分支,因此显然其中一些分支缺少了一些内容。

解决方法是创建并使用您自己的Button子类,如下所示(对不起C#,我相信您可以将其转换为VB):

public class MyButton : Button
{
    protected override void OnMouseUp(MouseEventArgs mevent)
    {
        if (this.IsDisposed) return;
        base.OnMouseUp(mevent);
    }
}