Пользовательские шорткаты в Windows с помощью Autohotkey

    По следам недавних и не столь недавних публикаций о шорткатах в Windows (1, 2) и Linux решил написать о том, как при помощи программы Autohotkey (Windows-only, инсталлятор, портабельная (zip) версия) можно задавать свои собственные клавиатурные сокращения для тех команд, для которых в системе по умолчанию никаких шорткатов не предусмотрено. Во многом свою роль здесь сыграло желание иметь в Винде те же шорткаты, что и на Маке, на котором я одно время много работал.

    Autohotkey — не просто менеджер хоткеев, а поистине универсальный инструмент для манипулирования Windows, и реализация кастомных сокращений — отнюдь не единственная задача, которую она помогает решить (документация на английском, русском языке). Autohotkey использует свой собственный скриптовый язык, довольно простой, а для профессиональных программеров, как я подозреваю, и вовсе элементарный. На форуме программы опубликованы множество скриптов, написанных на языке AHK, в том числе целые приложения (пакетные переименователи, редакторы кода, инструменты для веб-разработки и т.д.).

    Можно использовать шорткаты самых разных типов: обычные клавиатурные сокращения, сокращения, использующие мышь (кнопки и колесико), двойные щелчки и щелчки, комбинирующие разные кнопки мыши, двойные/тройные нажатия клавиш, модификаторы сами по себе (Ctrl, Alt и др.), кнопки джойстика и т.д. Кроме того, вы можете заставить шорткат работать только в определенных приложениях, и это открывает пространство для исправления «неправильных» по вашему мнению шорткатов в программах, где изменять их возможности нет (см. пример с Windows Media Player).

    Я не включил сюда команды, которые могут выполнять и другие схожие программы (например, Hoekey, ограниченная по функциональности, но съедающая очень мало памяти — около 100-500 Кб, в отличие от Autohotkey, которая ест примерно 2-7 Мб). В том числе системные команды, позволяющие открывать по хоткею Панель управления, запускать текущий скринсейвер и т.д. Если что, соответствующие примеры могу выложить в отдельном топике. Незаменимый скрипт для смены раскладки и конвертирования текста из одной раскладки в другую написан нашим соотечественником wOxxOm с форума Autohotkey. Все скрипты работают и проверены на WinXP, хотя Autohotkey работает и под Вистой, гарантировать работоспособность всех примеров под ней не представляется возможным.

    Далее приведены: сокращение, команда, ему присвоенная, и соответствующий код, который необходимо вставить в файл Autohotkey.ini. И, конечно, все шорткаты можно поменять на свой вкус. Просто измените часть скрипта до двойного двоеточия.

    Очищаем корзину с помощью Shift+Alt+Backspace
    +!Backspace:: FileRecycleEmpty


    Закрываем любые окна с помощью Ctrl+Q (как на Linux)
    $^q::
    IfWinActive ahk_class WMPlayerApp
    PostMessage, 0x10
    else
    WinClose, A
    return


    Минимизируем/максимизируем окна с Ctrl+Win+колесико мыши
    ^#WheelUp:: WinMaximize A
    ^#WheelDown:: WinRestore A


    Win+Shift+C — копируем в буфер обмена путь к выделенному в проводнике файлу
    #+c::
    clipboard =
    Send, ^c
    ClipWait, 2
    Sort, clipboard


    Cворачиваем окна до строки заголовка нажатием тильды (`)
    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


    Передвигаем окна с зажатой клавишей Win (или любой другой)
    #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


    Изменяем размер окон правой кнопкой мыши с зажатой клавишей Win
    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 — показываем/скрываем скрытые файлы в проводнике
    !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


    Поднимаемся на директорию вверх щелчком средней кнопкой мыши в проводнике
    ~MButton::
    MouseGetPos,,,,hovercontrol
    if hovercontrol = SysListView321
    Send {Backspace}
    else if hovercontrol = #327701
    Send {Backspace}
    Return


    Создаем новую папку в проводнике двойным щелчком по любому пустому пространству внутри окна
    #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


    Изменяем прозрачность окна Ctrl+Shift+колесиком мыши
    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


    Закрываем окна в области панели задач Ctrl+средней кнопкой мыши
    ^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


    Изменяем вид папок в проводнике с помощью Win+цифровые клавиши
    #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 ; Таблица


    Изменяем системную громкость с помощью Win+колесико мыши
    #WheelUp::
    SoundSet +5
    SoundSet, +5, wave
    return

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


    Scroll Lock — изменяем раскладку выделенного текста
    $~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%
    }
    


    Изменяем текущую раскладку нажатием правой 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



    Поделиться публикацией
    Реклама помогает поддерживать и развивать наши сервисы

    Подробнее
    Реклама
    Комментарии 30
    • 0
      А не мог бы кто-нибудь добрый выложить сборник всех маковых шорткатов для виндуса? Очень было бы полезно при парраленьной работе на маке и винде... Я в свое время сам пытался составить, но не осилил.
    • +1
      Неплохая подборка:) Сам пользуюсь AHK на Win-машине.

      Кстати, довольно полезной может быть возможность компилировать скрипты. На выходе – .exe, который можно положить на флешку. Если там используются стандартные для XP вещи получается очень удобно:)

      По поводу Висты сразу приходит в голову вот что – там классы у стандартных окошек могут быть другие, интерфейс же перелопатили, и, следовательно, некоторые скрипты будут просто бесполезны (что, вообще-то, легко исправляется, благо с AHK идет утилита для получения всех необходимых разведданых:) А вот стандартные команды (а ля очистить корзину) должны работать «из коробки».
      • +1
        Переместил топик в блог Windows.
        2xabk: Да, особенно компилирование удобно для всяческих утилит, написанных на языке AHK, которые просто созданы для того, чтобы быть standalone - типа тех же переименователей...
        • –1
          «Zip-(портабельная) версия».

          Прочтите, пожалуйста, § 86. Я имею в виду первый пример, с ноутбуками.

          Надо было написать просто: «портабельная версия (zip)».
          • 0
            Пожалуйста:)
            • 0
              Сейчас ненамного лучше, если честно.

              Объясняю более подробно.

              Вы ставите ссылку на версию, к которой есть два разнородных (относящихся к разным критериям классификации) описания: «портабельная версия» и «zip».

              Сразу отметим, что засовывать «zip» между «портабельная» и «версия» незачем. Это можно было бы сделать, если бы вы хотели акцентировать внимание на то, что «zip» — тоже версия («портабельная версия» + «zip-версия») — тогда можно, так сказать, вынести общий множитель «версия» за скобки. Но в данном случае одно слово «zip» вполне самодостаточно, да и «zip-версия» выглядит довольно коряво.

              Поскольку у нас два описания, выделяем, которое из них главное, а второе берём в скобки. В данном случае я бы выбрал главным описание «портабельная версия», хотя с этим можно серьёзно поспорить. Я рассуждаю, что читателю более интересно знать, что эта версия отличается от инсталлятора тем, что является легко переносимой; однако на то могут последовать вполне резонные возражения, что в данном случае через запятую перечисляются форматы дистрибутивов: инсталлятор и zip, о втором из которых стоит дополнительно заметить, что это портабельная версия.

              Итак, либо «портабельная версия (zip)», либо «zip (портабельная версия)».

              Заключать в ссылку оба описания одновременно нет смысла, не говоря уже о том, что подчёркнутые скобки выглядят некрасиво (см. также о кавычках в ссылках). Надо делать ссылкой только главное описание.

              Поэтому либо «портабельная версия (zip)», либо «zip (портабельная версия)».

              Между прочим, ещё неплохо было бы избавиться от кальки «портабельная». «Переносимая», например — чем плохо?
              • 0
                Простите за офф-топик, но вот про кавычки в ссылках не надо. Включать их в ссылку или не включать — вопрос достаточно спорный, причём с точки зрения традиции ответ скорее включать, чем не включать.
          • 0
            о, она бесплатная. спасибо!

            скажите, есть ли способ приучить эту программу ставить текущую дату и время в любом окне по сочетанию клавиш? как F5 в блокноте?
            • 0
              Вот небольшой скриптик для Win+Z, но, я уверен, можно сделать и лучше:

              #z::
              Send %A_Hour%:%A_Min% - %A_DD%.%A_MM%.%A_YYYY%
              return
          • 0
            Пользуюсь давно этой штукой, но у меня скриптов сильно поменьше было. Спасибо за новые :)
            • +1
              Неужели очистить корзину достойна шортката? Вроде редкая операция...
              • 0
                Особенно хорошо получится, если этот шорткат нажать случайно.
                • 0
                  Просто поменяйте хоткей. Модификаторы: Alt - !, Win - #, Ctrl - ^, Shift - +.
                  • 0
                    Всё равно ведь случайно возможно нажать.
                    • 0
                      Ну это всего лишь только примеры, ну не нравится вам очищать корзину через хоткей, не очищайте). Не копируйте в Autohotkey.ini этот кусок кода, и всего-то делов). Вы свое недовольство адресовали бы лучше разработчикам Mac OS, у которых шорткат для очищения корзины встроен в систему (хотя мне с ним прекрасно жилось).
                      • 0
                        А у меня нет здесь недовольства, просто замечание слегка недоумённое.
              • 0
                В топку Проводник и WMP. TotalCMD + WinAMP forever!
                • 0
                  а мне больше FAR Manager нравится, а про винамп согласен )))
              • 0
                Сколько не втыкал подобные костыли (вплоть до уровня Hook'ов), так и не смог сделать две простые вещи, которые давно есть лине: переключение раскладки по клавише контекстного меню и второй буфер обмена "в колёсике мышки".
                • 0
                  Ну, переключение по правой Ctrl работает (см. скрипт в топике), осталось узнать, как в AHK задается клавиша контекстного меню. А с буфером обмена у меня тоже были проблемы, вы не одни)
                  • 0
                    да сделать это можно, только оно работает не так, как надо. Контестное меню будет вызываться, потом уже переключение. Пытался запрограммировать это на уровне Win32 API - то же самое. Система отлавливает это событие раньше пользовательского процесса в любом случае.
                    С буфером видел примеры на том же AHK - всё равно не то.
                • 0
                  Отличная статья. Спасибо.
                  Давно задавался такими же вопросами, а тут — на тебе — готовое решение + скриптовой язык.

                  А автору предыдущей статьи надо поменьше сидедь в фотошопе!
                  • +1
                    приветствую тебя, о Гуру AHK. твои скрипты у меня в системе пользуются почётом!
                    Велкам: habrahabr.ru/blogs/AutoHotKey/
                    • 0
                      Изменяем размер окон правой кнопкой мыши с зажатой клавишей Win

                      В этом скрипте надо добавить:

                      Remove_Splash:
                      SplashImage, Off
                      return

                      иначе будет ругаться и работать не будет
                      • 0
                        Помогите чайнику, вот это не работает «Scroll Lock — изменяем раскладку выделенного текста». Там что-то надо поменять?
                        • +1
                          а на какой системе? я сейчас, правда, ответить не смогу — в данный момент нет доступа к винде.
                          • 0
                            Спасибо, я нагуглил уже рабочий скрипт.

                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.