Skip to content

Commit 79a5bbc

Browse files
committed
GC pin all subclassing windows.
1 parent d24ed82 commit 79a5bbc

File tree

1 file changed

+9
-4
lines changed

1 file changed

+9
-4
lines changed

Rubberduck.VBEEditor/WindowsApi/SubclassingWindow.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System;
2-
using System.Collections.Concurrent;
32
using System.Diagnostics;
43
using System.Runtime.InteropServices;
54
using 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

Comments
 (0)