33using System . ComponentModel ;
44using System . Diagnostics ;
55using System . Linq ;
6- using System . Runtime . InteropServices ;
7- using System . Windows . Forms ;
86using Rubberduck . Common . Hotkeys ;
97using Rubberduck . Common . WinAPI ;
108using Rubberduck . Settings ;
119using Rubberduck . UI . Command ;
1210using NLog ;
1311using Rubberduck . VBEditor . SafeComWrappers . Abstract ;
12+ using Rubberduck . VBEditor . WindowsApi ;
1413
1514namespace Rubberduck . Common
1615{
17- public class RubberduckHooks : IRubberduckHooks
16+ public class RubberduckHooks : SubclassingWindow , IRubberduckHooks
1817 {
19- private readonly IntPtr _mainWindowHandle ;
20- private readonly IntPtr _oldWndProc ;
21- // This can't be local - otherwise RawInput can't call it in the subclassing chain.
22- // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
23- private readonly User32 . WndProc _newWndProc ;
24- private RawInput _rawinput ;
25- private RawKeyboard _kb ;
26- private RawMouse _mouse ;
2718 private readonly IGeneralConfigService _config ;
2819 private readonly IEnumerable < CommandBase > _commands ;
2920 private readonly IList < IAttachable > _hooks = new List < IAttachable > ( ) ;
3021 private static readonly Logger Logger = LogManager . GetCurrentClassLogger ( ) ;
3122
3223 public RubberduckHooks ( IVBE vbe , IGeneralConfigService config , IEnumerable < CommandBase > commands )
24+ : base ( ( IntPtr ) vbe . MainWindow . HWnd , ( IntPtr ) vbe . MainWindow . HWnd )
3325 {
34- var mainWindow = vbe . MainWindow ;
35- {
36- _mainWindowHandle = ( IntPtr ) mainWindow . HWnd ;
37- }
38-
39- _newWndProc = WindowProc ;
40- _oldWndProc = User32 . SetWindowLong ( _mainWindowHandle , ( int ) WindowLongFlags . GWL_WNDPROC , Marshal . GetFunctionPointerForDelegate ( _newWndProc ) ) ;
41-
4226 _commands = commands ;
4327 _config = config ;
4428 }
@@ -56,18 +40,6 @@ public void HookHotkeys()
5640 var config = _config . LoadConfiguration ( ) ;
5741 var settings = config . UserSettings . HotkeySettings ;
5842
59- _rawinput = new RawInput ( _mainWindowHandle ) ;
60-
61- var kb = ( RawKeyboard ) _rawinput . CreateKeyboard ( ) ;
62- _rawinput . AddDevice ( kb ) ;
63- kb . RawKeyInputReceived += Keyboard_RawKeyboardInputReceived ;
64- _kb = kb ;
65-
66- var mouse = ( RawMouse ) _rawinput . CreateMouse ( ) ;
67- _rawinput . AddDevice ( mouse ) ;
68- mouse . RawMouseInputReceived += Mouse_RawMouseInputReceived ;
69- _mouse = mouse ;
70-
7143 foreach ( var hotkey in settings . Settings . Where ( hotkey => hotkey . IsEnabled ) )
7244 {
7345 RubberduckHotkey assigned ;
@@ -76,35 +48,12 @@ public void HookHotkeys()
7648 var command = Command ( assigned ) ;
7749 Debug . Assert ( command != null ) ;
7850
79- AddHook ( new Hotkey ( _mainWindowHandle , hotkey . ToString ( ) , command ) ) ;
51+ AddHook ( new Hotkey ( Hwnd , hotkey . ToString ( ) , command ) ) ;
8052 }
8153 }
8254 Attach ( ) ;
8355 }
8456
85- private void Mouse_RawMouseInputReceived ( object sender , RawMouseEventArgs e )
86- {
87- if ( e . UlButtons . HasFlag ( UsButtonFlags . RI_MOUSE_LEFT_BUTTON_UP ) || e . UlButtons . HasFlag ( UsButtonFlags . RI_MOUSE_RIGHT_BUTTON_UP ) )
88- {
89- OnMessageReceived ( this , HookEventArgs . Empty ) ;
90- }
91- }
92-
93- // keys that change the current selection.
94- private static readonly HashSet < Keys > NavKeys = new HashSet < Keys >
95- {
96- Keys . Up , Keys . Down , Keys . Left , Keys . Right , Keys . PageDown , Keys . PageUp , Keys . Enter
97- } ;
98-
99- private void Keyboard_RawKeyboardInputReceived ( object sender , RawKeyEventArgs e )
100- {
101- // note: handling *all* keys causes annoying RTrim of current line, making editing code a PITA.
102- if ( e . Message == WM . KEYUP && NavKeys . Contains ( ( Keys ) e . VKey ) )
103- {
104- OnMessageReceived ( this , HookEventArgs . Empty ) ;
105- }
106- }
107-
10857 public IEnumerable < IAttachable > Hooks { get { return _hooks ; } }
10958
11059 public void AddHook ( IAttachable hook )
@@ -182,60 +131,41 @@ private void hook_MessageReceived(object sender, HookEventArgs e)
182131 OnMessageReceived ( sender , e ) ;
183132 }
184133
185- public void Dispose ( )
186- {
187- Detach ( ) ;
188- User32 . SetWindowLong ( _mainWindowHandle , ( int ) WindowLongFlags . GWL_WNDPROC , _oldWndProc ) ;
189- _mouse . RawMouseInputReceived -= Mouse_RawMouseInputReceived ;
190- _kb . RawKeyInputReceived -= Keyboard_RawKeyboardInputReceived ;
191- }
192-
193- private IntPtr WindowProc ( IntPtr hWnd , uint uMsg , IntPtr wParam , IntPtr lParam )
134+ public override int SubClassProc ( IntPtr hWnd , IntPtr msg , IntPtr wParam , IntPtr lParam , IntPtr uIdSubclass , IntPtr dwRefData )
194135 {
195- try
196- {
197- var suppress = false ;
198- switch ( ( WM ) uMsg )
199- {
200- case WM . HOTKEY :
201- suppress = hWnd == _mainWindowHandle && HandleHotkeyMessage ( wParam ) ;
202- break ;
203- case WM . SETFOCUS :
136+ var suppress = false ;
137+ switch ( ( WM ) msg )
138+ {
139+ case WM . HOTKEY :
140+ suppress = hWnd == Hwnd && HandleHotkeyMessage ( wParam ) ;
141+ break ;
142+ case WM . SETFOCUS :
143+ Attach ( ) ;
144+ break ;
145+ case WM . RUBBERDUCK_CHILD_FOCUS :
146+ if ( lParam == IntPtr . Zero )
147+ {
148+ Detach ( ) ;
149+ }
150+ else
151+ {
204152 Attach ( ) ;
205- break ;
206- case WM . RUBBERDUCK_CHILD_FOCUS :
207- if ( lParam == IntPtr . Zero )
208- {
209- Detach ( ) ;
210- }
211- else
212- {
213- Attach ( ) ;
214- }
215- return IntPtr . Zero ;
216- case WM . NCACTIVATE :
217- if ( wParam == IntPtr . Zero )
218- {
219- Detach ( ) ;
220- }
221- break ;
222- case WM . CLOSE :
223- case WM . RUBBERDUCK_SINKING :
224- suppress = true ;
153+ }
154+ suppress = true ;
155+ break ;
156+ case WM . NCACTIVATE :
157+ if ( wParam == IntPtr . Zero )
158+ {
225159 Detach ( ) ;
226- break ;
227- }
228-
229- return suppress
230- ? IntPtr . Zero
231- : User32 . CallWindowProc ( _oldWndProc , hWnd , uMsg , wParam , lParam ) ;
232- }
233- catch ( Exception exception )
234- {
235- Logger . Error ( exception ) ;
236- }
237-
238- return IntPtr . Zero ;
160+ }
161+ break ;
162+ case WM . CLOSE :
163+ case WM . DESTROY :
164+ case WM . RUBBERDUCK_SINKING :
165+ Detach ( ) ;
166+ break ;
167+ }
168+ return suppress ? 0 : base . SubClassProc ( hWnd , msg , wParam , lParam , uIdSubclass , dwRefData ) ;
239169 }
240170
241171 private bool HandleHotkeyMessage ( IntPtr wParam )
0 commit comments