Skip to content

Instantly share code, notes, and snippets.

@t-mat
Last active October 16, 2023 08:21
Show Gist options
  • Save t-mat/8771347 to your computer and use it in GitHub Desktop.
Save t-mat/8771347 to your computer and use it in GitHub Desktop.
Windows: keyrate - keyboard repeat rate configuration utility.
@setlocal enabledelayedexpansion & set "ARGS=%*" & powershell -nop -ex Bypass -c "Add-Type (gc '%~dpf0'|select -Skip 1|Out-String); exit [Program]::Main();" & exit /b !ERRORLEVEL!
// How can I increase the key repeat rate beyond the OS's limit?
// https://stackoverflow.com/a/11056655
using System;
using System.Linq;
using System.Runtime.InteropServices;
public static class Program {
[DllImport("shell32.dll")]
private static extern IntPtr CommandLineToArgvW(
[MarshalAs(UnmanagedType.LPWStr)] string lpCmdLine, out int pNumArgs);
[DllImport("kernel32.dll")]
private static extern IntPtr LocalFree(IntPtr hMem);
private static string[] GetArgs() {
string argStr = Environment.GetEnvironmentVariable("ARGS");
if (string.IsNullOrEmpty(argStr)) {
return new string[0];
}
int nArgs;
IntPtr argIntPtrs = CommandLineToArgvW(argStr, out nArgs);
if (argIntPtrs == IntPtr.Zero) {
return new string[0];
}
try {
var args = new string[nArgs];
for (int i = 0; i < nArgs; i++) {
IntPtr p = Marshal.ReadIntPtr(argIntPtrs, i * IntPtr.Size);
args[i] = Marshal.PtrToStringUni(p);
}
return args;
}
finally
{
LocalFree(argIntPtrs);
}
}
public static int Main() {
return KeyRate.Main(GetArgs());
}
}
public static class KeyRate {
[DllImport("user32.dll", SetLastError = false)]
internal static extern bool SystemParametersInfo(uint uiAction, uint uiParam, ref FILTERKEYS pvParam, uint fWinIni);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
internal struct FILTERKEYS {
public uint cbSize;
public uint dwFlags;
public uint iWaitMSec;
public uint iDelayMSec;
public uint iRepeatMSec;
public uint iBounceMSec;
}
private const uint SPI_SETFILTERKEYS = 0x0033;
private const uint FKF_FILTERKEYSON = 0x0001;
private const uint FKF_AVAILABLE = 0x0002;
private static void Usage() {
Console.WriteLine("Usage: keyrate <delay ms> <repeat ms>");
}
public static int Main(string[] args) {
if(args.Length != 0 && args.Length != 2) {
Usage();
Console.WriteLine("Invoke with no parameters to disable keyrate acceleration.");
return 1; // exit code => !ERRORLEVEL!
}
FILTERKEYS fk;
fk.cbSize = 0;
fk.dwFlags = 0;
fk.iWaitMSec = 0;
fk.iDelayMSec = 0;
fk.iRepeatMSec = 0;
fk.iBounceMSec = 0;
if(args.Length == 2) {
fk.iDelayMSec = (uint) Math.Max(0, Convert.ToInt32(args[0]));
fk.iRepeatMSec = (uint) Math.Max(0, Convert.ToInt32(args[1]));
fk.dwFlags = FKF_FILTERKEYSON | FKF_AVAILABLE;
Console.WriteLine("Setting keyrate: delay={0}ms, rate={1}ms"
, fk.iDelayMSec, fk.iRepeatMSec);
} else {
Usage();
Console.WriteLine("No parameters given: disabling.");
}
fk.cbSize = (uint) Marshal.SizeOf(fk);
if(! SystemParametersInfo(SPI_SETFILTERKEYS, 0, ref fk, 0)) {
Console.WriteLine("System call failed.\nUnable to set keyrate.");
return 1; // exit code => !ERRORLEVEL!
}
return 0; // exit code => !ERRORLEVEL!
}
}
@t-mat
Copy link
Author

t-mat commented Oct 16, 2023

Looks good, nice work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment