📜 ⬆️ ⬇️

Custom shortcuts in Windows using Autohotkey

Following the recent and not so recent publications about shortcuts in Windows ( 1 , 2 ) and Linux decided to write about how using Autohotkey (Windows-only, installer , portable (zip) version ) you can set your own keyboard shortcuts for those commands for which no shortcuts are provided for in the system by default. In many ways, my role here was played by the desire to have the same shortcuts in Windows as on the Mac, on which I once worked a lot.

Autohotkey is not just a hotkey manager, but a truly universal tool for manipulating Windows, and implementing custom shortcuts is not the only task that it helps to solve ( documentation in English , Russian ). Autohotkey uses its own scripting language, quite simple, and for professional programmers, as I suspect, is completely elementary. A number of scripts written in AHK have been published on the program's forum, including entire applications (batch renames, code editors, web development tools, etc.).

You can use shortcuts of various types: regular keyboard shortcuts, shortcuts that use the mouse (buttons and scroll wheel), double clicks and clicks, combining different mouse buttons, double / triple keystrokes, modifiers themselves (Ctrl, Alt, etc.), joystick buttons, etc. In addition, you can force shortcuts to work only in certain applications, and this opens up space for correcting shortcuts that you think are “incorrect” in programs where there is no possibility to change their capabilities (see the example with Windows Media Player).
')
I did not include commands that can perform other similar programs (for example, Hoekey , which is limited in functionality, but eats up very little memory - about 100-500 KB, unlike Autohotkey, which eats about 2-7 MB). This includes system commands that allow you to open the Control Panel via hotkey, launch the current screensaver, etc. If anything, I can put the relevant examples in a separate topic. An indispensable script for changing the layout and converting text from one layout to another was written by our compatriot wOxxOm from the Autohotkey forum . All scripts are working and tested on WinXP, although Autohotkey works under Vista, to ensure the performance of all the examples under it is not possible.

The following are the abbreviations, the command assigned to it, and the corresponding code to be inserted into the Autohotkey.ini file. And, of course, all shortcuts can be changed to your taste. Just change part of the script to double colon.

Clear the cart with Shift + Alt + Backspace
+!Backspace:: FileRecycleEmpty


Close any windows with Ctrl + Q (like on Linux)
$^q::
IfWinActive ahk_class WMPlayerApp
PostMessage, 0x10
else
WinClose, A
return


Minimize / maximize windows with Ctrl + Win + mouse wheel
^#WheelUp:: WinMaximize A
^#WheelDown:: WinRestore A


Win + Shift + C - copy to the clipboard the path to the selected file in Explorer
#+c::
clipboard =
Send, ^c
ClipWait, 2
Sort, clipboard


Minimize the windows to the title bar by pressing the tilde (`)
ws_MinHeight = 25

OnExit, ExitSub
return

`::
Sleep, 200
WinGet, ws_ID, ID, A
Loop, Parse, ws_IDList, |
{
IfEqual, A_LoopField, %ws_ID%
{
StringTrimRight, ws_Height, ws_Window%ws_ID%, 0
WinMove, ahk_id %ws_ID%,,,,, %ws_Height%
WinSet, AlwaysOnTop, off, A
StringReplace, ws_IDList, ws_IDList, |%ws_ID%
return
}
}
WinGetPos,,,, ws_Height, A
WinSet, AlwaysOnTop, on, ahk_id %ws_ID%
ws_Window%ws_ID% = %ws_Height%
WinMove, ahk_id %ws_ID%,,,,, %ws_MinHeight%
ws_IDList = %ws_IDList%|%ws_ID%
return

ExitSub:
Loop, Parse, ws_IDList, |
{
if A_LoopField = ; First field in list is normally blank.
continue ; So skip it.
StringTrimRight, ws_Height, ws_Window%A_LoopField%, 0
WinMove, ahk_id %A_LoopField%,,,,, %ws_Height%
}
ExitApp


Move the windows with the Win key held down (or whatever)
#LButton::
CoordMode, Mouse
MouseGetPos, EWD_MouseStartX, EWD_MouseStartY, EWD_MouseWin
WinGetClass, EWD_Win_Class, ahk_id %EWD_MouseWin%
If EWD_Win_Class = ProgMan
Return
WinGet, State, MinMax, ahk_id %EWD_MouseWin%
If State = 1
{
SplashImage,, W160 H27 B1 FM8 WM400 CT000080,, ,, Calibri
SetTimer, Remove_Splash, 600
Return

Remove_Splash:
SetTimer, Remove_Splash, Off
SplashImage, Off
Return
}
WinGetPos, EWD_OriginalPosX, EWD_OriginalPosY,,, ahk_id %EWD_MouseWin%
SetTimer, EWD_WatchMouse, 10
Return

EWD_WatchMouse:
EWD_Work = 1
GetKeyState, EWD_LButtonState, LButton, P
If EWD_LButtonState = U
{
SetTimer, EWD_WatchMouse, off
EWD_Work =
Return
}
GetKeyState, EWD_EscapeState, Escape, P
If EWD_EscapeState = D
{
SetTimer, EWD_WatchMouse, off
EWD_Work =
WinMove, ahk_id %EWD_MouseWin%,, %EWD_OriginalPosX%, %EWD_OriginalPosY%
Return
}
CoordMode, Mouse
MouseGetPos, EWD_MouseX, EWD_MouseY
WinGetPos, EWD_WinX, EWD_WinY,,, ahk_id %EWD_MouseWin%
SetWinDelay, -1
WinMove, ahk_id %EWD_MouseWin%,, EWD_WinX + EWD_MouseX - EWD_MouseStartX, EWD_WinY + EWD_MouseY - EWD_MouseStartY
EWD_MouseStartX := EWD_MouseX
EWD_MouseStartY := EWD_MouseY
Return


Resize windows with the right mouse button while holding the Win key
LWin & RButton::
CoordMode, Mouse ; Switch to screen/absolute coordinates.
MouseGetPos, SWM_MouseStartX, SWM_MouseStartY, SWM_MouseWin
WinGetPos, SWM_WinX, SWM_WinY, SWM_WinW, SWM_WinH, ahk_id %SWM_MouseWin%
WinGetClass, SWM_Win_Class, ahk_id %SWM_MouseWin%
If SWM_Win_Class = ProgMan
Return
WinGet, State, MinMax, ahk_id %SWM_MouseWin%
If State = 1
{
SplashImage,, W160 H26 B1 FM8 WM400 CT000080,, ,, Calibri
SetTimer, Remove_Splash, 600
Return
}
GetKeyState, SMW_LCtrlState, LCtrl
if SMW_LCtrlState=D
{
WinClose, ahk_id %SWM_MouseWin%
return
}
SWM_ResizeTypeX=0
SWM_ResizeTypeY=0
if (SWM_MouseStartX < SWM_WinX+SWM_WinW/2)
SWM_ResizeTypeX=1
if (SWM_MouseStartY < SWM_WinY+SWM_WinH/2)
SWM_ResizeTypeY=1
SetTimer, SWM_WatchMouse_Resize, 10
return

SWM_WatchMouse_Move:
GetKeyState, SMW_LButtonState, LButton, P
if SMW_LButtonState = U
{
SetTimer, SWM_WatchMouse_Move, off
return
}
Gosub SWM_GetMouseAndWindowPos
SWM_WinX += %SWM_DeltaX%
SWM_WinY += %SWM_DeltaY%
SetWinDelay, -1
WinMove, ahk_id %SWM_MouseWin%,, %SWM_WinX%, %SWM_WinY%
return

SWM_WatchMouse_Resize:
GetKeyState, SMW_RButtonState, RButton, P
if SMW_RButtonState = U
{
SetTimer, SWM_WatchMouse_Resize, off
return
}
Gosub SWM_GetMouseAndWindowPos
if SWM_ResizeTypeX
{
SWM_WinX += %SWM_DeltaX%
SWM_WinW -= %SWM_DeltaX%
}
else
SWM_WinW += %SWM_DeltaX%
if SWM_ResizeTypeY
{
SWM_WinY += %SWM_DeltaY%
SWM_WinH -= %SWM_DeltaY%
}
else
SWM_WinH += %SWM_DeltaY%
SetWinDelay, -1
WinMove, ahk_id %SWM_MouseWin%,, %SWM_WinX%, %SWM_WinY%, %SWM_WinW%, %SWM_WinH%
return

SWM_GetMouseAndWindowPos:
CoordMode, Mouse
MouseGetPos, SWM_MouseX, SWM_MouseY
SWM_DeltaX = %SWM_MouseX%
SWM_DeltaX -= %SWM_MouseStartX%
SWM_DeltaY = %SWM_MouseY%
SWM_DeltaY -= %SWM_MouseStartY%
SWM_MouseStartX = %SWM_MouseX%
SWM_MouseStartY = %SWM_MouseY%
WinGetPos, SWM_WinX, SWM_WinY, SWM_WinW, SWM_WinH, ahk_id %SWM_MouseWin%
return


Alt + H - show / hide hidden files in Explorer
!H::GoSub,CheckActiveWindow

CheckActiveWindow:
ID := WinExist("A")
WinGetClass,Class, ahk_id %ID%
WClasses := "CabinetWClass ExploreWClass"
IfInString, WClasses, %Class%
GoSub, Toggle_HiddenFiles_Display
Return

Toggle_HiddenFiles_Display:
RootKey = HKEY_CURRENT_USER
SubKey = Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced

RegRead, HiddenFiles_Status, % RootKey, % SubKey, Hidden

if HiddenFiles_Status = 2
RegWrite, REG_DWORD, % RootKey, % SubKey, Hidden, 1
else
RegWrite, REG_DWORD, % RootKey, % SubKey, Hidden, 2
PostMessage, 0x111, 28931,,, ahk_id %ID%
Return


Climb the directory up by clicking the middle mouse button in the explorer
~MButton::
MouseGetPos,,,,hovercontrol
if hovercontrol = SysListView321
Send {Backspace}
else if hovercontrol = #327701
Send {Backspace}
Return


Create a new folder in Explorer by double clicking on any empty space inside the window
#IfWinActive ahk_class CabinetWClass
~LButton::
SetKeyDelay, , 50
MouseGetPos, , , , ctrl
ControlGet, sel, List, Count Selected, SysListView321, A
If DllCall("GetDoubleClickTime") > A_TimeSincePriorHotkey
and A_ThisHotkey = A_PriorHotkey
and ctrl = "SysListView321"
and sel = 0
SendEvent, !fwf
Return
#IfWinActive


Change the transparency of the window Ctrl + Shift + mouse wheel
OnExit EXIT
^+WheelDown::
^+WheelUp::
Sleep 50
MouseGetPos cx, cy, Win_Id
WinGetClass Class, ahk_id %Win_Id%
If Class in Progman,Shell_TrayWnd
Return
IfEqual N%Win_Id%,, {
WinGet T, Transparent, ahk_id %Win_Id%
IfEqual T,, SetEnv T,255
List = %List%%Win_Id%,%T%,
N%Win_Id% = %T%
}
IfEqual A_ThisHotKey,^+WheelUp, EnvAdd N%Win_Id%,12
Else N%Win_Id% -= 12 ;Transparency changing step
IfGreater N%Win_Id%,255, SetEnv N%Win_Id%,255
IfLess N%Win_Id%,40, SetEnv N%Win_Id%,40
WinSet Transparent, % N%Win_Id%, ahk_id %Win_Id%
TrayTip,,% "Transparency: " N%Win_Id%
Return

EXIT:
Loop Parse, List, `,
If (A_Index & 1)
Id = %A_LoopField%
Else
Winset Transparent, %A_LoopField%, ahk_id %Id%
ExitApp


Close the windows in the taskbar area Ctrl + middle mouse button
^MButton::
SetBatchLines, -1
CoordMode, Mouse, Screen
SetMouseDelay, -1
SetKeyDelay, -1
MouseGetPos, ClickX, ClickY, WindowUnderMouseID
WinActivate, ahk_id %WindowUnderMouseID%

; WM_NCHITTEST
SendMessage, 0x84,, ( ClickY << 16 )|ClickX,, ahk_id %WindowUnderMouseID%
WM_NCHITTEST_Result =%ErrorLevel%
/*
#define HTERROR (-2)
#define HTTRANSPARENT (-1)
#define HTNOWHERE 0
#define HTCLIENT 1
#define HTCAPTION 2
#define HTSYSMENU 3
#define HTGROWBOX 4
#define HTSIZE HTGROWBOX
#define HTMENU 5
#define HTHSCROLL 6
#define HTVSCROLL 7
#define HTMINBUTTON 8
#define HTMAXBUTTON 9
#define HTLEFT 10
#define HTRIGHT 11
#define HTTOP 12
#define HTTOPLEFT 13
#define HTTOPRIGHT 14
#define HTBOTTOM 15
#define HTBOTTOMLEFT 16
#define HTBOTTOMRIGHT 17
#define HTBORDER 18
#define HTREDUCE HTMINBUTTON
#define HTZOOM HTMAXBUTTON
#define HTSIZEFIRST HTLEFT
#define HTSIZELAST HTBOTTOMRIGHT
#if(WINVER >= 0x0400)
#define HTOBJECT 19
#define HTCLOSE 20
#define HTHELP 21
*/

;Close window with titlebar click
If WM_NCHITTEST_Result in 2,3,8,9,20,21
{
PostMessage, 0x112, 0xF060,,, ahk_id %WindowUnderMouseID% ; 0x112 = WM_SYSCOMMAND, 0xF060 = SC_CLOSE
Return
}

;Close taskbar program click
IfWinActive, ahk_class Shell_TrayWnd
{
MouseClick, Right, %ClickX%, %ClickY%
Sleep, 50
Send, c
WinWaitNotActive, ahk_class Shell_TrayWnd,, 0.5
If ErrorLevel =1
Send, !{Tab}
Return
}

If GetKeyState("MButton", "P")
MouseClick, Middle, %ClickX%, %ClickY%,, Down
Else
MouseClick, Middle, %ClickX%, %ClickY%
Return


Change the appearance of folders in the explorer using Win + number keys
#1::PostMessage, 0x111, 28717,,, ahk_class CabinetWClass ;
+#1::PostMessage, 0x111, 28719,,, ahk_class CabinetWClass ;
#2::PostMessage, 0x111, 28718,,, ahk_class CabinetWClass ;
#3::PostMessage, 0x111, 28715,,, ahk_class CabinetWClass ;
#4::PostMessage, 0x111, 28716,,, ahk_class CabinetWClass ;


Change the system volume using Win + mouse wheel
#WheelUp::
SoundSet +5
SoundSet, +5, wave
return

#WheelDown::
SoundSet -5
SoundSet, -5, wave
return


Scroll Lock - change the layout of the selected text
 $~ScrollLock::RecodeTextENRU() RecodeTextENRU() { StringCaseSense On AutoTrim,Off clipSave:=clipAnsi() send ^{Insert} sleep,50 dest= text:=clipAnsi() StringCaseSense,On prevCharToEN=0 ;  RUtoEN=F<DULT:PBQRKVYJGHCNEA{WXIO}SM">Zf,dult;pbqrkvyjghcnea[wxio]sm'.z RUtoSP1=.,/"â„–;:? RUtoSP2=[];',.{}:"<>/?|@#$^& ;" ABCDEFGHIJKLMNOPQRSTUVWXYZ ENtoRU= loop,parse,text { destChar=%A_LoopField% ; check explicit (non punctuations) ranges ifGreaterOrEqual,A_LoopField, prevCharToEN=1 else if A_LoopField between A and Z prevCharToEN=0 else if A_LoopField between a and z prevCharToEN=0 ; to Russian ifEqual,prevCharToEN,0 { StringGetPos,i,RUtoEN,%A_LoopField% ifEqual,ErrorLevel,0 Transform,destChar,chr,% i + 0xC0 else { StringGetPos,i,RUtoSP2,%A_LoopField% ifEqual,ErrorLevel,0 StringMid,destChar,RUtoSP1,% i+1, 1 } } ; to English because nothing changed ifEqual,destChar,%A_LoopField% { StringGetPos,i,ENtoRU,%A_LoopField% ifEqual,ErrorLevel,0 Transform,destChar,chr,% i + (i>=26 ? 71 : 65) else ; check .,;':"[]{} { StringGetPos,i,RUtoSP1,%A_LoopField% ifEqual,ErrorLevel,0,StringMid,destChar,RUtoSP2,% i+1, 1 } ifNotEqual,destChar,%A_LoopField% prevCharToEN=1 } dest=%dest%%destChar% } ; decide compatibility of unicode clipboard WinGetClass,cls,A if cls in TMsgEditor,wndclass_desked_gsk { ControlGetFocus,cls,A ifInString,cls,TXTRichEdit clipSetUnicode(dest) else Clipboard=%dest% } else clipSetUnicode(dest) sleep,50 send +{Insert} sleep 50 clipSetUnicode(clipSave) LangSwitch() } ; read unicode clipboard into ansi string clipAnsi() { StringLen,L,Clipboard L:=(L+1)*4 transform,ca_Clip,unicode varSetCapacity(ca_WideText,L,0) varSetCapacity(ca_AnsiText,L,0) ; Convert UTF-8 to UTF-16. CP_UTF8=65001 if dllCall("MultiByteToWideChar",uint,65001, uint,0, str,ca_Clip , uint,-1, str,ca_WideText, uint,L/2) dllCall("WideCharToMultiByte",uint,0, uint,0, str,ca_WideText , uint,-1, str,ca_AnsiText, uint,L/2, uint,0, uint,0) ; Convert UTF-16 to ANSI. CP_ACP=0 return ca_AnsiText } ;-------------------------------------------------------------- ; copy ansi string to clipboard in unicode mode clipSetUnicode(cu_AnsiText) { StringLen,L,cu_AnsiText L:=(L+1)*4 varSetCapacity(cu_WideText,L,0) varSetCapacity(cu_UTFtext,L,0) ; ANSI to UTF-16. CP_ACP=0 if dllCall("MultiByteToWideChar",uint,0, uint,0, str,cu_AnsiText , uint,-1, str,cu_WideText, uint,L/2) dllCall("WideCharToMultiByte",uint,65001, uint,0, str,cu_WideText , uint,-1, str,cu_UTFtext, uint,L/2, uint,0, uint,0) ; Convert UTF-16 to UTF-8. CP_UTF8=65001 transform,clipboard,unicode,%cu_UTFtext% } 


Change the current layout by pressing the right Ctrl
$~RControl::LangSwitch(1)
$~RControl up::LangSwitch(2)

LangSwitch( iKeyDownUp=0 )
{
static tickLast
IfEqual,iKeyDownUp,1
{ tickLast=%A_TickCount%
return
}
IfEqual,iKeyDownUp,2
If( A_TickCount-tickLast>200 )
return

HKL:=DllCall("GetKeyboardLayout", "uint",GetThreadOfWindow(), "uint")

HKLnum:=DllCall("GetKeyboardLayoutList","uint",0,"uint",0)
VarSetCapacity( HKLlist, HKLnum*4, 0 )
DllCall("GetKeyboardLayoutList","uint",HKLnum,"uint",&HKLlist)
loop,%HKLnum%
{ if( NumGet( HKLlist, (A_Index-1)*4 ) = HKL )
{ HKL:=NumGet( HKLlist, mod(A_Index,HKLnum)*4 )
break
}
}
ControlGetFocus,ctl,A
SendMessage,0x50,0,HKL,%ctl%,A ;WM_INPUTLANGCHANGEREQUEST

;show traytip
LOCALE_SENGLANGUAGE=0x1001
LOCALE_SENGCOUNTRY=0x1002
VarSetCapacity( sKbd, 260, 0 )
VarSetCapacity( sCountry, 260, 0 )
DllCall("GetLocaleInfo","uint",HKL>>16,"uint",LOCALE_SENGLANGUAGE, "str",sKbd, "uint",260)
DllCall("GetLocaleInfo","uint",HKL & 0xFFFF,"uint",LOCALE_SENGCOUNTRY, "str",sCountry, "uint",260)
traytip,%sKbd%,%sCountry%
SetTimer,REMOVE_TOOLTIP,500 ;0.5 second
return
REMOVE_TOOLTIP:
SetTimer,REMOVE_TOOLTIP,off
traytip
return
}

;returns first thread for the ;sets optional to pipe | separated thread list for the GetProcessThreadOrList( processID, byRef list="" )
{
;THREADENTRY32 {
THREADENTRY32_dwSize=0 ; DWORD
THREADENTRY32_cntUsage = 4 ;DWORD
THREADENTRY32_th32ThreadID = 8 ;DWORD
THREADENTRY32_th32OwnerProcessID = 12 ;DWORD
THREADENTRY32_tpBasePri = 16 ;LONG
THREADENTRY32_tpDeltaPri = 20 ;LONG
THREADENTRY32_dwFlags = 24 ;DWORD
THREADENTRY32_SIZEOF = 28

TH32CS_SNAPTHREAD=4

hProcessSnap := DllCall("CreateToolhelp32Snapshot","uint",TH32CS_SNAPTHREAD, "uint",0)
ifEqual,hProcessSnap,-1, return

VarSetCapacity( thE, THREADENTRY32_SIZEOF, 0 )
NumPut( THREADENTRY32_SIZEOF, thE )

ret=-1

if( DllCall("Thread32First","uint",hProcessSnap, "uint",&thE ))
loop
{
if( NumGet( thE ) >= THREADENTRY32_th32OwnerProcessID + 4)
if( NumGet( thE, THREADENTRY32_th32OwnerProcessID ) = processID )
{ th := NumGet( thE, THREADENTRY32_th32ThreadID )
IfEqual,ret,-1
ret:=th
list .= th "|"
}
NumPut( THREADENTRY32_SIZEOF, thE )
if( DllCall("Thread32Next","uint",hProcessSnap, "uint",&thE )=0)
break
}

DllCall("CloseHandle","uint",hProcessSnap)
StringTrimRight,list,list,1
return ret
}

; Returns thread owning specified window handle
; default = Active window
GetThreadOfWindow( hWnd=0 )
{
IfEqual,hWnd,0
hWnd:=WinExist("A")
DllCall("GetWindowThreadProcessId", "uint",hWnd, "uintp",id)
GetProcessThreadOrList( id, threads )
IfEqual,threads,
return 0
CB:=RegisterCallback("GetThreadOfWindowCallBack","Fast")
lRet=0
lParam:=hWnd
loop,parse,threads,|
{ NumPut( hWnd, lParam )
DllCall("EnumThreadWindows", "uint",A_LoopField, "uint",CB, "uint",&lParam)
if( NumGet( lParam )=true )
{ lRet:=A_LoopField
break
}
}
DllCall("GlobalFree", "uint", CB)
return lRet
}

GetThreadOfWindowCallBack( hWnd, lParam )
{
IfNotEqual,hWnd,% NumGet( 0+lParam )
return true
NumPut( true, 0+lParam )
return 0
}


Ctrl+Shift+Win+Escape/Ctrl+Shift+Win+Alt+Escape - /
#+^Escape:: ;shutdown timer
InputBox, minutes ,Sleeptimer, Put the minutes before shutdown below:,,200,140
if ErrorLevel
exit
else
Sleep, (minutes*60*1000)
Shutdown, 8
return

#+!^Escape:: ;restart timer
InputBox, minutes ,Sleeptimer, Put the minutes before restart below:,,200,140
if ErrorLevel
exit
else
Sleep, (minutes*60*1000)
Shutdown, 2
return


Windows Media Player Space ( )
~Space::
IfWinActive, ahk_class WMPTransition
{
PostMessage, 0x111, 32808, 0, , Windows Media Player
}
IfWinActive, ahk_class WMPlayerApp
{
PostMessage, 0x111, 32808, 0, , Windows Media Player
}
return



Source: https://habr.com/ru/post/24652/


All Articles