Skip to content

Commit 86b22cb

Browse files
authored
Merge pull request #4833 from bclothier/ComDisconnect
Introducing ComCommand classes
2 parents 65aac29 + b22c78c commit 86b22cb

File tree

128 files changed

+1313
-547
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

128 files changed

+1313
-547
lines changed

Rubberduck.API/VBA/Parser.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public sealed class Parser : IParser, IDisposable
7070
private readonly RubberduckParserState _state;
7171
private readonly SynchronousParseCoordinator _parser;
7272
private readonly IVBE _vbe;
73-
private readonly IVBEEvents _vbeEvents;
73+
private readonly IVbeEvents _vbeEvents;
7474
private readonly IUiDispatcher _dispatcher;
7575
private readonly CancellationTokenSource _tokenSource;
7676

@@ -91,7 +91,7 @@ internal Parser(object vbe) : this()
9191
}
9292

9393
_vbe = RootComWrapperFactory.GetVbeWrapper(vbe);
94-
_vbeEvents = VBEEvents.Initialize(_vbe);
94+
_vbeEvents = VbeEvents.Initialize(_vbe);
9595
var declarationFinderFactory = new ConcurrentlyConstructedDeclarationFinderFactory();
9696
var projectRepository = new ProjectsRepository(_vbe);
9797
var projectsToBeLoadedFromComSelector = new ProjectsToResolveFromComProjectsSelector(projectRepository);

Rubberduck.Core/App.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using System.Linq;
1313
using Rubberduck.Parsing.UIContext;
1414
using Rubberduck.Resources;
15+
using Rubberduck.Runtime;
1516
using Rubberduck.UI.Command;
1617
using Rubberduck.VBEditor.Utility;
1718
using Rubberduck.VersionCheck;

Rubberduck.Core/AutoComplete/SelfClosingPairs/SelfClosingPairCompletionService.cs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,17 @@ namespace Rubberduck.AutoComplete.SelfClosingPairs
1212
{
1313
public class SelfClosingPairCompletionService
1414
{
15-
/*
16-
// note: this works... but the VBE makes an annoying DING! when the command isn't available.
17-
// todo: implement our own intellisense, then uncomment this code.
18-
private readonly IShowIntelliSenseCommand _showIntelliSense;
15+
private readonly IShowQuickInfoCommand _showQuickInfo;
1916

20-
public SelfClosingPairCompletionService(IShowIntelliSenseCommand showIntelliSense)
17+
public SelfClosingPairCompletionService(IShowQuickInfoCommand showQuickInfo)
2118
{
22-
_showIntelliSense = showIntelliSense;
19+
_showQuickInfo = showQuickInfo;
20+
}
21+
22+
public void ShowIntellisense()
23+
{
24+
_showQuickInfo.Execute();
2325
}
24-
*/
2526

2627
public bool Execute(SelfClosingPair pair, CodeString original, char input, out CodeString result)
2728
{

Rubberduck.Core/AutoComplete/SelfClosingPairs/SelfClosingPairHandler.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ private bool HandleInternal(AutoCompleteEventArgs e, CodeString original, SelfCl
143143
{
144144
e.Handled = true;
145145
result = reprettified;
146+
_scpService.ShowIntellisense();
146147
return true;
147148
}
148149

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using System.Runtime.InteropServices;
2+
using Rubberduck.Runtime;
3+
using Rubberduck.UI.Command.ComCommands;
4+
using Rubberduck.VBEditor.Events;
5+
using Rubberduck.VBEditor.SafeComWrappers.Abstract;
6+
7+
namespace Rubberduck.AutoComplete
8+
{
9+
public interface IShowQuickInfoCommand
10+
{
11+
/// <summary>
12+
/// Displays the quick info in the VBE.
13+
/// NOTE: By default, it makes an utterly annoying DING! in the VBE if the "QuickInfo" command is unavailable. Hooking is used to suppress the ding.
14+
/// </summary>
15+
void Execute();
16+
}
17+
18+
public class ShowQuickInfoCommand : ComCommandBase, IShowQuickInfoCommand
19+
{
20+
private readonly IVBE _vbe;
21+
private readonly IBeepInterceptor _beepInterceptor;
22+
23+
public ShowQuickInfoCommand(IVBE vbe, IVbeEvents vbeEvents, IBeepInterceptor beepInterceptor) : base(vbeEvents)
24+
{
25+
_vbe = vbe;
26+
_beepInterceptor = beepInterceptor;
27+
AddToCanExecuteEvaluation(SpecialEvaluateCanExecute);
28+
}
29+
30+
private bool SpecialEvaluateCanExecute(object parameter)
31+
{
32+
try
33+
{
34+
return parameter != null || _vbe.ProjectsCount == 1;
35+
}
36+
catch (COMException)
37+
{
38+
return false;
39+
}
40+
}
41+
42+
public void Execute()
43+
{
44+
OnExecute(null);
45+
}
46+
47+
protected override void OnExecute(object parameter)
48+
{
49+
const int showQuickInfoId = 2531;
50+
using (var commandBars = _vbe.CommandBars)
51+
{
52+
using (var command = commandBars.FindControl(showQuickInfoId))
53+
{
54+
// Ensures that the queued beep message (if any) is suppressed
55+
_beepInterceptor.SuppressBeep(100);
56+
57+
command.Execute();
58+
}
59+
}
60+
}
61+
}
62+
}

Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerViewModel.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
using System.Windows.Input;
1717
using Rubberduck.Parsing.UIContext;
1818
using Rubberduck.Templates;
19-
using Rubberduck.UI.UnitTesting.Commands;
19+
using Rubberduck.UI.Command.ComCommands;
20+
using Rubberduck.UI.UnitTesting.ComCommands;
2021
using Rubberduck.VBEditor.SafeComWrappers.Abstract;
2122

2223
namespace Rubberduck.Navigation.CodeExplorer

Rubberduck.Core/Rubberduck.Core.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
using System.Timers;
4+
using EasyHook;
5+
using Rubberduck.VBEditor.VbeRuntime;
6+
7+
namespace Rubberduck.Runtime
8+
{
9+
public class BeepEventArgs : EventArgs
10+
{
11+
public bool Handled { get; set; }
12+
}
13+
14+
public interface IBeepInterceptor : IDisposable
15+
{
16+
void SuppressBeep(double millisecondsToSuppress);
17+
event EventHandler<BeepEventArgs> Beep;
18+
}
19+
20+
public sealed class BeepInterceptor : IBeepInterceptor
21+
{
22+
public event EventHandler<BeepEventArgs> Beep;
23+
24+
private readonly IVbeNativeApi _vbeApi;
25+
private readonly LocalHook _hook;
26+
private readonly Timer _timer;
27+
28+
public BeepInterceptor(IVbeNativeApi vbeApi)
29+
{
30+
_vbeApi = vbeApi;
31+
_hook = HookVbaBeep();
32+
_timer = new Timer();
33+
_timer.Elapsed += TimerElapsed;
34+
}
35+
36+
public void SuppressBeep(double millisecondsToSuppress)
37+
{
38+
_suppressed = true;
39+
_timer.Interval = millisecondsToSuppress;
40+
_timer.Enabled = true;
41+
}
42+
43+
private LocalHook HookVbaBeep()
44+
{
45+
var processAddress = LocalHook.GetProcAddress(_vbeApi.DllName, "rtcBeep");
46+
var callbackDelegate = new VbaBeepDelegate(VbaBeepCallback);
47+
var hook = LocalHook.Create(processAddress, callbackDelegate, null);
48+
hook.ThreadACL.SetInclusiveACL(new[] { 0 });
49+
return hook;
50+
}
51+
52+
[UnmanagedFunctionPointer(CallingConvention.StdCall, SetLastError = true)]
53+
private delegate void VbaBeepDelegate();
54+
55+
private bool _suppressed;
56+
private void VbaBeepCallback()
57+
{
58+
if (_suppressed)
59+
{
60+
return;
61+
}
62+
63+
var e = new BeepEventArgs();
64+
Beep?.Invoke(this, e);
65+
66+
if (!e.Handled)
67+
{
68+
_vbeApi.Beep();
69+
}
70+
}
71+
72+
private void TimerElapsed(object sender, ElapsedEventArgs e)
73+
{
74+
_suppressed = false;
75+
_timer.Enabled = false;
76+
}
77+
78+
private bool _disposed;
79+
public void Dispose()
80+
{
81+
if (_disposed)
82+
{
83+
return;
84+
}
85+
86+
_hook?.Dispose();
87+
_timer?.Dispose();
88+
_disposed = true;
89+
}
90+
}
91+
}

Rubberduck.Core/Settings/ReferenceConfigProvider.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ public class ReferenceConfigProvider : ConfigurationServiceBase<ReferenceSetting
1616
private static readonly string HostApplication = Path.GetFileName(Application.ExecutablePath).ToUpperInvariant();
1717

1818
private readonly IEnvironmentProvider _environment;
19-
private readonly IVBEEvents _events;
19+
private readonly IVbeEvents _events;
2020
private bool _listening;
2121

22-
public ReferenceConfigProvider(IPersistenceService<ReferenceSettings> persister, IEnvironmentProvider environment, IVBEEvents events)
22+
public ReferenceConfigProvider(IPersistenceService<ReferenceSettings> persister, IEnvironmentProvider environment, IVbeEvents events)
2323
: base(persister, new DefaultSettings<ReferenceSettings, Properties.Settings>())
2424
{
2525
_environment = environment;

Rubberduck.Core/UI/CodeExplorer/Commands/AddClassModuleCommand.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
using System.Collections.Generic;
2+
using Rubberduck.VBEditor.Events;
23
using Rubberduck.VBEditor.SafeComWrappers;
34

45
namespace Rubberduck.UI.CodeExplorer.Commands
56
{
67
public class AddClassModuleCommand : AddComponentCommandBase
78
{
8-
public AddClassModuleCommand(ICodeExplorerAddComponentService addComponentService)
9-
: base(addComponentService)
10-
{}
9+
public AddClassModuleCommand(
10+
ICodeExplorerAddComponentService addComponentService, IVbeEvents vbeEvents)
11+
: base(addComponentService, vbeEvents) { }
1112

1213
public override IEnumerable<ProjectType> AllowableProjectTypes => ProjectTypes.All;
1314

0 commit comments

Comments
 (0)