Skip to content

Commit c85bacf

Browse files
committed
loads both toolwindows; access violation crash on exit (Rubberduck crash repro!)
1 parent 03f41fc commit c85bacf

File tree

8 files changed

+135
-32
lines changed

8 files changed

+135
-32
lines changed

App.cs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,35 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
4-
using System.Text;
5-
using System.Threading.Tasks;
6-
using Microsoft.Vbe.Interop;
1+
using Microsoft.Vbe.Interop;
72

83
namespace SlimDucky
94
{
105
public class App
116
{
127
private readonly VBE _vbe;
8+
private readonly AddIn _adddIn;
139

14-
public App(VBE vbe)
10+
public App(VBE vbe, AddIn addIn)
1511
{
1612
_vbe = vbe;
13+
_adddIn = addIn;
14+
15+
_winFormsUserControl = new WinFormsControl();
16+
_wpfUserControl = new WpfHostControl();
1717
}
1818

19+
private IDockableUserControl _wpfUserControl;
20+
private IDockableUserControl _winFormsUserControl;
21+
1922
public void Startup()
2023
{
21-
24+
var winFormsPresenter = new DockableToolwindowPresenter(_vbe, _adddIn, _winFormsUserControl);
25+
var wpfPresenter = new DockableToolwindowPresenter(_vbe, _adddIn, _wpfUserControl);
26+
27+
winFormsPresenter.Show();
28+
wpfPresenter.Show();
2229
}
2330

2431
public void Shutdown()
2532
{
26-
2733
}
2834
}
2935
}

Connect.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ private void InitializeAddIn()
8585
return;
8686
}
8787

88-
_app = new App(_vbe);
88+
_app = new App(_vbe, _addIn);
8989
_app.Startup();
9090

9191
_isInitialized = true;

DockableToolwindowPresenter.cs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
using System;
2+
using System.Diagnostics;
3+
using System.Runtime.InteropServices;
4+
using System.Windows.Forms;
5+
using Microsoft.Vbe.Interop;
6+
7+
namespace SlimDucky
8+
{
9+
public class DockableToolwindowPresenter
10+
{
11+
private readonly AddIn _addin;
12+
private readonly Window _window;
13+
private readonly VBE _vbe;
14+
15+
private object _userControlObject;
16+
17+
public DockableToolwindowPresenter(VBE vbe, AddIn addin, IDockableUserControl view)
18+
{
19+
_vbe = vbe;
20+
_addin = addin;
21+
UserControl = view;
22+
_window = CreateToolWindow(view);
23+
}
24+
25+
public IDockableUserControl UserControl { get; }
26+
27+
private Window CreateToolWindow(IDockableUserControl view)
28+
{
29+
Window toolWindow;
30+
try
31+
{
32+
object control = null;
33+
toolWindow = _vbe.Windows.CreateToolWindow(_addin, _DockableWindowHost.ProgId, view.Caption, view.ClassId, ref control);
34+
_userControlObject = control;
35+
}
36+
catch(COMException exception)
37+
{
38+
Debug.WriteLine(exception);
39+
throw;
40+
}
41+
42+
var userControlHost = (_DockableWindowHost)_userControlObject;
43+
toolWindow.Visible = true; //window resizing doesn't work without this
44+
45+
EnsureMinimumWindowSize(toolWindow);
46+
47+
toolWindow.Visible = true; // here Rubberduck checks window settings to show toolwindow at startup
48+
49+
userControlHost.AddUserControl(view as UserControl, new IntPtr(_vbe.MainWindow.HWnd));
50+
return toolWindow;
51+
}
52+
53+
private void EnsureMinimumWindowSize(Window window)
54+
{
55+
const int defaultWidth = 350;
56+
const int defaultHeight = 200;
57+
58+
if(!window.Visible || window.LinkedWindows != null)
59+
{
60+
return;
61+
}
62+
63+
if(window.Width < defaultWidth)
64+
{
65+
window.Width = defaultWidth;
66+
}
67+
68+
if(window.Height < defaultHeight)
69+
{
70+
window.Height = defaultHeight;
71+
}
72+
}
73+
74+
public virtual void Show() => _window.Visible = true;
75+
public virtual void Hide() => _window.Visible = false;
76+
77+
~DockableToolwindowPresenter()
78+
{
79+
// destructor for tracking purposes only - do not suppress unless
80+
Debug.WriteLine("DockableToolwindowPresenter finalized.");
81+
}
82+
}
83+
}

IDockableUserControl.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
namespace SlimDucky
2+
{
3+
public interface IDockableUserControl
4+
{
5+
/// <summary>
6+
/// Gets a string containing the GUID with which the class is registered.
7+
/// </summary>
8+
string ClassId { get; }
9+
10+
/// <summary>
11+
/// Gets a string containing the caption of the toolwindow.
12+
/// </summary>
13+
string Caption { get; }
14+
}
15+
}

Properties/AssemblyInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
// Setting ComVisible to false makes the types in this assembly not visible
1818
// to COM components. If you need to access a type in this assembly from
1919
// COM, set the ComVisible attribute to true on that type.
20-
[assembly: ComVisible(true)]
20+
[assembly: ComVisible(false)]
2121

2222
// The following GUID is for the ID of the typelib if this project is exposed to COM
2323
[assembly: Guid("07e68a3e-6ec7-4ee3-8904-013a6db77f79")]

SlimDucky.csproj

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99
<AppDesignerFolder>Properties</AppDesignerFolder>
1010
<RootNamespace>SlimDucky</RootNamespace>
1111
<AssemblyName>SlimDucky</AssemblyName>
12-
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
12+
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
1313
<FileAlignment>512</FileAlignment>
14+
<TargetFrameworkProfile />
1415
</PropertyGroup>
1516
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
1617
<DebugSymbols>true</DebugSymbols>
@@ -56,9 +57,11 @@
5657
<ItemGroup>
5758
<Compile Include="App.cs" />
5859
<Compile Include="Connect.cs" />
60+
<Compile Include="DockableToolwindowPresenter.cs" />
5961
<Compile Include="DockableWindowHost.cs">
6062
<SubType>UserControl</SubType>
6163
</Compile>
64+
<Compile Include="IDockableUserControl.cs" />
6265
<Compile Include="Properties\AssemblyInfo.cs" />
6366
<Compile Include="SubclassingWindow.cs" />
6467
<Compile Include="SubClassingWindowEventArgs.cs" />

WinFormsControl.cs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.ComponentModel;
4-
using System.Drawing;
5-
using System.Data;
6-
using System.Linq;
7-
using System.Text;
8-
using System.Threading.Tasks;
9-
using System.Windows.Forms;
1+
using System.Windows.Forms;
2+
using System.Runtime.InteropServices;
103

114
namespace SlimDucky
125
{
13-
public partial class WinFormsControl : UserControl
6+
[ComVisible(true)]
7+
[Guid("AA0811DA-4C0E-45FE-A017-994298C675E5")]
8+
public partial class WinFormsControl : UserControl, IDockableUserControl
149
{
1510
public WinFormsControl()
1611
{
1712
InitializeComponent();
1813
}
14+
15+
public string ClassId => "AA0811DA-4C0E-45FE-A017-994298C675E5";
16+
public string Caption => "WinForms ToolWindow";
1917
}
2018
}

WpfHostControl.cs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.ComponentModel;
4-
using System.Drawing;
5-
using System.Data;
6-
using System.Linq;
7-
using System.Text;
8-
using System.Threading.Tasks;
9-
using System.Windows.Forms;
1+
using System.Windows.Forms;
2+
using System.Runtime.InteropServices;
103

114
namespace SlimDucky
125
{
13-
public partial class WpfHostControl : UserControl
6+
[ComVisible(true)]
7+
[Guid("23D58F4F-FEE2-4D63-A5AE-EBBD360F26ED")]
8+
public partial class WpfHostControl : UserControl, IDockableUserControl
149
{
1510
public WpfHostControl()
1611
{
1712
InitializeComponent();
1813
}
14+
15+
public string ClassId => "23D58F4F-FEE2-4D63-A5AE-EBBD360F26ED";
16+
public string Caption => "WPF ToolWindow";
1917
}
2018
}

0 commit comments

Comments
 (0)