11using System ;
2- using System . Collections . Concurrent ;
32using System . Diagnostics ;
43using System . Runtime . InteropServices ;
54using Rubberduck . Common . WinAPI ;
@@ -12,6 +11,7 @@ public abstract class SubclassingWindow : IDisposable
1211 private readonly IntPtr _hwnd ;
1312 private readonly SubClassCallback _wndProc ;
1413 private bool _listening ;
14+ private GCHandle _thisHandle ;
1515
1616 private readonly object _subclassLock = new object ( ) ;
1717
@@ -43,7 +43,7 @@ protected SubclassingWindow(IntPtr subclassId, IntPtr hWnd)
4343 public void Dispose ( )
4444 {
4545 ReleaseHandle ( ) ;
46- GC . SuppressFinalize ( this ) ;
46+ // GC.SuppressFinalize(this);
4747 }
4848
4949 private void AssignHandle ( )
@@ -55,6 +55,11 @@ private void AssignHandle()
5555 {
5656 throw new Exception ( "SetWindowSubClass Failed" ) ;
5757 }
58+ //DO NOT REMOVE THIS CALL. Dockable windows are instantiated by the VBE, not directly by RD. On top of that,
59+ //since we have to inherit from UserControl we don't have to keep handling window messages until the VBE gets
60+ //around to destroying the control's host or it results in an access violation when the base class is disposed.
61+ //We need to manually call base.Dispose() ONLY in response to a WM_DESTROY message.
62+ _thisHandle = GCHandle . Alloc ( this , GCHandleType . Normal ) ;
5863 _listening = true ;
5964 }
6065 }
@@ -85,10 +90,10 @@ public virtual int SubClassProc(IntPtr hWnd, IntPtr msg, IntPtr wParam, IntPtr l
8590 }
8691
8792 Debug . Assert ( IsWindow ( _hwnd ) ) ;
88- //TODO: This should change to WM.DESTROY once subclassing\hooking consolidation is complete.
89- if ( ( uint ) msg == ( uint ) WM . RUBBERDUCK_SINKING )
93+ if ( ( uint ) msg == ( uint ) WM . RUBBERDUCK_SINKING || ( uint ) msg == ( uint ) WM . DESTROY )
9094 {
9195 ReleaseHandle ( ) ;
96+ _thisHandle . Free ( ) ;
9297 }
9398 return DefSubclassProc ( hWnd , msg , wParam , lParam ) ;
9499 }
0 commit comments