Skip to content

Instantly share code, notes, and snippets.

@apfelchips
Last active June 21, 2024 19:13
Show Gist options
  • Save apfelchips/e30321f33abc1eb1a481e83b1e79d5c5 to your computer and use it in GitHub Desktop.
Save apfelchips/e30321f33abc1eb1a481e83b1e79d5c5 to your computer and use it in GitHub Desktop.
First remap modifier keys with sharpkeys; AHK script has to run as Administrator to work on System Windows / Apps running as Administrator; see Watchdog ScheduledTask below, when you do this make sure to remove the inherited file permissions from C:/tools and only allow administrators write access.
;#NoTrayIcon
TraySetIcon("accessibilitycpl.dll","6") ; Keyboard Icon
;#Persistent https://www.autohotkey.com/docs/commands/_Persistent.htm
SetWorkingDir(A_ScriptDir) ; Ensures a consistent starting directory.
#SingleInstance force
;#InstallKeybdHook ; see: https://www.autohotkey.com/docs/v1/lib/_HotkeyModifierTimeout.htm
; Debugging
; #Warn All, OutputDebug ; Show Warnings on DebugView
; src: https://gist.github.com/apfelchips/e30321f33abc1eb1a481e83b1e79d5c5/
; doc:
; https://www.ahkgen.com/
; https://autohotkey.com/docs/Hotkeys.htm
; https://autohotkey.com/docs/KeyList.htm
; https://www.autohotkey.com/docs/commands/Send.htm
; Ref https://github.com/rbreaves/kinto/blob/master/windows/kinto.ahk
; Ref https://autohotkey.com/board/topic/60675-osx-style-command-keys-in-windows/
; Ref https://gist.github.com/trevoreyre/8df3a186bb18df4b17d5417a5d1143ad
; Ref https://github.com/Drugoy/Autohotkey-scripts-.ahk
; ^ = Control
; ! = Alt
; + = Shift
; # = Windows
; * = Wildcard / ignore Modifiers
; $ = no Recursion
; ~ = no Key Masking
; sc063 = Thinkpad FN
; sharpkeys: https://github.com/randyrants/sharpkeys/releases/
; online .reg remap generator: https://n8ta.com/projects/windows_key_remapper.html
; LWin --> LALT
; LAlt --> RControl
; optional (right side)
; RAlt --> RControl
; RWin --> RAlt
; AppsKey --> RWin
; optional (needed for AppleKeyboardLayoutMode)
; LControl --> 0x005C
; Remap keys back
sc005C::LControl
; define application groups
;GroupAdd AltTabWindow, ahk_class MultitaskingViewFrame ; Windows 10
;GroupAdd AltTabWindow, ahk_class TaskSwitcherWnd ; Windows Vista, 7, 8.1
;GroupAdd AltTabWindow, ahk_class #32771 ; Older, or with classic alt-tab enabled
ResetModifiers(){
Send("{Shift up}")
Send("{Control up}")
Send("{LControl up}")
Send("{RControl up}")
Send("{Alt up}")
Send("{LWin up}")
Send("{RWin up}")
Send("{CapsLock up}")
SetStoreCapsLockMode( "Off" )
SetCapsLockState( "AlwaysOff" )
return
}
resetcounter:=0
if ( resetcounter = 0 ) {
ResetModifiers( )
resetcounter++
}
; CapsLock Protection
+CapsLock::CapsLock
CapsLock::Ctrl
; TODO: Find AutoElevate replacement
;AutoElevate := "true"
; src: https://autohotkey.com/board/topic/46526-run-as-administrator-xpvista7-a-isadmin-params-lib/?p=289601
Log(msg){
OutputDebug("[AHK] " Msg)
}
; #SetTitleMatchMode RegEx breaks too much / has undefined behaviour
WinActiveProcessRegEx(regexNeedle, comfort:=true){
try {
tmp := WinGetProcessName("A")
if (comfort){
regexNeedle := "i)^" . regexNeedle . "$"
}
return RegExMatch(tmp, regexNeedle)
} catch as e {
return false
}
}
WinActiveClassRegEx(regexNeedle, comfort:=true){
try {
tmp := WinGetClass("A")
if (comfort){
regexNeedle := "i)^" . regexNeedle . "$"
}
return RegExMatch(tmp, regexNeedle)
} catch as e {
return false
}
}
WinActiveTitleRegEx(regexNeedle, comfort := true){
try {
tmp := WinGetTitle("A")
if (comfort){
regexNeedle := "i)" . regexNeedle
}
return RegExMatch(tmp, regexNeedle)
} catch as e {
return false
}
}
CountWindows(){
owindows := WinGetList(,,,)
awindows := Array()
windows := owindows.Length
For v in owindows {
awindows.Push(v)
}
wCount := 0
wTitleOut := ""
Loop awindows.Length
{
id := awindows[A_Index]
wTitle := WinGetTitle("ahk_id " id)
;wTitleOut .= wTitle . "`n"
if (wTitle != "") {
wCount += 1
}
}
;MsgBox, %wCount%
return wCount
}
WaitForWindowChange(){
If (WinActiveClassRegEx("awindows.Length\.UI\.Core\.CoreWindow")){
return
}
ErrorLevel := !WinWaitNotActive("A")
return
}
;reset all modifiers on escape
*~Esc::
{
Send("{Control up}")
Send("{LControl up}")
Send("{RControl up}")
Send("{Shift up}")
Send("{Alt up}")
Send("{LWin up}")
Send("{RWin up}")
;Send {AppsKey up}
Send("{CapsLock up}")
SetCapsLockState("Off")
;KeyHistory
}
/**
* Disable Alt key acceleration.
* These next two lines are very important. You have to change the "menu mask
* key" away from being Control, to something that won't result in cross-talk.
* https://autohotkey.com/boards/viewtopic.php?f=76&t=57683
*/
; Send{Alt up}{sc0EA up}{sc0E9 up} when using alt
A_MenuMaskKey := "vk07" ; vk07 is unassigned
;#UseHook On ; https://www.autohotkey.com/docs/commands/_UseHook.htm
~LAlt::
{
SendInput("{Blind}{sc0E9}")
ErrorLevel := !KeyWait("LAlt") ; this wasit for the key to be RELEASED. So that it doesn't keep spamming SC0E9 (as seen from an AHK window Key history and script info... window.)
SendInput("{Blind}{sc0EA}")
}
~RAlt::
{
SendInput("{Blind}{sc0E9}")
ErrorLevel := !KeyWait("RAlt") ; so that it doesn't keep spamming SC0E9
SendInput("{Blind}{sc0EA}")
;#UseHook Off
}
#HotIf ( WinActiveProcessRegEx("ConEmu(64)?\.exe") )
~LAlt::
{
SendInput("{Blind}")
}
~RAlt::
{
SendInput("{Blind}")
}
#HotIf
; rctrl+Tab --> Expose
+F11::
>^Tab::
>^+Tab::
;$!<Tab::
;$!<+Tab::
{
;KeyWait LAlt
SendInput("#{Tab}")
;Send("#{Tab}")
Send("{Control up}") ; sometimes get stuck here
; Send("{Alt up}{sc0EA up}{sc0E9 up}{LWin down}{Tab}{LWin up}")
}
; FIXME: somethimes hangs
; Command-Tab --> Switch windows
; Ref: https://autohotkey.com/board/topic/148298-ctrl-tab-ctrl-shift-tab-for-alttabshiftalttab-task-switching-windows-10/
; https://www.autohotkey.com/docs/Hotkeys.htm#AltTabRemarks
;#HotIf ( CountWindows() > 0 )
; >^Tab::
; {
; Send("{Alt down}{Tab}")
; }
; >^+Tab::
; {
; Send("{Alt down}{Shift down}{Tab}{Shift up}")
; }
;#HotIf
;#HotIf ( WinExist("ahk_class MultitaskingViewFrame") )
; ~sc0EA up::
; ~sc0E9 up::
; ~*Alt up::
; ~*Esc::
; {
; Send("{Control up}") ; RControl up or LControl up don't get detected reliably!!!
; Send("{Alt up}")
; }
;#HotIf
; disable StartMenu on Command+Escape
$>^Escape::
{
SendInput("+{Escape}")
}
; StartMenu aka Spotlight light --> Use Powertoys Run instead
;>^Space::
;{
;Send {blind}^<{Esc}
;Send {blind}#
;Send {F15}
;}
; Command+Shift+V - Pure / PlainText Clipboard / Paste
$>^+v::
{
wholeclipboard:=ClipboardAll()
global A_Clipboard := A_Clipboard
Sleep(100) ; wait for clipboard to be cleansed
Send("^{v}")
Sleep(100) ; wait before restoring original clipboard content
global A_Clipboard:=wholeclipboard
}
; Command+Shift+opt+V - Pure / PlainText Clipboard / Paste
$>^+!v::
{
wholeclipboard:=ClipboardAll()
global A_Clipboard := A_Clipboard
;Clipboard := StrReplace(Clipboard, "\", " ")
A_Clipboard := StrReplace(A_Clipboard, "`r`n", "")
Sleep(100) ; wait for clipboard to be cleansed
Send("^{v}")
Sleep(100) ; wait before restoring original clipboard content
global A_Clipboard:=wholeclipboard
}
; Command-M / Command-H - Minimize active window
$>^m::
$>^h::
{
WinMinimize("A")
}
; Command-R - Reload
$>^r::
{
Send("{F5}")
}
$>^q::
$!f4::
{
if ( WinActiveProcessRegEx("notes2\.exe") or ( WinActiveProcessRegEx("Outlook\.exe") and WinActiveTitleRegEx("- Outlook$") ) or WinActiveProcessRegEx("PSRClient\.exe") or WinActiveTitleRegEx("^Valuemation") ){
WinMinimize("A")
} else if (WinActiveProcessRegEx("explorer\.exe") and ( WinActiveClassRegEx("Progman") or WinActiveClassRegEx("WorkerW") or WinActiveClassRegEx("Shell_TrayWnd") )) {
; do nothing to prevent opening the shutdown dialog
} else {
Send("{LAlt down}{F4}{LAlt up}")
;WinClose, A
}
}
; "force close"
$>^!<q::
{
WinKill("A")
}
$#+w:: ; Logitech Options Gesture Mapping
$>^w::
{
if ( WinActiveProcessRegEx("KeePassXC\.exe")
or WinActiveProcessRegEx("SumatraPDF\.exe")
or WinActiveProcessRegEx("mdview\.exe")
or WinActiveProcessRegEx("AutoHotkey\.exe")
or WinActiveClassRegEx("Photo_Lightweight_Viewer")
or WinActiveClassRegEx("TaskManagerWindow")
or (WinActiveProcessRegEx("Outlook\.exe") and not ( WinActiveTitleRegEx("- Outlook$") ))
or (WinActiveProcessRegEx("ApplicationFrameHost\.exe") and not WinActiveTitleRegEx("- Remote Desktop$")) ; UWP apps
or (WinActiveProcessRegEx("explorer\.exe") and ( not ( WinActiveClassRegEx("Progman") or WinActiveClassRegEx("WorkerW") or WinActiveClassRegEx("Shell_TrayWnd") ))) )
{
WinClose("A")
} else if ( WinActiveProcessRegEx("WindowsTerminal\.exe") ){
Send("+^{w}")
} else if ( WinActiveProcessRegEx("PSRClient\.exe") ){
Send("{Esc}")
} else if ( WinActiveTitleRegEx("- Outlook$") or WinActiveTitleRegEx("^Valuemation") or WinActiveProcessRegEx("Teams\.exe") or WinActiveProcessRegEx("ms-teams\.exe") ){
WinMinimize("A")
} else if ( WinActiveProcessRegEx("ConEmu(64)?\.exe")){ ; Programs that can differentiate between LControl <=> RControl
Send("{RControl down}{w}{RControl up}")
} else {
Send("^{w}")
Send("{Control up}") ; sometimes get stuck here
}
}
; Sublime Notes Shortcut
;#HotIf ( WinActiveProcessRegEx("sublime_text\.exe") and WinActiveTitleRegEx("\(notes\).-.Sublime.Text$"))
; !Space::
; {
; Send ^{p}
; }
;#HotIf
;!Space::
;{
; ;; SetTitleMatchMode 3
; ;; DetectHiddenWindows, On
; ;; WinGet, obsidian_window_id, IDLast, ahk_exe Obsidian.exe
; ;; SetTitleMatchMode 1
;
; EnvGet, ProgFiles, ProgramFiles
; EnvGet, UserProfile, UserProfile
; RunWait %ProgramFiles%\Sublime Text\subl.exe %UserProfile%\Nextcloud\notes\notes.sublime-project,
; if ErrorLevel {
; Run notepad.exe ; fallback software tip: https://www.binaryfortress.com/NotepadReplacer/Download/
; }
; ;; DetectHiddenWindows, Off
;}
#HotIf (WinActiveProcessRegEx("Outlook\.exe") and ( WinActiveTitleRegEx("- Outlook$") ))
Ins::
{
Send("{LControl down}{q}{LControl up}")
}
^F::
{
Send("{Enter}")
Send("{F4}")
}
#HotIf
#HotIf (WinActiveProcessRegEx("Outlook\.exe"))
^F::
{
Send("{F4}")
}
#HotIf
#HotIf (WinActiveProcessRegEx("notes2\.exe") )
^<TAB::
^<+TAB::
{
Send("{blind}{F8}")
}
#HotIf
;; Windows Terminal RCtrl Shim | https://aka.ms/terminal-keybindings
#HotIf ( WinActiveProcessRegEx("WindowsTerminal\.exe"))
>^c:: Send("{blind}{Shift down}{c}{Shift up}")
>^v:: Send("{blind}{Shift down}{v}{Shift up}")
>^n:: Send("{blind}{Shift down}{n}{Shift up}")
>^t:: Send("{blind}{Shift down}{t}{Shift up}")
>^f:: Send("{blind}{Shift down}{f}{Shift up}")
>^a:: Send("{blind}{Shift down}{a}{Shift up}")
#HotIf
;; macOS text navigation
; Command-Shift-arrow navigation + highlight
;;>^+Left::Send("{Shift down}{Home}{Shift up}")
;;>^+Right::Send("{Shift down}{End}{Shift down}")
;;>^+Up::Send("{Control down}{Shift down}{Home}{Shift up}{Control up}")
;;>^+Down::Send("{Control down}{Shift down}{End}{Shift up}{Control up}")
;; Option-arrow navigation
;;!<Left::Send("{Control down}{Left}{Control up}")
;;!<Right::Send("{Control down}{Right}{Control up}")
;; Option-Shift-arrow navigation + highlight
;;!<+Left::Send("{Control down}{Shift down}{Left}{Shift up}{Control up}")
;;!<+Right::Send("{Control down}{Shift down}{Right}{Shift up}{Control up}")
; Command-D - Delete forward
;;>^d::Send("{Delete}
;; Command-Delete - Delete line
;;>^Backspace::Send("{Shift down}{Home}{Shift up}{Delete}")
;; Command-Shift-Delete - Delete line forward
;;>^+Backspace::Send("{Shift down}{End}{Shift up}{Delete}")
;; Option-Delete - Delete word
;;!Backspace::Send("{Control down}{Backspace}{Control up}")
;; Option-Shift-Delete - Delete word forward
;;!+Backspace::Send("{Control down}{Delete}{Control up}")
;; Screenshots
; https://docs.microsoft.com/en-us/windows/uwp/launch-resume/launch-screen-snipping
$+>^3::
$+>^4::
{
Run("explorer.exe ms-screenclip:")
;Run, C:\WINDOWS\system32\SnippingTool.exe /clip ; legacy Snipping Tool
}
;; Finder Emulation
#HotIf ( WinActiveProcessRegEx("explorer\.exe") and WinActiveClassRegEx("CabinetWClass") )
>^Left::
{
SendEvent("{RControl up}")
SendEvent("!{Left}")
}
>^Right::
{
SendEvent("{RControl up}")
SendEvent("!{Right}")
}
>^Up::
{
SendEvent("{RControl up}")
SendEvent("!{Up}")
}
>^Down::
{
SendEvent("{RControl up}")
SendEvent("!{Down}")
}
#HotIf
;; Affinity Suite RControl weirdness fix
#HotIf ( WinActiveProcessRegEx("photo\.exe") ) or ( WinActiveProcessRegEx("designer\.exe") ) or ( WinActiveProcessRegEx("publisher\.exe") )
>^d::
{
Send("^{d}")
}
#HotIf
#HotIf ( WinActiveProcessRegEx("explorer\.exe") )
$+Enter::
{
SendEvent("{F2}") ; rename action
}
$>^o::
{
Send("{Control up}")
SendEvent("{Control up}")
SendEvent("{Enter}")
}
$!>^i::
$>^i::
{
SendEvent("!{Enter}")
}
$^+.::
{
HiddenFiles_Status := RegRead("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced", "Hidden")
if (HiddenFiles_Status = 2){
RegWrite(1, "REG_DWORD", "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced", "Hidden")
Send("{F5}")
} else {
RegWrite(2, "REG_DWORD", "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced", "Hidden")
Send("{F5}")
}
}
$>^k:: ; connect to server
$>^+g:: ; goto file
{
if ( WinActiveClassRegEx("CabinetWClass") ){
SendEvent("{F4}")
} else if ( WinActiveClassRegEx("Progman") ){
Run("explore " A_MyDocuments "\..\")
Sleep(200)
SendEvent("{F4}")
}
}
$>^+Backspace::
$>^+Delete::
{
msgResult := MsgBox("`"Empty Recycle Bin?`"", "", 1)
if (msgResult = "Ok"){
FileRecycleEmpty()
}
}
#HotIf
; Media Controls
^F7::Send("{Media_Prev}")
^F8::Send("{Media_Play_Pause}")
^F9::Send("{Media_Next}")
^F10::Send("{Volume_Mute}")
^F11::Send("{Volume_Down}")
^F12::Send("{Volume_Up}")
; HotCorners
CoordMode("Mouse") ; mouse coords to screen
SetTimer(MouseCheck, 250) ; MouseCheck execution interval
MouseCheck(){
try {
if (!WinExist("A")) || (WinGetProcessName("A") == "LockApp.exe") { ; check if currently on windows lockscreen
return
}
}
catch as e {
return
}
static origx:=-1,origy:=-1 ; init values of origx|origy
MouseGetPos(&mx,&my)
if (mx=origx) && (my=origy) { ; check if mouse coordinates chaged
return
}
origx:=mx,origy:=my ; remember last coordinates
if (mx=0) && (my=0){ ; Top Left
sleep 500
MouseGetPos(&mx,&my)
if (mx=0) && (my=0){ ; mouse is still in the corner
;send the monitor into off mode
;SendMessage(0x112, 0xF170, 2, , "Program Manager")
MouseMove( 1, 1, 2, "R" )
DllCall("LockWorkStation")
}
return
} else if (mx=A_ScreenWidth-1) && (my=0){ ; Top Right
return
} else if (mx=0) && (my=A_ScreenHeight-1){ ; Bottom Left
return
} else if (mx=A_ScreenWidth-1) && (my=A_ScreenHeight-1){ ; Bottom Right
return
}
}
' Usage:
' wscript.exe //E:vbscript HiddentPowershell.vbs -ExecutionPolicy ByPass -File "C:\Program Files\Get-HelloWorld.ps1"
'
' Will run Powershell in a hidden console, like this:
' powershell.exe -ExecutionPolicy ByPass -File "C:\Program Files\Get-HelloWorld.ps1"
'
' More Info: https://github.com/UNT-CAS/HiddenPowershell
Set oShell = CreateObject("Wscript.Shell")
Const LOG_EVENT_SUCCESS = 0
Const LOG_EVENT_ERROR = 1
Const LOG_EVENT_INFORMATION = 4
Dim iExitStatus : iExitStatus = LOG_EVENT_SUCCESS
Dim sArgs : sArgs = "powershell.exe"
Dim sMessage : sMessage = ""
For Each sArg in Wscript.Arguments
If InStr(sArg, " ") > 0 Then
' If there's a space in the argument, wrap it in quotes.
sArgs = sArgs & " """ & sArg & """"
Else
sArgs = sArgs & " " & sArg
End If
Next
sMessage = "HiddenPowershell Running: " _
& vbCrLf & vbTab & Wscript.ScriptFullName _
& vbCrLf & vbTab & sArgs
oShell.LogEvent LOG_EVENT_INFORMATION, sMessage
iReturn = oShell.Run(sArgs, 0, True)
If iReturn <> 0 Then
iExitStatus = LOG_EVENT_ERROR
End If
sMessage = "HiddenPowershell Exited: " _
& vbCrLf & vbTab & Wscript.ScriptFullName _
& vbCrLf & vbTab & sArgs _
& vbCrLf & vbTab & "Exit Code: " & iReturn
oShell.LogEvent iExitStatus, sMessage
Wscript.Quit iReturn
while ($true) {
$WatchedProcesses = Get-CimInstance -ClassName Win32_Process -Filter "name = 'AutoHotkey.exe'"
$WatchedCli = Write-Output $WatchedProcesses | Select CommandLine | Select-String -Pattern 'macOS-shortcuts.ahk'
if ( $WatchedCli.Count -eq 0 ){
Start-Process -FilePath "${env:ProgramFiles}\AutoHotkey\Autohotkey.exe" -ArgumentList "${env:SystemDrive}\tools\macOS-shortcuts.ahk" -Verb RunAs
Write-Host "starting watched process"
}
#Write-Host "nothing to do, waiting..."
Start-Sleep -s 35
}
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<RegistrationInfo>
<Date>2021-03-18T16:51:09.0308012</Date>
<Author>apfelchips</Author>
<URI>\macOS-shortcuts-watchdog</URI>
</RegistrationInfo>
<Triggers>
<LogonTrigger>
<Enabled>true</Enabled>
<UserId>.\user</UserId>
<Delay>PT13S</Delay>
</LogonTrigger>
</Triggers>
<Principals>
<Principal id="Author">
<UserId>xxxxxxxxxxxxxxxxx</UserId>
<LogonType>InteractiveToken</LogonType>
<RunLevel>HighestAvailable</RunLevel>
</Principal>
</Principals>
<Settings>
<MultipleInstancesPolicy>StopExisting</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
<AllowHardTerminate>true</AllowHardTerminate>
<StartWhenAvailable>false</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<IdleSettings>
<StopOnIdleEnd>true</StopOnIdleEnd>
<RestartOnIdle>false</RestartOnIdle>
</IdleSettings>
<AllowStartOnDemand>true</AllowStartOnDemand>
<Enabled>true</Enabled>
<Hidden>true</Hidden>
<RunOnlyIfIdle>false</RunOnlyIfIdle>
<WakeToRun>false</WakeToRun>
<ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
<Priority>7</Priority>
</Settings>
<Actions Context="Author">
<Exec>
<Command>C:\Windows\System32\wscript.exe</Command>
<Arguments>"C:\tools\HiddenPowershell.vbs" -ExecutionPolicy ByPass -noProfile -File "C:\tools\macOS-shortcuts-watchdog.ps1"</Arguments>
</Exec>
</Actions>
</Task>
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
;#NoTrayIcon
Menu, Tray, Icon, pifmgr.dll, 13 ; Keyboard Icon
;#Persistent https://www.autohotkey.com/docs/commands/_Persistent.htm
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
#SingleInstance force
; Debugging
; #Warn All, OutputDebug ; Show Warnings on DebugView
#Warn UseUnsetLocal, Off ; Can't use default Parameters without warning
; doc:
; https://www.ahkgen.com/
; https://autohotkey.com/docs/Hotkeys.htm
; https://autohotkey.com/docs/KeyList.htm
; see DebugMessages with: https://learn.microsoft.com/en-us/sysinternals/downloads/debugview
; Ref https://autohotkey.com/board/topic/60675-osx-style-command-keys-in-windows/
; Ref https://gist.github.com/trevoreyre/8df3a186bb18df4b17d5417a5d1143ad
; Ref https://github.com/Drugoy/Autohotkey-scripts-.ahk
; ! = Alt
; ^ = Control
; + = Shift
; # = Windows
; * = Wildcard / ignore Modifiers
; $ = no Recursion
; ~ = no Key Masking
; sharpkeys: https://github.com/randyrants/sharpkeys/releases/
; PgDown --> Unknown: 0x0070
; PgUp --> Unknown: 0x0071
; PrintScr --> Unknown: 0x007F
; src: AHKHID.akh: https://github.com/jleb/AHKHID
AHKHID_GetDevCount() {
global iCount = ""
;Get the device count
r := DllCall("GetRawInputDeviceList", "Ptr", 0, "UInt*", iCount, "UInt", A_PtrSize * 2)
;Check for error
If (r = -1) Or ErrorLevel {
ErrorLevel = GetRawInputDeviceList call failed.`nReturn value: %r%`nErrorLevel: %ErrorLevel%`nLine: %A_LineNumber%`nLast Error: %A_LastError%
Return -1
} Else Return iCount
}
AHKHID_Initialize(bRefresh = False) {
global iCount
Static uHIDList, bInitialized := False
If bInitialized And Not bRefresh
Return &uHIDList
;Get the device count
r := DllCall("GetRawInputDeviceList", "Ptr", 0, "UInt*", iCount, "UInt", A_PtrSize * 2)
;Check for error
If (r = -1) Or ErrorLevel {
ErrorLevel = GetRawInputDeviceList call failed.`nReturn value: %r%`nErrorLevel: %ErrorLevel%`nLine: %A_LineNumber%`nLast Error: %A_LastError%
Return -1
}
;Prep var
VarSetCapacity(uHIDList, iCount * (A_PtrSize * 2))
r := DllCall("GetRawInputDeviceList", "Ptr", &uHIDList, "UInt*", iCount, "UInt", A_PtrSize * 2)
If (r = -1) Or ErrorLevel {
ErrorLevel = GetRawInputDeviceList call failed.`nReturn value: %r%`nErrorLevel: %ErrorLevel%`nLine: %A_LineNumber%`nLast Error: %A_LastError%
Return -1
}
bInitialized := True
Return &uHIDList
}
AHKHID_GetDevIndex(Handle) {
Loop % AHKHID_GetDevCount()
If (NumGet(AHKHID_Initialize(), (A_Index - 1) * (A_PtrSize * 2)) = Handle)
Return A_Index
Return 0
}
AHKHID_GetDevHandle(i) {
Return NumGet(AHKHID_Initialize(), (i - 1) * (A_PtrSize * 2))
}
AHKHID_GetDevType(i, IsHandle = False) {
Return Not IsHandle ? NumGet(AHKHID_Initialize(), ((i - 1) * (A_PtrSize * 2)) + A_PtrSize, "UInt")
: NumGet(AHKHID_Initialize(), ((AHKHID_GetDevIndex(i) - 1) * (A_PtrSize * 2)) + A_PtrSize, "UInt")
}
AHKHID_GetDevName(i, IsHandle = False) {
;Get index if i is handle
h := IsHandle ? i : AHKHID_GetDevHandle(i)
;Get device name length. RIDI_DEVICENAME
r := DllCall("GetRawInputDeviceInfo", "Ptr", h, "UInt", 0x20000007, "Ptr", 0, "UInt*", iLength)
If (r = -1) Or ErrorLevel {
ErrorLevel = GetRawInputDeviceInfo call failed.`nReturn value: %r%`nErrorLevel: %ErrorLevel%`nLine: %A_LineNumber%`nLast Error: %A_LastError%
Return ""
}
;Get device name.
VarSetCapacity(s, (iLength + 1) * 2) ;RIDI_DEVICENAME
r := DllCall("GetRawInputDeviceInfo", "Ptr", h, "UInt", 0x20000007, "Str", s, "UInt*", iLength)
If (r = -1) Or ErrorLevel {
ErrorLevel = GetRawInputDeviceInfo call failed.`nReturn value: %r%`nErrorLevel: %ErrorLevel%`nLine: %A_LineNumber%`nLast Error: %A_LastError%
Return ""
}
Return s
}
; see hardmode: https://autohotkey.com/board/topic/113250-detect-usb-keypad/#entry663129
; watcher https://autohotkey.com/board/topic/45042-detect-when-specific-usb-device-is-connected/#entry280394
on_device_changed(wParam, lParam, msg, hwnd){
;OutputDebug, ### on_device_changed(%wParam%, %lParam%, %msg%, %hwnd%) ###
if ( msg = 537 ) { ; watcher on WM_DEVICECHANGE 0x219
Reload
}
}
externalKeyboardCount := 0
updateExternalKeyboardCount()
OnMessage(0x219, "on_device_changed") ;https://www.autohotkey.com/docs/misc/SendMessageList.htm
sleep 500
return
updateExternalKeyboardCount(){
global externalKeyboardCount
externalKeyboardCount := 0
devCount := AHKHID_GetDevCount()
iterator := 0
internalKeyboards := []
internalKeyboards.Push("\\?\ACPI#LEN0071#4&1b7d46ad&0#{884b96c3-56ef-11d1-bc8c-00a0c91405dd}") ; ThinkPad Keyboard
internalKeyboards.Push("\\?\HID#VID_1050&PID_0407&MI_00#7&1165288&0&0000#{884b96c3-56ef-11d1-bc8c-00a0c91405dd}")
internalKeyboards.Push("\\?\HID#VID_04D9&PID_FC45&MI_01#9&2c2eeb1&0&0000#{884b96c3-56ef-11d1-bc8c-00a0c91405dd}")
loop %devCount% {
isInternal := False
deviceTypeID := AHKHID_GetDevType(iterator)
if (deviceTypeID = 1) {
devName := AHKHID_GetDevName(iterator)
OutputDebug, ### %iterator%: %devName% ###
for each, internalKeyboard in internalKeyboards {
if ( internalKeyboard = devName ) {
OutputDebug, ### Internal Keyboard: %devName% ###
isInternal = True
}
}
if not ( isInternal ){
OutputDebug, ### External Keyboard: %devName% ###
externalKeyboardCount += 1
}
}
iterator += 1
}
OutputDebug, ### externalKeyboardCount: "%externalKeyboardCount%" ###
return
}
#If ( externalKeyboardCount = 0 )
*SC07F::Send {Blind}{RAlt down}
*SC07F Up::Send {Blind}{RAlt up}
#If
#If ( externalKeyboardCount > 0 )
*SC071::Send {Blind}{PgUp}
*SC070::Send {Blind}{PgDn}
*SC07F::Send {Blind}{PrintScreen}
#If
Windows Registry Editor Version 5.00
; https://github.com/randyrants/sharpkeys/blob/master/SharpKeys/Dialog_Main.cs#L581
; Left Alt --> Right Ctrl
; Left Win --> Left Alt
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout]
"Scancode Map"=hex:00,00,00,00,00,00,00,00,03,00,00,00,1d,e0,38,00,38,00,5b,e0,\
00,00,00,00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment