1
1
using System ;
2
- using System . Collections . Concurrent ;
3
2
using System . Diagnostics ;
4
3
using System . Runtime . InteropServices ;
5
4
using Rubberduck . Common . WinAPI ;
@@ -12,6 +11,7 @@ public abstract class SubclassingWindow : IDisposable
12
11
private readonly IntPtr _hwnd ;
13
12
private readonly SubClassCallback _wndProc ;
14
13
private bool _listening ;
14
+ private GCHandle _thisHandle ;
15
15
16
16
private readonly object _subclassLock = new object ( ) ;
17
17
@@ -43,7 +43,7 @@ protected SubclassingWindow(IntPtr subclassId, IntPtr hWnd)
43
43
public void Dispose ( )
44
44
{
45
45
ReleaseHandle ( ) ;
46
- GC . SuppressFinalize ( this ) ;
46
+ // GC.SuppressFinalize(this);
47
47
}
48
48
49
49
private void AssignHandle ( )
@@ -55,6 +55,11 @@ private void AssignHandle()
55
55
{
56
56
throw new Exception ( "SetWindowSubClass Failed" ) ;
57
57
}
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 ) ;
58
63
_listening = true ;
59
64
}
60
65
}
@@ -85,10 +90,10 @@ public virtual int SubClassProc(IntPtr hWnd, IntPtr msg, IntPtr wParam, IntPtr l
85
90
}
86
91
87
92
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 )
90
94
{
91
95
ReleaseHandle ( ) ;
96
+ _thisHandle . Free ( ) ;
92
97
}
93
98
return DefSubclassProc ( hWnd , msg , wParam , lParam ) ;
94
99
}
0 commit comments