Skip to content

Commit

Permalink
Merge branch 'release/1.1.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
markellus committed Jun 18, 2017
2 parents 30a254b + 84b4371 commit 90385da
Show file tree
Hide file tree
Showing 10 changed files with 244 additions and 134 deletions.
6 changes: 3 additions & 3 deletions AltF4/AltF4.csproj
Expand Up @@ -52,15 +52,15 @@
<Reference Include="UIAutomationTypes" />
</ItemGroup>
<ItemGroup>
<Compile Include="AltF4Handler.cs" />
<Compile Include="NativeMethods.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SafeList.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="app.manifest" />
<None Include="Install.cmd">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
107 changes: 107 additions & 0 deletions AltF4/AltF4Handler.cs
@@ -0,0 +1,107 @@
/**********************************************
* Extreme AltF4 *
* (C) 2017 Marcel Bulla *
* https://github.com/markellus/Extreme-AltF4 *
* See file LICENSE for license information *
**********************************************/

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using static AltF4.NativeMethods;

namespace AltF4
{
internal class AltF4Handler
{
public static AltF4Handler Get()
{
return _instance;
}

private static AltF4Handler _instance = new AltF4Handler();

private static SafeList<Keys> _listKeys;

private static IntPtr _hookID = IntPtr.Zero;

private bool _fired;

private LowLevelKeyboardProc _callback;

public event EventHandler OnAltF4;

private AltF4Handler()
{
_listKeys = new SafeList<Keys>();
_callback = HookCallback;
_hookID = SetHook(_callback);
_fired = false;
}

~AltF4Handler()
{
UnhookWindowsHookEx(_hookID);
}

private IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
{
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
GetModuleHandle(curModule.ModuleName), 0);
}
}
}

private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode < 0)
{
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}

int vkCode = Marshal.ReadInt32(lParam);
Keys code = (Keys)vkCode;

if (KeyDown(wParam))
{
_listKeys.SafeAdd(code);
}
else if (KeyUp(wParam))
{
_listKeys.SafeRemove(code);
}

if (_listKeys.Contains(Keys.F4) &&
(_listKeys.Contains(Keys.LMenu) || _listKeys.Contains(Keys.Alt)))
{
if(!_fired)
{
_fired = true;
OnAltF4?.Invoke(this, EventArgs.Empty);
}
return (IntPtr)1;
}
else
{
_fired = false;
}

return CallNextHookEx(_hookID, nCode, wParam, lParam);
}

private bool KeyDown(IntPtr wParam)
{
return (wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN);
}

private bool KeyUp(IntPtr wParam)
{
return (wParam == (IntPtr)WM_KEYUP || wParam == (IntPtr)WM_SYSKEYUP);
}
}
}
36 changes: 36 additions & 0 deletions AltF4/NativeMethods.cs
@@ -0,0 +1,36 @@
/**********************************************
* Extreme AltF4 *
* (C) 2017 Marcel Bulla *
* https://github.com/markellus/Extreme-AltF4 *
* See file LICENSE for license information *
**********************************************/

using System;
using System.Runtime.InteropServices;

namespace AltF4
{
internal static class NativeMethods
{
public const int WH_KEYBOARD_LL = 13;
public const int WM_KEYDOWN = 0x0100;
public const int WM_SYSKEYDOWN = 0x0104;
public const int WM_KEYUP = 0x0101;
public const int WM_SYSKEYUP = 0x0105;

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName);

internal delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
}
}
108 changes: 26 additions & 82 deletions AltF4/Program.cs
@@ -1,95 +1,52 @@
using System;
using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Windows.Automation;
using System.Collections.Generic;
using System.IO;

namespace AltF4
{
/// <summary>
/// Main class
/// </summary>
class Program
{
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private const int WM_SYSKEYDOWN = 0x0104;
private const int WM_KEYUP = 0x0101;
private const int WM_SYSKEYUP = 0x0105;
private static LowLevelKeyboardProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;

internal delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);

private static List<Keys> listKeys = new List<Keys>();

private static bool bKilled = false;
/// <summary>
/// The program which is currently in foreground.
/// </summary>
private static Process procFocus;

/// <summary>
/// Program entry method
/// </summary>
private static void Main(string[] args)
{
//check if the program is already running
Process[] _procRunning = Process.GetProcessesByName("AltF4");

if(_procRunning.Length > 1)
{
Environment.Exit(0);
}

//Add event handlers
AutomationFocusChangedEventHandler focusHandler = OnFocusChanged;
Automation.AddAutomationFocusChangedEventHandler(focusHandler);

_hookID = SetHook(_proc);
AltF4Handler.Get().OnAltF4 += OnAltF4;

//Start program loop
Application.Run();

UnhookWindowsHookEx(_hookID);
}

private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
private static void OnAltF4(object sender, EventArgs e)
{
if (nCode >= 0)
if (procFocus != null && !procFocus.HasExited)
{
int vkCode = Marshal.ReadInt32(lParam);
Keys code = (Keys)vkCode;

if (wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN)
try
{


if (!listKeys.Contains(code))
{
listKeys.Add(code);
}

if (listKeys.Contains(Keys.F4) &&
(listKeys.Contains(Keys.LMenu) || listKeys.Contains(Keys.Alt)))
{
if (!bKilled && procFocus != null && !procFocus.HasExited)
{
procFocus.Kill();
bKilled = true;
}
return (IntPtr)1;
}
procFocus.Kill();
}
else if (wParam == (IntPtr)WM_KEYUP || wParam == (IntPtr)WM_SYSKEYUP)
{
if (listKeys.Contains(code))
{
listKeys.Remove(code);
}

if (!listKeys.Contains(Keys.F4) &&
!listKeys.Contains(Keys.LMenu) &&
!listKeys.Contains(Keys.Alt))
{
bKilled = false;
}
}
}

return CallNextHookEx(_hookID, nCode, wParam, lParam);
}

private static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
GetModuleHandle(curModule.ModuleName), 0);
catch { }
}
}

Expand All @@ -101,19 +58,6 @@ private static void OnFocusChanged(object sender, AutomationFocusChangedEventArg
int processId = focusedElement.Current.ProcessId;
procFocus = Process.GetProcessById(processId);
}
}

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
}
}
}
8 changes: 4 additions & 4 deletions AltF4/Properties/AssemblyInfo.cs
Expand Up @@ -5,11 +5,11 @@
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("AltF4 Rage Quit Enabler")]
[assembly: AssemblyTitle("Extreme AltF4")]
[assembly: AssemblyDescription("Overrides Alt F4 to kill a process immediatly")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AltF4 Rage Quit Enabler")]
[assembly: AssemblyProduct("Extreme AltF4")]
[assembly: AssemblyCopyright("Copyright © Marcel Bulla 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
Expand All @@ -32,5 +32,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.1.0")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyVersion("1.1.0.0")]
[assembly: AssemblyFileVersion("1.1.0.0")]
30 changes: 30 additions & 0 deletions AltF4/SafeList.cs
@@ -0,0 +1,30 @@
/**********************************************
* Extreme AltF4 *
* (C) 2017 Marcel Bulla *
* https://github.com/markellus/Extreme-AltF4 *
* See file LICENSE for license information *
**********************************************/

using System.Collections.Generic;

namespace AltF4
{
internal class SafeList<T> : List<T>
{
public void SafeAdd(T item)
{
if (!this.Contains(item))
{
this.Add(item);
}
}

public void SafeRemove(T item)
{
if (this.Contains(item))
{
this.Remove(item);
}
}
}
}

0 comments on commit 90385da

Please sign in to comment.