1

Тема: АНК: (из Коллекции) скрипт-индикатор для NumLock CapsLock ScrollLock..

ссылка на коллекцию

На работе беспроводная клавиатура, но идея скрипта понравилась, использую дома и на проводной.

Решил, что будет удобнее, если и текущая раскладка будет отображаться на кнопке "Пуск", а стандартную можно убрать.
Благодаря решениям teadrinker и creature.ws раскладка отображается и в консольных приложениях.
В какой-то теме подсмотрел как расширить кнопку, объединил, в итоге получился скрипт:

#persistent ; необходимо, только если используется в качестве отдельного скрипта
; или встраивается в скрипт без строк автозамены, горячих клавиш или команд GUI.
SetTimer, Start, 100 ; настройте второй параметр, чтобы изменить интервал реагирования
Start:
    StartButtonText = %NumToggle%%ScrollToggle%%InsToggle% %CapsLang%

    GetKeyState, NumToggle, Numlock, T
    If NumToggle = U
        NumToggle = -
    Else
        NumToggle = N

    GetKeyState, ScrollToggle, ScrollLock, T
    If ScrollToggle = U
        ScrollToggle = -
    Else
        ScrollToggle = S

    GetKeyState,InsToggle, Insert, T
    If InsToggle = U
        InsToggle = -
    Else
        InsToggle = I

    GetKeyState, CapsToggle, CapsLock, T ; проверяем, включен ли Capslock

    InputLocale:= GetInputLangName(GetInputLangID("A"))
    StringLeft, InputLocale, InputLocale, 2
    StringUpper, InputLocale, InputLocale

    If CapsToggle = U
      StringLower, InputLocale, InputLocale
    CapsLang := InputLocale

    ControlMove, Button1, 0,, 62,, ahk_class Shell_TrayWnd  ; увеличение размера кнопки "Пуск"

    ControlSetText,Button1,%StartButtonText%,ahk_class Shell_TrayWnd  ;изменение текста на кнопке "Пуск"

Return


GetInputLangID(window)
{
    If !(hWnd := WinExist(window))
        return
 
    WinGetClass, Class
 
    if (Class == "ConsoleWindowClass")
    {
        WinGet, consolePID, PID
        DllCall("AttachConsole", Ptr, consolePID)
        VarSetCapacity(buff, 16)
        DllCall("GetConsoleKeyboardLayoutName", Str, buff)
        DllCall("FreeConsole")
        langID := "0x" . SubStr(buff, -3)
    }
    Else
        langID := DllCall("GetKeyboardLayout", Ptr, DllCall("GetWindowThreadProcessId", Ptr, hWnd, UInt, 0, Ptr), Ptr) & 0xFFFF
 
    return langID
}
 
GetInputLangName(langId)
{
    Size := (DllCall("GetLocaleInfo", UInt, langId, UInt, 0x1001, UInt, 0, UInt, 0) * 2)   ; LOCALE_SENGLANGUAGE := 0x1001
    VarSetCapacity(localeSig, Size, 0)
    DllCall("GetLocaleInfo", UInt, langId, UInt, 0x1001, Str, localeSig, UInt, Size)
    return localeSig
}

Отображение CapsLock отдельной буквой убрал. Вместо этого верхний или нижний регистр отображается в названии раскладки.
Вопросы по этому скрипту:
Можно ли раскладку выводить цветным шрифтом на цветном фоне? Можно ли вывести на месте картинки?
Т.е. хотелось бы получить отображение, как у оригинальной: белым шрифтом на синем фоне.

В теме   подсмотрел как можно изменить изображение у кнопки "Пуск".
Второй вариант скрипта с изображениями:

#persistent ; необходимо, только если используется в качестве отдельного скрипта
; или встраивается в скрипт без строк автозамены, горячих клавиш или команд GUI.
;SetBatchLines, -1
StringCaseSense, On

Gui, +ToolWindow -Caption            
Gui, +Lastfound                      
GUI_ID := WinExist()                
WinGet, TaskBar_ID, ID, ahk_class Shell_TrayWnd 
DllCall("SetParent", "uint", GUI_ID, "uint", Taskbar_ID) 
Gui, Margin, 0, 0
Gui, Add, Picture, x2 y3 w16 h16 gStartM vStartM, xx_s.bmp
Gui, Show, x0 y0 , Start Button

PrevInputLocale:="xx"  ; переменная введена для того, чтобы не мерцало изображение с раскладкой 

SetTimer, Start, 100 ; настройте второй параметр, чтобы изменить интервал реагирования
Return

Start:
    StartButtonText = %NumToggle%%ScrollToggle%%InsToggle%

    GetKeyState, NumToggle, Numlock, T
    If NumToggle = U
        NumToggle = -
    Else
        NumToggle = N

    GetKeyState, ScrollToggle, ScrollLock, T
    If ScrollToggle = U
        ScrollToggle = -
    Else
        ScrollToggle = S

    GetKeyState,InsToggle, Insert, T
    If InsToggle = U
        InsToggle = -
    Else
        InsToggle = I

    GetKeyState, CapsToggle, CapsLock, T ; проверяем, включен ли Capslock

    InputLocale:= GetInputLangName(GetInputLangID("A"))

    StringLeft, InputLocale, InputLocale, 2
    If CapsToggle = U
      StringLower, InputLocale, InputLocale
    Else
      StringUpper, InputLocale, InputLocale


    IF (InputLocale <> PrevInputLocale)
      {
       IF InputLocale = en
         GuiControl,, Static1, en_s.bmp
       Else If InputLocale = EN
         GuiControl,, Static1, EN.bmp
       Else If InputLocale = ru
         GuiControl,, Static1, ru_s.bmp
       Else If InputLocale = RU
         GuiControl,, Static1, RU.bmp
       ELSE
         {
          If CapsToggle = U
            GuiControl,, Static1, xx_s.bmp
          Else
            GuiControl,, Static1, XX.bmp
         }
       PrevInputLocale := InputLocale
      }

    ControlSetText,Button1,%A_Space%%StartButtonText%,ahk_class Shell_TrayWnd  ;изменение текста на кнопке "Пуск"

Return


GetInputLangID(window)
{
    If !(hWnd := WinExist(window))
        return
 
    WinGetClass, Class
 
    if (Class == "ConsoleWindowClass")
    {
        WinGet, consolePID, PID
        DllCall("AttachConsole", Ptr, consolePID)
        VarSetCapacity(buff, 16)
        DllCall("GetConsoleKeyboardLayoutName", Str, buff)
        DllCall("FreeConsole")
        langID := "0x" . SubStr(buff, -3)
    }
    Else
        langID := DllCall("GetKeyboardLayout", Ptr, DllCall("GetWindowThreadProcessId", Ptr, hWnd, UInt, 0, Ptr), Ptr) & 0xFFFF
 
    return langID
}
 
GetInputLangName(langId)
{
    Size := (DllCall("GetLocaleInfo", UInt, langId, UInt, 0x1001, UInt, 0, UInt, 0) * 2)   ; LOCALE_SENGLANGUAGE := 0x1001
    VarSetCapacity(localeSig, Size, 0)
    DllCall("GetLocaleInfo", UInt, langId, UInt, 0x1001, Str, localeSig, UInt, Size)
    return localeSig
}

StartM: 
Send ^{Esc}
return

Недостатки.
На каждый язык нужно свое изображение. Если состояние CapsLock показывать в раскладке как в этом скрипте, требуется по дополнительному изображению на каждый язык.
Можно ли каким-то образом менять текст изображения прямо в скрипте, т.е. использовать одно изображение?
Хотя большинство использует 2-4 языка и дорисовать иконки - небольшая проблема.
Решение этого вопроса - лишь заявка на универсальность.

icons.zip

2 (изменено: monsoon, 2017-05-30 17:39:32)

Re: АНК: (из Коллекции) скрипт-индикатор для NumLock CapsLock ScrollLock..

Привык к этому скрипту.
Как его подправить, чтобы заработал в win7 в классической теме?
На всякий случай используемые изображения: icons.zip

Вот так выглядела кнопка Пуск в winXP для русской раскладки в нижнем регистре с включенными NumLock и Insert ("-" - отключен ScrollLock):
http://s1.bild.me/bilder/110417/1586406indicStart_.JPG

3

Re: АНК: (из Коллекции) скрипт-индикатор для NumLock CapsLock ScrollLock..

Вижу, что в этом скрипте меняется текст кнопки «Пуск». В Windows 7 это сделать не получится, так что никак.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

4

Re: АНК: (из Коллекции) скрипт-индикатор для NumLock CapsLock ScrollLock..

После поиска информации по крупицам кое-что получилось:


#Persistent
SetBatchLines, -1
StringCaseSense, On

Gui, +ToolWindow +AlwaysOnTop -Caption            
Gui, +Lastfound                      

PrevInputLocale:="xx"  ; переменная введена для того, чтобы не мерцало изображение с раскладкой 
PrevKeysState:="---"   ; переменная введена для того, чтобы не мерцал текст состояния клавиш

Gui, Margin, 0, 0
Gui, Add, Picture, x2 y3 w16 h16 gStartP vStartP, xx_s.bmp
Gui, Font, s8 bold, Courier New
Gui, Add, Text, x24 y4 w26 h16  gStartT vStartT, %PrevKeysState%
Gui, Show, x2 y744 , Start Button

SetTimer, Start, 200  ; настройте второй параметр, чтобы изменить интервал реагирования
Return

Start:
    StartButtonText = %NumToggle%%ScrollToggle%%InsToggle%

    GetKeyState, NumToggle, Numlock, T
    If NumToggle = U
        NumToggle = -
    Else
        NumToggle = N

    GetKeyState, ScrollToggle, ScrollLock, T
    If ScrollToggle = U
        ScrollToggle = -
    Else
        ScrollToggle = S

    GetKeyState,InsToggle, Insert, T
    If InsToggle = U
        InsToggle = -
    Else
        InsToggle = I

    GetKeyState, CapsToggle, CapsLock, T ; проверяем, включен ли Capslock

    InputLocale:= GetInputLangName(GetInputLangID("A"))

    StringLeft, InputLocale, InputLocale, 2
    If CapsToggle = U
      StringLower, InputLocale, InputLocale
    Else
      StringUpper, InputLocale, InputLocale


    IF (InputLocale <> PrevInputLocale)
      {
       IF InputLocale = en
         GuiControl,, Static1, en_s.bmp
       Else If InputLocale = EN
         GuiControl,, Static1, EN.bmp
       Else If InputLocale = ru
         GuiControl,, Static1, ru_s.bmp
       Else If InputLocale = RU
         GuiControl,, Static1, RU.bmp
       ELSE
         {
          If CapsToggle = U
            GuiControl,, Static1, xx_s.bmp
          Else
            GuiControl,, Static1, XX.bmp
         }
       PrevInputLocale := InputLocale
       sleep, 100
      }

    IF (StartButtonText <> PrevKeysState)
      {
       GuiControl,, Static2, %StartButtonText%
       PrevKeysState := StartButtonText
      }

Return


GetInputLangID(window)
{
    If !(hWnd := WinExist(window))
        return
 
    WinGetClass, Class
 
    if (Class == "ConsoleWindowClass")
    {
        WinGet, consolePID, PID
        DllCall("AttachConsole", Ptr, consolePID)
        VarSetCapacity(buff, 16)
        DllCall("GetConsoleKeyboardLayoutName", Str, buff)
        DllCall("FreeConsole")
        langID := "0x" . SubStr(buff, -3)
    }
    Else
        langID := DllCall("GetKeyboardLayout", Ptr, DllCall("GetWindowThreadProcessId", Ptr, hWnd, UInt, 0, Ptr), Ptr) & 0xFFFF
 
    return langID
}
 
GetInputLangName(langId)
{
    Size := (DllCall("GetLocaleInfo", UInt, langId, UInt, 0x1001, UInt, 0, UInt, 0) * 2)   ; LOCALE_SENGLANGUAGE := 0x1001
    VarSetCapacity(localeSig, Size, 0)
    DllCall("GetLocaleInfo", UInt, langId, UInt, 0x1001, Str, localeSig, UInt, Size)
    return localeSig
}

StartP: 
StartT: 
Send ^{Esc}
return 

Скрипт настроен под разрешение 768 по высоте. Можно было бы определять разрешение и определять координаты относительно него.
Но основной вопрос: как сделать так, чтобы измененная кнопка Пуск восстанавливалась после нажатия на нее или после клика на свободном месте панели задач и т.п., на winXP этого не требовалось.

5 (изменено: teadrinker, 2017-05-30 16:34:42)

Re: АНК: (из Коллекции) скрипт-индикатор для NumLock CapsLock ScrollLock..

Не совсем понял вопрос. В коде кнопка Пуск никак не меняется, она просто перекрывается окном скрипта. Что именно нужно-то, чтобы клик проходил сквозь него?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

6 (изменено: monsoon, 2017-05-30 17:26:16)

Re: АНК: (из Коллекции) скрипт-индикатор для NumLock CapsLock ScrollLock..

teadrinker
Когда скрипт только запущен все отображается прекрасно. Клик-то как раз проходит, но после него, возвращается показ стандартной кнопки и требуется перезапустить скрипт. Тоже самое происходит, если например подвести курсор мыши к какой-либо программе на панели задач и дождаться появления тултипа.
Т.е. хотелось бы, чтобы перекрытие с раскладкой было всегда над кнопкой.

7 (изменено: teadrinker, 2017-05-30 18:20:35)

Re: АНК: (из Коллекции) скрипт-индикатор для NumLock CapsLock ScrollLock..

Попробуйте так:


#Persistent
SetBatchLines, -1
StringCaseSense, On

SWP_NOSIZE := 1, GW_HWNDNEXT := SWP_NOMOVE := 2

Gui, +ToolWindow +AlwaysOnTop -Caption +hwndhGui  
Gui, +Lastfound                      

PrevInputLocale:="xx"  ; переменная введена для того, чтобы не мерцало изображение с раскладкой 
PrevKeysState:="---"   ; переменная введена для того, чтобы не мерцал текст состояния клавиш

Gui, Margin, 0, 0
Gui, Add, Picture, x2 y3 w16 h16 gStartP vStartP, xx_s.bmp
Gui, Font, s8 bold, Courier New
Gui, Add, Text, x24 y4 w26 h16  gStartT vStartT, %PrevKeysState%

WinGetPos, X, Y,,, % "ahk_id" hButton := WinExist("ahk_class Button")
Gui, Show, x%X% y%Y% , Start Button

SetTimer, Start, 200  ; настройте второй параметр, чтобы изменить интервал реагирования
Return

Start:
    ButtonAbove := false
    Loop
        hWnd := A_Index = 1 ? DllCall("GetTopWindow", Ptr, 0, Ptr) : DllCall("GetWindow", Ptr, hWnd, UInt, GW_HWNDNEXT, Ptr)
    until (hWnd = hButton && ButtonAbove := true) || hWnd = hGui
    if ButtonAbove
        DllCall("SetWindowPos", Ptr, hGui, Ptr, 0, Int, 0, Int, 0, Int, 0, Int, 0, UInt, SWP_NOSIZE|SWP_NOMOVE)
        
    StartButtonText = %NumToggle%%ScrollToggle%%InsToggle%

    GetKeyState, NumToggle, Numlock, T
    If NumToggle = U
        NumToggle = -
    Else
        NumToggle = N

    GetKeyState, ScrollToggle, ScrollLock, T
    If ScrollToggle = U
        ScrollToggle = -
    Else
        ScrollToggle = S

    GetKeyState,InsToggle, Insert, T
    If InsToggle = U
        InsToggle = -
    Else
        InsToggle = I

    GetKeyState, CapsToggle, CapsLock, T ; проверяем, включен ли Capslock

    InputLocale:= GetInputLangName(GetInputLangID("A"))

    StringLeft, InputLocale, InputLocale, 2
    If CapsToggle = U
      StringLower, InputLocale, InputLocale
    Else
      StringUpper, InputLocale, InputLocale


    IF (InputLocale <> PrevInputLocale)
      {
       IF InputLocale = en
         GuiControl,, Static1, en_s.bmp
       Else If InputLocale = EN
         GuiControl,, Static1, EN.bmp
       Else If InputLocale = ru
         GuiControl,, Static1, ru_s.bmp
       Else If InputLocale = RU
         GuiControl,, Static1, RU.bmp
       ELSE
         {
          If CapsToggle = U
            GuiControl,, Static1, xx_s.bmp
          Else
            GuiControl,, Static1, XX.bmp
         }
       PrevInputLocale := InputLocale
       sleep, 100
      }

    IF (StartButtonText <> PrevKeysState)
      {
       GuiControl,, Static2, %StartButtonText%
       PrevKeysState := StartButtonText
      }

Return


GetInputLangID(window)
{
    If !(hWnd := WinExist(window))
        return
 
    WinGetClass, Class
 
    if (Class == "ConsoleWindowClass")
    {
        WinGet, consolePID, PID
        DllCall("AttachConsole", Ptr, consolePID)
        VarSetCapacity(buff, 16)
        DllCall("GetConsoleKeyboardLayoutName", Str, buff)
        DllCall("FreeConsole")
        langID := "0x" . SubStr(buff, -3)
    }
    Else
        langID := DllCall("GetKeyboardLayout", Ptr, DllCall("GetWindowThreadProcessId", Ptr, hWnd, UInt, 0, Ptr), Ptr) & 0xFFFF
 
    return langID
}
 
GetInputLangName(langId)
{
    Size := (DllCall("GetLocaleInfo", UInt, langId, UInt, 0x1001, UInt, 0, UInt, 0) * 2)   ; LOCALE_SENGLANGUAGE := 0x1001
    VarSetCapacity(localeSig, Size, 0)
    DllCall("GetLocaleInfo", UInt, langId, UInt, 0x1001, Str, localeSig, UInt, Size)
    return localeSig
}

StartP: 
StartT: 
Send ^{Esc}
return 
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

8

Re: АНК: (из Коллекции) скрипт-индикатор для NumLock CapsLock ScrollLock..

teadrinker
Спасибо!!! Работает! При клике на Пуск появляется на доли секунды стандартная кнопка и восстанавливается окошко GUI с раскладкой:
http://s1.bild.me/bilder/110417/4239106screenshot_2017-05-30_001.jpg