System.ObjectDisposedException when the button style is set to FlatStyle.System in WinForms application
I've a child form which shows up on clicking a button in parent. And the code goes like below.
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
The child form has in turn a button that closes itself.
Public Class Child
    Private Sub btnCloseMe_Click(sender As Object, e As EventArgs) Handles btnCloseMe.Click
        Me.Close()
    End Sub
End Class
Steps to get exception:
Me.Close()  Exception:
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: 
Does anyone has any idea, this is explicitly coming when button style set to FlatStyle.System 
Shortly, it's a bug. The Button/ButtonBase internal implementation maintains some mouse state related flags which are not properly cleared in that case. FlatStyle.System seems to be a special case involving a lot of branches in the source code, so apparently some of them is missing something.
The workaround would be to create and use your own Button subclass like this (sorry for C#, I'm sure you can translate it to VB):
public class MyButton : Button
{
    protected override void OnMouseUp(MouseEventArgs mevent)
    {
        if (this.IsDisposed) return;
        base.OnMouseUp(mevent);
    }
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With