Skip to content

Commit c286a47

Browse files
committed
Merge pull request #1305 from retailcoder/next
Adding mouse hook
2 parents cfef061 + 5736321 commit c286a47

30 files changed

+399
-58
lines changed

RetailCoder.VBE/App.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
using System.Linq;
66
using System.Runtime.InteropServices.ComTypes;
77
using System.Windows.Forms;
8-
using System.Windows.Input;
98
using Microsoft.Vbe.Interop;
109
using NLog;
1110
using Rubberduck.Common;
@@ -61,6 +60,7 @@ public App(VBE vbe, IMessageBox messageBox,
6160
_hooks = hooks;
6261
_logger = LogManager.GetCurrentClassLogger();
6362

63+
_hooks.MessageReceived += _hooks_MessageReceived;
6464
_configService.SettingsChanged += _configService_SettingsChanged;
6565
_configService.LanguageChanged += ConfigServiceLanguageChanged;
6666
_parser.State.StateChanged += Parser_StateChanged;
@@ -81,6 +81,15 @@ public App(VBE vbe, IMessageBox messageBox,
8181
UiDispatcher.Initialize();
8282
}
8383

84+
private void _hooks_MessageReceived(object sender, HookEventArgs e)
85+
{
86+
if (sender is MouseHookWrapper)
87+
{
88+
// right-click detected
89+
_appMenus.EvaluateCanExecute(_parser.State);
90+
}
91+
}
92+
8493
private void _configService_SettingsChanged(object sender, EventArgs e)
8594
{
8695
// also updates the ShortcutKey text
@@ -252,6 +261,15 @@ private void _stateBar_Refresh(object sender, EventArgs e)
252261

253262
private void Parser_StateChanged(object sender, EventArgs e)
254263
{
264+
if (_parser.State.Status != ParserState.Ready)
265+
{
266+
_hooks.Detach();
267+
}
268+
else
269+
{
270+
_hooks.Attach();
271+
}
272+
255273
Debug.WriteLine("App handles StateChanged ({0}), evaluating menu states...", _parser.State.Status);
256274
_appMenus.EvaluateCanExecute(_parser.State);
257275
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using System;
2+
using EventHook;
3+
using EventHook.Hooks;
4+
5+
namespace Rubberduck.Common
6+
{
7+
public class MouseHookWrapper : IAttachable
8+
{
9+
public MouseHookWrapper()
10+
{
11+
MouseWatcher.OnMouseInput += MouseWatcher_OnMouseInput;
12+
}
13+
14+
private void MouseWatcher_OnMouseInput(object sender, MouseEventArgs e)
15+
{
16+
// only handle right-clicks
17+
if (e.Message != MouseMessages.WM_RBUTTONDOWN)
18+
{
19+
return;
20+
}
21+
22+
var handler = MessageReceived;
23+
if (handler != null)
24+
{
25+
handler.Invoke(this, HookEventArgs.Empty);
26+
}
27+
}
28+
29+
public bool IsAttached { get; private set; }
30+
public event EventHandler<HookEventArgs> MessageReceived;
31+
32+
public void Attach()
33+
{
34+
MouseWatcher.Start();
35+
IsAttached = true;
36+
}
37+
38+
public void Detach()
39+
{
40+
MouseWatcher.Stop();
41+
IsAttached = false;
42+
}
43+
}
44+
}

RetailCoder.VBE/Common/RubberduckHooks.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Diagnostics;
34
using System.Linq;
45
using System.Runtime.InteropServices;
56
using Microsoft.Vbe.Interop;
@@ -31,16 +32,19 @@ public RubberduckHooks(VBE vbe, IAttachable timerHook, IGeneralConfigService con
3132
_oldWndPointer = User32.SetWindowLong(_mainWindowHandle, (int)WindowLongFlags.GWL_WNDPROC, _newWndProc);
3233
_oldWndProc = (User32.WndProc)Marshal.GetDelegateForFunctionPointer(_oldWndPointer, typeof(User32.WndProc));
3334

34-
_timerHook = timerHook;
3535
_config = config;
36+
_timerHook = timerHook;
3637
_timerHook.MessageReceived += timerHook_MessageReceived;
3738
}
3839

40+
3941
public void HookHotkeys()
4042
{
4143
Detach();
4244
_hooks.Clear();
4345

46+
AddHook(new MouseHookWrapper());
47+
4448
var config = _config.LoadConfiguration();
4549
var settings = config.UserSettings.GeneralSettings.HotkeySettings;
4650
foreach (var hotkey in settings.Where(hotkey => hotkey.IsEnabled))
@@ -89,12 +93,19 @@ public void Attach()
8993

9094
private void hook_MessageReceived(object sender, HookEventArgs e)
9195
{
92-
if (sender is ILowLevelKeyboardHook)
96+
if (sender is LowLevelKeyboardHook)
9397
{
9498
// todo: handle 2-step hotkeys?
9599
return;
96100
}
97101

102+
if (sender is MouseHookWrapper)
103+
{
104+
Debug.WriteLine("MouseHookWrapper message received");
105+
OnMessageReceived(sender, HookEventArgs.Empty);
106+
return;
107+
}
108+
98109
var hotkey = sender as IHotkey;
99110
if (hotkey != null)
100111
{

RetailCoder.VBE/Refactorings/ImplementInterface/ImplementInterfaceRefactoring.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ private List<Parameter> GetParameters(Declaration member)
187187
})
188188
.ToList();
189189

190-
if (member.DeclarationType == DeclarationType.PropertyGet)
190+
if (member.DeclarationType == DeclarationType.PropertyGet && parameters.Any())
191191
{
192192
parameters.Remove(parameters.Last());
193193
}

RetailCoder.VBE/Rubberduck.csproj

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,10 @@
229229
<Reference Include="Castle.Core">
230230
<HintPath>..\packages\Castle.Core.3.2.0\lib\net45\Castle.Core.dll</HintPath>
231231
</Reference>
232+
<Reference Include="EventHook, Version=1.4.26.0, Culture=neutral, processorArchitecture=MSIL">
233+
<HintPath>..\packages\EventHook.1.4.26\lib\net45\EventHook.dll</HintPath>
234+
<Private>True</Private>
235+
</Reference>
232236
<Reference Include="extensibility, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
233237
<EmbedInteropTypes>True</EmbedInteropTypes>
234238
</Reference>
@@ -244,6 +248,18 @@
244248
<Reference Include="Ninject.Extensions.NamedScope">
245249
<HintPath>..\packages\Ninject.Extensions.NamedScope.3.2.0.0\lib\net45-full\Ninject.Extensions.NamedScope.dll</HintPath>
246250
</Reference>
251+
<Reference Include="Nito.AsyncEx, Version=3.0.1.0, Culture=neutral, processorArchitecture=MSIL">
252+
<HintPath>..\packages\Nito.AsyncEx.3.0.1\lib\net45\Nito.AsyncEx.dll</HintPath>
253+
<Private>True</Private>
254+
</Reference>
255+
<Reference Include="Nito.AsyncEx.Concurrent, Version=3.0.1.0, Culture=neutral, processorArchitecture=MSIL">
256+
<HintPath>..\packages\Nito.AsyncEx.3.0.1\lib\net45\Nito.AsyncEx.Concurrent.dll</HintPath>
257+
<Private>True</Private>
258+
</Reference>
259+
<Reference Include="Nito.AsyncEx.Enlightenment, Version=3.0.1.0, Culture=neutral, processorArchitecture=MSIL">
260+
<HintPath>..\packages\Nito.AsyncEx.3.0.1\lib\net45\Nito.AsyncEx.Enlightenment.dll</HintPath>
261+
<Private>True</Private>
262+
</Reference>
247263
<Reference Include="PresentationCore" />
248264
<Reference Include="PresentationFramework" />
249265
<Reference Include="PresentationFramework.Aero" />
@@ -299,6 +315,7 @@
299315
<Compile Include="Common\ILowLevelKeyboardHook.cs" />
300316
<Compile Include="Common\IRubberduckHooks.cs" />
301317
<Compile Include="Common\ModuleExporter.cs" />
318+
<Compile Include="Common\MouseHookWrapper.cs" />
302319
<Compile Include="Common\RubberduckHooks.cs" />
303320
<Compile Include="Common\TimerHook.cs" />
304321
<Compile Include="Common\WinAPI\KBDLLHOOKSTRUCT.cs" />

RetailCoder.VBE/UI/Command/MenuItems/CommandMenuItemBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public Func<string> Caption
3636
/// <remarks>Returns <c>true</c> if not overridden.</remarks>
3737
public virtual bool EvaluateCanExecute(RubberduckParserState state)
3838
{
39-
return true;
39+
return _command.CanExecute(state);
4040
}
4141

4242
public virtual bool BeginGroup { get { return false; } }
Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System.Windows.Input;
2-
using Rubberduck.Parsing.VBA;
32
using Rubberduck.UI.Command.MenuItems.ParentMenus;
43

54
namespace Rubberduck.UI.Command.MenuItems
@@ -13,10 +12,5 @@ public ProjectExplorerRefactorRenameCommandMenuItem(ICommand command)
1312

1413
public override string Key { get { return "RefactorMenu_Rename"; } }
1514
public override int DisplayOrder { get { return (int)RefactoringsMenuItemDisplayOrder.RenameIdentifier; } }
16-
17-
public override bool EvaluateCanExecute(RubberduckParserState state)
18-
{
19-
return state.Status == ParserState.Ready;
20-
}
2115
}
2216
}

RetailCoder.VBE/UI/Command/MenuItems/RefactorEncapsulateFieldCommandMenuItem.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
using System.Drawing;
21
using System.Windows.Input;
32
using Rubberduck.Parsing.VBA;
4-
using Rubberduck.Properties;
53
using Rubberduck.UI.Command.MenuItems.ParentMenus;
64

75
namespace Rubberduck.UI.Command.MenuItems
@@ -20,7 +18,7 @@ public RefactorEncapsulateFieldCommandMenuItem(ICommand command)
2018

2119
public override bool EvaluateCanExecute(RubberduckParserState state)
2220
{
23-
return state.Status == ParserState.Ready;
21+
return Command.CanExecute(null);
2422
}
2523
}
2624
}

RetailCoder.VBE/UI/Command/MenuItems/RefactorExtractInterfaceCommandMenuItem.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public RefactorExtractInterfaceCommandMenuItem(ICommand command)
2020

2121
public override bool EvaluateCanExecute(RubberduckParserState state)
2222
{
23-
return state.Status == ParserState.Ready;
23+
return Command.CanExecute(null);
2424
}
2525
}
2626
}

RetailCoder.VBE/UI/Command/MenuItems/RefactorExtractMethodCommandMenuItem.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public override bool BeginGroup
2626

2727
public override bool EvaluateCanExecute(RubberduckParserState state)
2828
{
29-
return state.Status == ParserState.Ready;
29+
return Command.CanExecute(null);
3030
}
3131
}
3232
}

0 commit comments

Comments
 (0)