Skip to content

Commit

Permalink
Init
Browse files Browse the repository at this point in the history
  • Loading branch information
Brainterminator committed Jul 29, 2024
0 parents commit 8cb85fe
Show file tree
Hide file tree
Showing 6 changed files with 903 additions and 0 deletions.
674 changes: 674 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

173 changes: 173 additions & 0 deletions Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
using System;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace KeyboardHook
{
class Program
{
private static LowLevelKeyboardProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
private static Keys currentKey = Keys.None;
private static Keys haltedKey = Keys.None;
private static bool inSimulation = false;

private static NotifyIcon trayIcon;
private static ContextMenuStrip trayMenu;

static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);

trayMenu = new ContextMenuStrip();
trayMenu.Items.Add("Activate Hook", null, OnActivateHook);
trayMenu.Items.Add("Deactivate Hook", null, OnDeactivateHook);
trayMenu.Items.Add("Exit", null, OnExit);

trayIcon = new NotifyIcon();
trayIcon.Text = "Keyboard Hook";
trayIcon.Icon = new Icon("Resources/straver.ico");

trayIcon.ContextMenuStrip = trayMenu;
trayIcon.Visible = true;

Application.Run();
}

private static void OnActivateHook(object sender, EventArgs e)
{
if (_hookID == IntPtr.Zero)
{
_hookID = SetHook(_proc);
MessageBox.Show("Keyboard hook activated.", "Info", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
MessageBox.Show("Keyboard hook is already activated.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}

private static void OnDeactivateHook(object sender, EventArgs e)
{
if (_hookID != IntPtr.Zero)
{
UnhookWindowsHookEx(_hookID);
_hookID = IntPtr.Zero;
MessageBox.Show("Keyboard hook deactivated.", "Info", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
MessageBox.Show("Keyboard hook is not active.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}

private static void OnExit(object sender, EventArgs e)
{
if (_hookID != IntPtr.Zero)
{
UnhookWindowsHookEx(_hookID);
}
trayIcon.Visible = false;
Application.Exit();
}

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);
}
}

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

private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && !inSimulation)
{
int vkCode = Marshal.ReadInt32(lParam);
Keys key = (Keys)vkCode;
if (key == Keys.A || key == Keys.D)
{
if (wParam == (IntPtr)WM_KEYDOWN)
{
if (currentKey != key)
{
if (currentKey != Keys.None)
{
haltedKey = currentKey;
SimulateKeyUp(currentKey);
}
currentKey = key;
SimulateKeyDown(currentKey);
}
}
else if (wParam == (IntPtr)WM_KEYUP)
{
if (key == currentKey)
{
SimulateKeyUp(currentKey);
if (haltedKey != key && haltedKey != Keys.None)
{
currentKey = haltedKey;
SimulateKeyDown(currentKey);
}
else
{
currentKey = Keys.None;
}
}
if (key == haltedKey && haltedKey != Keys.None)
{
haltedKey = Keys.None;
}
}
return (IntPtr)1;
}
}

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

private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private const int WM_KEYUP = 0x0101;

[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);

[DllImport("user32.dll", SetLastError = true)]
private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);

private const int KEYEVENTF_EXTENDEDKEY = 0x0001;
private const int KEYEVENTF_KEYUP = 0x0002;

private static void SimulateKeyDown(Keys key)
{
inSimulation = true;
keybd_event((byte)key, 0, KEYEVENTF_EXTENDEDKEY, UIntPtr.Zero);
inSimulation = false;
}

private static void SimulateKeyUp(Keys key)
{
inSimulation = true;
keybd_event((byte)key, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, UIntPtr.Zero);
inSimulation = false;
}
}
}
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

# Straver <img src="https://raw.githubusercontent.com/Brainterminator/Straver/main/Resources/straver.ico" alt="Straver Icon" style="width:20px; vertical-align:middle;" />

Snap-Tap alternative for non-Razer Keyboards. This software prevents overlapping inputs of the A and D keys.

## How to use

Straver adds a small icon to your taskbar, where you can conveniently activate and deactivate the hook.
<img src="https://lowearthorbit.de/straver/straver-guide.png" />

## License

Straver is licensed under the terms of the GNU General Public License version 3. You can find a copy of the terms and conditions of that license [here](https://www.gnu.org/licenses/gpl-3.0.txt).

## Downloads

- [Public builds of Straver](https://github.com/Brainterminator/Straver/releases/tag/1.0)
Binary file added Resources/straver.ico
Binary file not shown.
14 changes: 14 additions & 0 deletions Straver.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
<ApplicationIcon>Resources\straver.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<None Update="Resources\straver.ico">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
25 changes: 25 additions & 0 deletions Straver.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.002.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Straver", "Straver.csproj", "{AFFFAAE0-70D3-4605-A5F8-0B54B776233D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AFFFAAE0-70D3-4605-A5F8-0B54B776233D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AFFFAAE0-70D3-4605-A5F8-0B54B776233D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AFFFAAE0-70D3-4605-A5F8-0B54B776233D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AFFFAAE0-70D3-4605-A5F8-0B54B776233D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {5F05AF47-067A-404F-BEE5-B5A4911B2995}
EndGlobalSection
EndGlobal

0 comments on commit 8cb85fe

Please sign in to comment.