Skip to content

Commit a0d9745

Browse files
committed
Makes posible to execute the shortcuts when an app that hook the keyboard is active
1 parent 7fe08b0 commit a0d9745

File tree

4 files changed

+138
-7
lines changed

4 files changed

+138
-7
lines changed

Static/KeyboardManager.cs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,15 @@ public KeyEvent(KeyboardShortcut key)
4040

4141
public static void DisableSystemKeys(IEnumerable<IHandleKeyboardHookControl> controls)
4242
{
43-
// Note: This does not work in the VS host environment. To run in debug mode:
44-
// Project -> Properties -> Debug -> Uncheck "Enable the Visual Studio hosting process"
45-
IntPtr hInstance = Marshal.GetHINSTANCE(App.Current.GetType().Module);
46-
HandlerControls = controls;
47-
_handler = new LowLevelKeyboardProc(KeyboardHookHandler);
48-
CurrentHook = SetWindowsHookEx(WH_KEYBOARD_LL, _handler, hInstance, 0);
43+
if (CurrentHook == IntPtr.Zero)
44+
{
45+
// Note: This does not work in the VS host environment. To run in debug mode:
46+
// Project -> Properties -> Debug -> Uncheck "Enable the Visual Studio hosting process"
47+
IntPtr hInstance = Marshal.GetHINSTANCE(App.Current.GetType().Module);
48+
HandlerControls = controls;
49+
_handler = new LowLevelKeyboardProc(KeyboardHookHandler);
50+
CurrentHook = SetWindowsHookEx(WH_KEYBOARD_LL, _handler, hInstance, 0);
51+
}
4952
}
5053

5154
public static void EnableSystemKeys()

Static/WindowsManager.cs

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Diagnostics;
4+
using System.IO;
5+
using System.Linq;
6+
using System.Runtime.InteropServices;
7+
using System.Text;
8+
using System.Threading.Tasks;
9+
10+
namespace VolumeSwitch
11+
{
12+
public class WindowsManager
13+
{
14+
static WindowsManager()
15+
{
16+
var file = MustHookFile;
17+
MustHookFileWatcher = new FileSystemWatcher(file.DirectoryName, file.Name);
18+
MustHookFileWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName;
19+
MustHookFileWatcher.Changed += OnMustHookFileChanged;
20+
MustHookFileWatcher.Created += OnMustHookFileChanged;
21+
MustHookFileWatcher.Deleted += OnMustHookFileChanged;
22+
MustHookFileWatcher.EnableRaisingEvents = true;
23+
}
24+
25+
//https://stackoverflow.com/a/10280800
26+
private const uint WINEVENT_OUTOFCONTEXT = 0;
27+
private const uint EVENT_SYSTEM_FOREGROUND = 3;
28+
private static readonly FileSystemWatcher MustHookFileWatcher;
29+
private static readonly string MustHookFileName = "hook";
30+
private static FileInfo MustHookFile
31+
{
32+
get
33+
{
34+
return new FileInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, MustHookFileName));
35+
}
36+
}
37+
38+
delegate void WinEventHookProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
39+
private static WinEventHookProc _handler;
40+
private static IntPtr CurrentHook = IntPtr.Zero;
41+
42+
[DllImport("user32.dll")]
43+
private static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out uint ProcessId);
44+
[DllImport("user32.dll")]
45+
static extern IntPtr GetForegroundWindow();
46+
47+
[DllImport("user32.dll")]
48+
static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, WinEventHookProc lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);
49+
[DllImport("user32.dll")]
50+
private static extern bool UnhookWinEvent(IntPtr hhk);
51+
52+
private static bool IsCurrentAppActive()
53+
{
54+
return App.Handler == GetForegroundWindow();
55+
}
56+
57+
private static bool ShouldMonitorActiveAppChange()
58+
{
59+
var file = MustHookFile;
60+
return !IsCurrentAppActive() && file.Exists && !string.IsNullOrEmpty(File.ReadAllText(file.FullName));
61+
}
62+
63+
public static void StartMonitoringActiveAppChangesIfNeeded()
64+
{
65+
if (ShouldMonitorActiveAppChange() && CurrentHook == IntPtr.Zero)
66+
{
67+
_handler = new WinEventHookProc(OnActiveWindowChanged);
68+
CurrentHook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, _handler, 0, 0, WINEVENT_OUTOFCONTEXT);
69+
}
70+
}
71+
72+
public static void StopMonitoringActiveAppChanges()
73+
{
74+
if (CurrentHook != IntPtr.Zero)
75+
{
76+
UnhookWinEvent(CurrentHook);
77+
CurrentHook = IntPtr.Zero;
78+
KeyboardManager.EnableSystemKeys();
79+
}
80+
}
81+
82+
private static void OnActiveWindowChanged(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
83+
{
84+
try
85+
{
86+
bool disabled = false;
87+
var file = MustHookFile;
88+
if (file.Exists)
89+
{
90+
var processesToHook = File.ReadAllLines(file.FullName);
91+
if (processesToHook.Length > 0)
92+
{
93+
uint pid;
94+
GetWindowThreadProcessId(hwnd, out pid);
95+
Process p = Process.GetProcessById((int)pid);
96+
var activeProcessFile = new FileInfo(p.MainModule.FileName);
97+
if (processesToHook.Contains(activeProcessFile.Name))
98+
{
99+
KeyboardManager.DisableSystemKeys(null);
100+
disabled = true;
101+
}
102+
}
103+
}
104+
if (!disabled && !IsCurrentAppActive())
105+
{
106+
KeyboardManager.EnableSystemKeys();
107+
}
108+
}
109+
catch { }
110+
}
111+
112+
private static void OnMustHookFileChanged(object sender, FileSystemEventArgs e)
113+
{
114+
App.Current.Dispatcher.BeginInvoke((Action)(() =>
115+
{
116+
if (ShouldMonitorActiveAppChange())
117+
{
118+
StartMonitoringActiveAppChangesIfNeeded();
119+
}
120+
else
121+
{
122+
StopMonitoringActiveAppChanges();
123+
}
124+
}));
125+
}
126+
}
127+
}

View/MainWindow.xaml.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ protected override void OnSourceInitialized(EventArgs e)
3131
base.OnSourceInitialized(e);
3232
App.RegisterWindow(this);
3333
this.DataContext = new MainWindowViewModel(this);
34-
KeyboardManager.DisableSystemKeys(this.VisualTreeChildren<IHandleKeyboardHookControl>().ToList());
3534
}
3635

3736

@@ -45,6 +44,7 @@ protected override void OnDeactivated(EventArgs e)
4544
{
4645
base.OnDeactivated(e);
4746
KeyboardManager.EnableSystemKeys();
47+
WindowsManager.StartMonitoringActiveAppChangesIfNeeded();
4848
}
4949

5050
protected override void OnClosing(CancelEventArgs e)

VolumeSwitch.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
<Compile Include="Model\Config.cs" />
6464
<Compile Include="Extensions\ExtensionsOfDependencyObject.cs" />
6565
<Compile Include="Model\KeyboardShortcutAction.cs" />
66+
<Compile Include="Static\WindowsManager.cs" />
6667
<Compile Include="View\Controls\IHandleKeyboardHookControl.cs" />
6768
<Compile Include="Static\KeyboardManager.cs" />
6869
<Compile Include="NotifyIcon\NativeMethods.cs" />

0 commit comments

Comments
 (0)