Floating ToolWindows containing ToolStrip issue

Docking/MDI for Windows Forms Forum

Posted 13 years ago by Gerard Laslett
Avatar
I believe there may be a problem with using the System.Windows.Forms.ToolStrip (or MenuStrip) on the a ToolWindow in floating mode, and hiding/unhiding it. The error occurs - when floating over a ToolStripItem that contains a tooltip, after the tooltip has been previously shown (by floating over it) and the toolwindow has been hidden and then shown again.
I believe the problem may be due to the window that is created by the dockmanager to host the usercontrol that contains the toolstrip, being destroyed, and then recreated when re-shown. Because the toolstripitem attached a tooltip to the "old" window that contained the control - when it attempts to access the tooltip - it is trying to access the "old" window that has already been disposed (since a new one was created - and the usercontrol instance placed in that new window).

Anyway - hope some of that made sense.

the stack trace is

************** Exception Text **************
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'ᐛ'.
   at System.Windows.Forms.Control.CreateHandle()
   at System.Windows.Forms.Form.CreateHandle()
   at System.Windows.Forms.Control.get_Handle()
   at System.Windows.Forms.ToolTip.get_CreateParams()
   at System.Windows.Forms.ToolTip.CreateHandle()
   at System.Windows.Forms.ToolTip.Hide(IWin32Window win)
   at System.Windows.Forms.ToolStrip.UpdateToolTip(ToolStripItem item)
   at System.Windows.Forms.ToolStripItem.OnMouseHover(EventArgs e)
   at System.Windows.Forms.ToolStripItem.FireEventInteractive(EventArgs e, ToolStripItemEventType met)
   at System.Windows.Forms.ToolStripItem.FireEvent(EventArgs e, ToolStripItemEventType met)
   at System.Windows.Forms.MouseHoverTimer.OnTick(Object sender, EventArgs e)
   at System.Windows.Forms.Timer.OnTick(EventArgs e)
   at System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)


************** Loaded Assemblies **************
mscorlib
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/mscorlib.dll
----------------------------------------
NS10
    Assembly Version: 10.0.1.34515
    Win32 Version: 10.0.1.1
    CodeBase: file:///D:/PROJECTS/NeedScope/NS10/NS10Solution/NS10/bin/Debug/NS10.exe
----------------------------------------
System.Windows.Forms
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Windows.Forms/2.0.0.0__b77a5c561934e089/System.Windows.Forms.dll
----------------------------------------
System
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System/2.0.0.0__b77a5c561934e089/System.dll
----------------------------------------
System.Drawing
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Drawing/2.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll
----------------------------------------
System.Data
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_32/System.Data/2.0.0.0__b77a5c561934e089/System.Data.dll
----------------------------------------
System.Xml
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Xml/2.0.0.0__b77a5c561934e089/System.Xml.dll
----------------------------------------
Microsoft.Practices.EnterpriseLibrary.Data
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.0.0
    CodeBase: file:///D:/PROJECTS/NeedScope/NS10/NS10Solution/NS10/bin/Debug/Microsoft.Practices.EnterpriseLibrary.Data.DLL
----------------------------------------
Microsoft.Practices.EnterpriseLibrary.Common
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.0.0
    CodeBase: file:///D:/PROJECTS/NeedScope/NS10/NS10Solution/NS10/bin/Debug/Microsoft.Practices.EnterpriseLibrary.Common.DLL
----------------------------------------
System.Configuration
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Configuration/2.0.0.0__b03f5f7f11d50a3a/System.Configuration.dll
----------------------------------------
System.Management
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Management/2.0.0.0__b03f5f7f11d50a3a/System.Management.dll
----------------------------------------
Microsoft.Practices.ObjectBuilder
    Assembly Version: 1.0.51109.0
    Win32 Version: 1.0.51109.0
    CodeBase: file:///D:/PROJECTS/NeedScope/NS10/NS10Solution/NS10/bin/Debug/Microsoft.Practices.ObjectBuilder.DLL
----------------------------------------
System.Data.OracleClient
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_32/System.Data.OracleClient/2.0.0.0__b77a5c561934e089/System.Data.OracleClient.dll
----------------------------------------
System.Transactions
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_32/System.Transactions/2.0.0.0__b77a5c561934e089/System.Transactions.dll
----------------------------------------
System.EnterpriseServices
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_32/System.EnterpriseServices/2.0.0.0__b03f5f7f11d50a3a/System.EnterpriseServices.dll
----------------------------------------
ActiproSoftware.WinUICore
    Assembly Version: 1.0.75.0
    Win32 Version: 1.0.75.0
    CodeBase: file:///C:/WINDOWS/assembly/GAC/ActiproSoftware.WinUICore/1.0.75.0__1eba893a2bc55de5/ActiproSoftware.WinUICore.dll
----------------------------------------
ActiproSoftware.UIStudio.Dock
    Assembly Version: 1.5.40.0
    Win32 Version: 1.5.40.0
    CodeBase: file:///D:/PROJECTS/NeedScope/NS10/NS10Solution/NS10/bin/Debug/ActiproSoftware.UIStudio.Dock.DLL
----------------------------------------
ActiproSoftware.Shared
    Assembly Version: 1.0.75.0
    Win32 Version: 1.0.75.0
    CodeBase: file:///C:/WINDOWS/assembly/GAC/ActiproSoftware.Shared/1.0.75.0__36ff2196ab5654b9/ActiproSoftware.Shared.dll
----------------------------------------
System.Design
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Design/2.0.0.0__b03f5f7f11d50a3a/System.Design.dll
----------------------------------------
NMathCore
    Assembly Version: 2.2.1.0
    Win32 Version: 2.2.1.0
    CodeBase: file:///C:/WINDOWS/assembly/GAC/NMathCore/2.2.1.0__0ece19bef78ff024/NMathCore.dll
----------------------------------------
Syncfusion.Grid.Windows
    Assembly Version: 4.102.0.10
    Win32 Version: 4.102.0.10
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/Syncfusion.Grid.Windows/4.102.0.10__3d67ed1f87d44c89/Syncfusion.Grid.Windows.dll
----------------------------------------
Syncfusion.Shared.Base
    Assembly Version: 4.102.0.10
    Win32 Version: 4.102.0.10
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/Syncfusion.Shared.Base/4.102.0.10__3d67ed1f87d44c89/Syncfusion.Shared.Base.dll
----------------------------------------
Syncfusion.Core
    Assembly Version: 4.102.0.10
    Win32 Version: 4.102.0.10
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/Syncfusion.Core/4.102.0.10__632609b4d040f6b4/Syncfusion.Core.dll
----------------------------------------
NMathStats
    Assembly Version: 2.1.1.0
    Win32 Version: 2.1.1.0
    CodeBase: file:///C:/WINDOWS/assembly/GAC/NMathStats/2.1.1.0__1f1bd11b6aaaac11/NMathStats.dll
----------------------------------------
Here is my setup:

I use the docking components in a tabbed MDI arrangement.
I have tool windows that float on top of the application, and are shown/hidden, by toggling a ToolStripButton in my main form.
The tool windows contain a usercontrol and are created using the following code (where tool is a reference to the usercontrol containing my tool controls including the toolstrip):
// create and configure the ToolWindow to hold it (but don't show)
ToolWindow toolWindow = new ToolWindow(_dockManager, tool.Key, tool.ToolWindowText, null, tool);
There is a DockManager on my main form.
To re-show the tool after it has been closed I use the following code:
ToolWindow toolWindow = _toolWindows[tool];
// activate the ToolWindow (can be called with no effect on an already active ToolWindow)
toolWindow.Activate();
if you need more info - I can provide it.
please let me know if more info is needed.

Meanwhile - I'm trying to fix it by completely removing the tool from the dockmanager, and re-creating and re-adding it everytime I want to show it, which means I have to record it's position, state, etc... everytime it closes... would prefer not have to do this.

Cheers.

Comments (3)

Posted 13 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Gerard,

I have run into this in the past with the Microsoft ToolStrip control as well. It seems like they initialize their internal tooltip to the first parent window that is there when a tooltip is displayed. However if the parent window changes, the ToolStrip never updates the internal tooltip to tell it that the parent window has changed. In your case the first parent window is disposed, thus causing the error.

I personally played around a few months ago trying to find a workaround with this (I believe I was able to duplicate it using only standard Windows Forms controls too) and never could find a way to resolve it. I even tried turning off and on tooltips for the ToolStrip and nothing seemed to work around the issue. Perhaps you can dig down and use Windows APIs to update the tooltips if you can get a handle to them?

So unfortunately I don't have an answer for you since it is a bug in Microsoft's ToolStrip code. But if you do find a workaround other than what you already are doing, please post it.


Actipro Software Support

Posted 13 years ago by Gerard Laslett
Avatar
k - thanks for reply.
Yes - I'm aware that this is an issue arriving from the bug in the MS code, but since the toolstrip is a very commonly used control - that perhaps you may consider finding a way for this issue not to occur when placing it in a ToolWindow, and floating it.

Since I was just using floating toolwindows anyway - and the current specification doesn't require them to ever dock, I've done away with the ToolWindow - and just put my control on a standard windows form, which I show using f.Show(mainForm). I just store a reference to the standard windows form in my mainForm.

Hiding this using f.Hide() - doesn't destroy the windows handle - and so it can be shown again without causing this exception, and closed using the control box. If it was closed - then when wanting to show again - then my code can check using something like:
if(f!=null && f.IsDisposed) f=new StandardForm();
f.Show(mainForm);

simple enough - just means I won't have the opportunity in the future to allow the user to dock it - because its no longer using a ToolWindow from the Docking classes.

I was starting to use code like:
Form hostForm = toolWindow.FindForm();
to start working with the window created to host the usercontrol with the ToolWindow is in floating mode - but this was just getting too messy, so opted to get back to the basics and just use a standard form.

Thanks for your help.
Gerard.

[Modified at 07/17/2006 11:51 PM]
Posted 13 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Ok I've played with it for another hour and have good and bad news. The good news is that I'm able to get a direct reference to the ToolTip by using reflection and even found a method to call which seems to help work around this Microsoft bug.
ToolTip t = (ToolTip)toolStrip1.GetType().GetProperty("ToolTip", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(toolStrip1, null);
t.RemoveAll();
That code must internally clear the reference to the parent Form. I had added that code to a test form under the DockManager.WindowClosing event.

So that handles closing of windows and then reactivating later. But the remaining problem is state changes. Like float a tool window, dock it and refloat it. Then the bug is there again since the WindowClosing code never fires.

What you really need is an event from us for tool window state changes. If you had that then you could put this code in there too and it should handle everything. That feature is on the TODO list. No wait, that wouldn't handle moving from one floating window container to another. Ugh... any ideas?


Actipro Software Support

The latest build of this product (v2020.1 build 0400) was released 6 days ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.