⬆️ ⬇️

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