Skip to content

Commit 944d75b

Browse files
committed
removed EventHook dependency; implemented MouseHook and KeyboardHook classes; doesn't crash, but doesn't work either.
1 parent c99f1f2 commit 944d75b

File tree

11 files changed

+278
-242
lines changed

11 files changed

+278
-242
lines changed

RetailCoder.VBE/App.cs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,11 @@ public App(VBE vbe, IMessageBox messageBox,
8484

8585
private void _hooks_MessageReceived(object sender, HookEventArgs e)
8686
{
87-
if (sender is MouseHookWrapper)
87+
if (sender is MouseHook)
8888
{
89-
// right-click detected
9089
_appMenus.EvaluateCanExecute(_parser.State);
9190
}
92-
if (sender is KeyboardHookWrapper)
91+
if (sender is KeyboardHook)
9392
{
9493
var pane = _vbe.ActiveCodePane;
9594
if (pane == null)
@@ -121,10 +120,12 @@ public void Startup()
121120

122121
Task.Delay(1000).ContinueWith(t =>
123122
{
124-
_parser.State.OnParseRequested(this);
125-
_hooks.HookHotkeys();
126-
_hooks.Attach();
127-
});
123+
UiDispatcher.Invoke(() =>
124+
{
125+
_parser.State.OnParseRequested(this);
126+
_hooks.HookHotkeys();
127+
});
128+
}).ConfigureAwait(false);
128129
}
129130

130131
#region sink handlers. todo: move to another class

RetailCoder.VBE/Common/Hotkeys/Hotkey.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ private static Keys GetKey(string keyCode)
147147
result = Keys.Return;
148148
break;
149149
default:
150-
if (!String.IsNullOrEmpty(keyCode))
150+
if (!string.IsNullOrEmpty(keyCode))
151151
{
152152
result = (Keys)Enum.Parse(typeof(Keys), keyCode);
153153
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
using System;
2+
using System.ComponentModel;
3+
using System.Diagnostics;
4+
using System.Runtime.InteropServices;
5+
using System.Windows.Forms;
6+
using Microsoft.Vbe.Interop;
7+
using Rubberduck.Common.WinAPI;
8+
9+
namespace Rubberduck.Common
10+
{
11+
public class KeyboardHook : IAttachable
12+
{
13+
private readonly VBE _vbe;
14+
private IntPtr _hookId;
15+
16+
public KeyboardHook(VBE vbe)
17+
{
18+
_vbe = vbe;
19+
}
20+
21+
private int _lastLineIndex;
22+
private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
23+
{
24+
var pane = _vbe.ActiveCodePane;
25+
if (pane != null)
26+
{
27+
int startLine;
28+
int endLine;
29+
int startColumn;
30+
int endColumn;
31+
32+
// not using extension method because a QualifiedSelection would be overkill:
33+
pane.GetSelection(out startLine, out startColumn, out endLine, out endColumn);
34+
if (startLine != _lastLineIndex)
35+
{
36+
// if the current line has changed, let the KEYDOWN be written to the IDE, and notify on KEYUP:
37+
_lastLineIndex = startLine;
38+
if (nCode >= 0 && (WM)wParam == WM.KEYUP)
39+
{
40+
//var key = (Keys)Marshal.ReadInt32(lParam);
41+
OnMessageReceived();
42+
}
43+
}
44+
}
45+
46+
return User32.CallNextHookEx(_hookId, nCode, wParam, lParam);
47+
}
48+
49+
private void OnMessageReceived()
50+
{
51+
var handler = MessageReceived;
52+
if (handler != null)
53+
{
54+
handler.Invoke(this, HookEventArgs.Empty);
55+
}
56+
}
57+
58+
public bool IsAttached { get; private set; }
59+
public event EventHandler<HookEventArgs> MessageReceived;
60+
61+
public void Attach()
62+
{
63+
if (IsAttached)
64+
{
65+
return;
66+
}
67+
68+
_hookId = User32.SetWindowsHookEx(WindowsHook.KEYBOARD, HookCallback, Kernel32.GetModuleHandle("user32"), 0);
69+
if (_hookId == IntPtr.Zero)
70+
{
71+
throw new Win32Exception();
72+
}
73+
IsAttached = true;
74+
Debug.WriteLine("{0}: {1}", GetType().Name, IsAttached ? "Attached" : "Detached");
75+
}
76+
77+
public void Detach()
78+
{
79+
if (!IsAttached)
80+
{
81+
return;
82+
}
83+
84+
User32.UnhookWindowsHookEx(_hookId);
85+
86+
IsAttached = false;
87+
Debug.WriteLine("{0}: {1}", GetType().Name, IsAttached ? "Attached" : "Detached");
88+
}
89+
}
90+
}

RetailCoder.VBE/Common/KeyboardHookWrapper.cs

Lines changed: 0 additions & 66 deletions
This file was deleted.

RetailCoder.VBE/Common/MouseHook.cs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
using System;
2+
using System.ComponentModel;
3+
using System.Diagnostics;
4+
using Rubberduck.Common.WinAPI;
5+
6+
namespace Rubberduck.Common
7+
{
8+
public class MouseHook : IAttachable
9+
{
10+
private IntPtr _hookId;
11+
12+
private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
13+
{
14+
if (nCode >= 0)
15+
{
16+
var button = (WM)wParam;
17+
if (button == WM.RBUTTONDOWN || button == WM.LBUTTONDOWN)
18+
{
19+
// handle right-click to evaluate commands' CanExecute before the context menu is shown;
20+
// handle left-click to do the same before the Rubberduck menu is drawn, too.
21+
OnMessageReceived();
22+
}
23+
}
24+
25+
return User32.CallNextHookEx(_hookId, nCode, wParam, lParam);
26+
}
27+
28+
private void OnMessageReceived()
29+
{
30+
var handler = MessageReceived;
31+
if (handler != null)
32+
{
33+
handler.Invoke(this, HookEventArgs.Empty);
34+
}
35+
}
36+
37+
public bool IsAttached { get; private set; }
38+
public event EventHandler<HookEventArgs> MessageReceived;
39+
40+
public void Attach()
41+
{
42+
if (IsAttached)
43+
{
44+
return;
45+
}
46+
47+
_hookId = User32.SetWindowsHookEx(WindowsHook.MOUSE, HookCallback, Kernel32.GetModuleHandle("user32"), 0);
48+
if (_hookId == IntPtr.Zero)
49+
{
50+
throw new Win32Exception();
51+
}
52+
53+
54+
IsAttached = true;
55+
Debug.WriteLine("{0}: {1}", GetType().Name, IsAttached ? "Attached" : "Detached");
56+
}
57+
58+
public void Detach()
59+
{
60+
if (!IsAttached)
61+
{
62+
return;
63+
}
64+
65+
User32.UnhookWindowsHookEx(_hookId);
66+
67+
IsAttached = false;
68+
Debug.WriteLine("{0}: {1}", GetType().Name, IsAttached ? "Attached" : "Detached");
69+
}
70+
}
71+
}

RetailCoder.VBE/Common/MouseHookWrapper.cs

Lines changed: 0 additions & 104 deletions
This file was deleted.

0 commit comments

Comments
 (0)