1 (изменено: serzh82saratov, 2017-11-04 20:01:46)

Тема: AHK: Замена стандартного элемента управления "Hotkey"

Известно, что встроенный элемент управления GUI - "Hotkey" имеет большие ограничения по количеству определяемых клавиш. Более того всё равно приходится переделывать его записи буквенных клавиш в коды, и при чтении обратно - т.к. при несоответствующей записи раскладке языка, ГК (горячая клавиша) не будет работать, а при чтении (для отображения в контроле) запись не будет видна.
   Так как иногда приходится писать знакомым небольшие скрипты, и потом долго объяснять куда и что записать для изменения кнопки - решил написать функции для простого добавления пользователем, и для себя в код, ГК через GUI. Данный код определяет практически все кнопки, и кнопки первых четырёх джойстиков, также по необходимости определяет левые\правые модификаторы. 

----------------------------------------------

В коллекции библиотека с помощью которой возможно регистрировать контролы "Edit" копирующие поведение контрола "Hotkey".

----------------------------------------------

Ниже основной код, для разработки своего проекта.

Блок функций для разработчика

----------------------------------------------

Всё просто, при старте скрипта указываем имя функции в которую передаётся массив данных (значения его ключей в примере) при каждом нажатии клавиш, и опции:

Hotkey_Init(FuncName, Options)

Можно вызывать повторно для изменения функции или опций.
Options - необязательный параметр из любых возможных букв "MLRJU", в любой последовательности и регистре. Если не указан, то только клавиатура.

M - Кнопки мыши без левой и правой.
L - Левая кнопка мыши, определяется только с модификаторами.
R - Правая кнопка мыши.
J - Кнопки джойстика, определяются только без модификаторов.
U - (редко используется) Отправлять событие отпускания кнопки и в том случае когда есть конечная клавиша, также в этом случае при отпускании модификаторов она сбрасывается. Опция может быть полезна например для создания истории нажатий.

Для установки или снятия перехвата нажатий (хука) вызываем:

Hotkey_Hook(Value)

Value = 1 - установка хука.
Value = 0 - снятие хука.

Текущее cостояние перехвата вернёт:

Hotkey_Arr("Hook")

Простой пример:


#NoEnv
#SingleInstance Force
OnExit, GuiClose
OnMessage(0x6, "WM_ACTIVATE")
Hotkey_Init("MyFunc", "MLRJ")
Gui, +AlwaysOnTop
Gui, Add, Text, w400 r19 vText, Нажимайте в активном окне
Gui, Show
Return

MyFunc(K)   {
    GuiControl, , Text, % K.Mods K.Name "`n`n"
        . K.Pref K.HK "`n`n---`n`n"
        . K.LRMods K.Name "`n`n"
        . K.LRPref K.HK "`n`n---`n`n"
        . K.TK "`n`n"
        . K.VK "`n`n"
        . K.SC "`n`n"
		. "Up: " K.Up "`t"
		. "IsMod: " K.IsMod "`t"
		. "IsJM: " K.IsJM "`t"   ; 1 - Joy, 2 - Mouse, 0 - Keyboard
		. "NFP: " K.NFP "`t"		; Не физическое нажатие
		. "Time: " K.Time "      "
		. K.PCtrl K.PAlt K.PShift K.PWin "`t"
		. K.PLCtrl K.PRCtrl K.PLAlt K.PRAlt K.PLShift K.PRShift K.PLWin K.PRWin
}

WM_ACTIVATE(wp)   {
    Hotkey_Hook(wp & 0xFFFF)
}

GuiClose:
    ExitApp

В этом скрипте более полный пример использования функций, а также наглядный способ получения информации о кнопках.
Ещё пример - скрипт для создания массивов.

Для наилучшей производительности клавиатурного хука в секции автовыполнения рекомендуется использование:

#NoEnv
ListLines Off  
SetBatchLines -1
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

2 (изменено: teadrinker, 2013-08-14 04:26:38)

Re: AHK: Замена стандартного элемента управления "Hotkey"

"Код для иллюстрации" из поста в Коллекции не работает. Там явная ошибка:

IniWrite, % %A_GuiControl%, % A_ScriptFullPath, Section, % A_GuiControl

Путь к ini-файлу не может быть A_ScriptFullPath.

Кроме того, в коде такой недостаток: в функциях используется несколько OnMessage(). Если пользователь добавит в свой скрипт такие же, отслеживающие те же сообщения, твои перестанут работать. Также используется команда OnExit, если пользователь вставит свою — твоя перестанет работать.

Набросал свой вариант, более простой в использовании и различающий левые и правые модификаторы:

Gui, Add, Edit, hwndhEdit1 vHK1 gHotkey w150 h20 Center
Gui, Add, Edit, hwndhEdit2 vHK2 gHotkey w150 h20 Center
Gui, Add, Edit, vShowHotkey w150 h20 Center
Gui, Show

HotkeyInit(hEdit1, hEdit2)   ; передаём в функцию хендлы нужных контролов через запятую
return

Hotkey:
   HotkeyString := ""
   KeysArray := {Ctrl: "^", Alt: "!", Shift: "+", Win: "#"}
   
   GuiControlGet, Text, %A_Gui%:, %A_GuiControl%
   if (Text != "" && Text != "Нет" && Substr(Text, -1) != "+ ")
   {
      String := RegExReplace(Text, "\s")
      Loop, parse, String, +
      {
         IsSym := ""
         for k,v in KeysArray
            if InStr(A_LoopField, k)
               HotkeyString .= (SubStr(A_LoopField, 1, 1) = "L" ? "<" : ">") . v, IsSym := 1
         
         PrevFormat := A_FormatInteger
         SetFormat, IntegerFast, H
         if !IsSym
            HotkeyString .= "vk" . SubStr(GetKeyVK(A_LoopField), 3) . "sc" . SubStr(GetKeySC(A_LoopField), 3)
         SetFormat, IntegerFast, % PrevFormat
      }
      
      GuiControl, %A_Gui%:, ShowHotkey, % HotkeyString
;     Hotkey, % HotkeyString, HKLabel, On   ; раскомментировать для установки хоткея
   }
   return
   
HKLabel:
   MsgBox, Вы нажали горячую клавишу %A_ThisHotkey%
   return

GuiClose:
   ExitApp

HotkeyInit(handles*)
{
   global oHK_VarsArray := {handles: handles}
   
   hEdit := oHK_VarsArray.handles.1
   hGui := DllCall("GetParent", Ptr, hEdit, Ptr)
   
   ControlGetFocus, Var, ahk_id %hGui%
   GuiControlGet, OutputVar, %hGui%:Hwnd, % Var
   
   for k,v in handles
   {
      ControlSetText,, Нет, % "ahk_id" v
      if (OutputVar = v)
         oHK_VarsArray.hHook := SetWindowsHookEx()
            , oHK_VarsArray.hControl := v
   }
   
   SetWinEventHook(0x8005, 0x8005, 0, RegisterCallback("HookProc", "F"),0,0,0)   ; EVENT_OBJECT_FOCUS := 0x8005
}

SetWindowsHookEx()
{
   Return DllCall("SetWindowsHookEx" . (A_IsUnicode ? "W" : "A")
      , Int, WH_KEYBOARD_LL := 13
      , Ptr, RegisterCallback("LowLevelKeyboardProc", "Fast")
      , Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
      , UInt, 0, Ptr)
}

LowLevelKeyboardProc(nCode, wParam, lParam)
{
   global oHK_VarsArray
   static WM_KEYDOWN := 0x100, WM_KEYUP := 0x101, WM_SYSKEYDOWN := 0x104, WM_SYSKEYUP := 0x105
      , prevMessage, prevKey, keys, EndKey
   
   SetFormat, IntegerFast, H
   Message := wParam, Extended := NumGet(lParam+0, 8, "UInt") & 1
   sc := Extended << 8 | NumGet(lParam+0, 4, "UInt"), vk := NumGet(lParam+0, 0, "UInt")
   key := GetKeyName("vk" SubStr(vk, 3) "sc" SubStr(sc, 3))

   if (wParam = prevMessage && key = prevKey)
      Return nCode < 0 ? DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam) : 1
   
   prevMessage := wParam, prevKey := key
   
   if key in LControl,RControl
      key := SubStr(key, 1, 1) . "Ctrl"
   
   if (Message = WM_KEYDOWN || Message = WM_SYSKEYDOWN)
   {
      if (keys != "" && EndKey)
         keys := EndKey := ""
      
      if key in LCtrl,RCtrl,LAlt,RAlt,LShift,RShift,LWin,RWin
      {
         if !InStr(keys, key)
            keys := key . " + " . keys
      }
      else if (SubStr(keys, -1) = "+ " || keys = "")
         keys .= key
   }
   
   if (Message = WM_KEYUP || Message = WM_SYSKEYUP)
   {
      if key in LCtrl,RCtrl,LAlt,RAlt,LShift,RShift,LWin,RWin
         keys := RegExReplace(keys, key . " \+ ")
      else if (keys != "")
         EndKey := 1
         
      if !EndKey
         SetTimer, SetText, -10
      
      Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam)
   }

   if !EndKey
      SetTimer, SetText, -10
   Return nCode < 0 ? DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam) : 1
   
SetText:
   ControlSetText,, % keys = "" ? "Нет" : keys, % "ahk_id" oHK_VarsArray.hControl
   return
}

SetWinEventHook(eventMin, eventMax, hmodWinEventProc, lpfnWinEventProc, idProcess, idThread, dwFlags)
{
   return DllCall("SetWinEventHook" , UInt, eventMin
                                    , UInt, eventMax
                                    , Ptr, hmodWinEventProc
                                    , Ptr, lpfnWinEventProc
                                    , UInt, idProcess
                                    , UInt, idThread
                                    , UInt, dwFlags, Ptr)
}

HookProc(hWinEventHook, event, hwnd)
{
   global oHK_VarsArray
   
   for k,v in oHK_VarsArray
      if (k = "handles")
         for m,n in v
            if (hwnd = n)
               IsValue := 1, oHK_VarsArray.hControl := n
   
   if (IsValue && !oHK_VarsArray.hHook)
      oHK_VarsArray.hHook := SetWindowsHookEx()
   else if (!IsValue && oHK_VarsArray.hHook)
      DllCall("UnhookWindowsHookEx", Ptr, oHK_VarsArray.hHook), oHK_VarsArray.hHook := ""
}

Первые два Edit-контрола для ввода клавиш, третий — для демонстрации модифицированного вида.
Код работает для любой битности.

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

3 (изменено: serzh82saratov, 2013-08-14 15:41:06)

Re: AHK: Замена стандартного элемента управления "Hotkey"

Спасибо за пример. Как всегда познавательный.
Я тоже думал сделать вариант различающий левые и правые модификаторы, но пошёл по подобию обычного контрола. Также в начале передавались хэндлы, но заменил на обычные переменные для понимания начинающих пользователей. Опять же для простоты ассоциированным переменным Edit назначаются коды кнопок. Вообщем задача была полностью скопировать Hotkey.

Набросал свой вариант, более простой в использовании

Врядли начинающим твоя подпрограмма Hotkey будет более понятна, чем простое  использование значения ассоциированной переменной.

Кроме того, в коде такой недостаток: в функциях используется несколько OnMessage(). Если пользователь добавит в свой скрипт такие же, отслеживающие те же сообщения, твои перестанут работать. Также используется команда OnExit, если пользователь вставит свою — твоя перестанет работать.

Да на полную библиотечность мой код не претендует, это точно.
А если пользователь поставит свой SetWinEventHook?

третий — для демонстрации модифицированного вида.

Символьные кнопки выдают vk0sc0.

Код работает для любой битности.

Подскажи, почему неработают мои в х64? Позавчера я честно пытался переделать.

Путь к ini-файлу не может быть A_ScriptFullPath.

??? Всё работает в некомпилированном виде. Сделано для теста, чтоб не создавать мусор.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

4 (изменено: serzh82saratov, 2013-08-14 15:42:12)

Re: AHK: Замена стандартного элемента управления "Hotkey"

HotkeyInit(handles*)

Кстати что значит звёздочка после параметра? Сколько читал, непойму.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

5 (изменено: serzh82saratov, 2013-08-14 15:46:37)

Re: AHK: Замена стандартного элемента управления "Hotkey"

teadrinker
При деактивации окна нажатые модификаторы (без кнопки) остаются прописанными, а надо бы сброс на слово "нет" по аналогии.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

6

Re: AHK: Замена стандартного элемента управления "Hotkey"

serzh82saratov пишет:

Врядли начинающим твоя подпрограмма Hotkey будет более понятна, чем простое  использование значения ассоциированной переменной.

Ассоциированная переменная не уникальна, они могут быть одинаковыми в разных GUI. Придётся тогда в функцию и идентификатор GUI передавать, что несколько усложняет использование.

serzh82saratov пишет:

Да на полную библиотечность мой код не претендует, это точно.

Это ещё и потому, что используется огромное количество глобальных переменных. Не ровён час, пользователь может с чем-то пересечься, таким образом получатся совершенно "необъяснимые" глюки. У меня, правда, тоже там есть один глобальный массив. Если удастся привести к "библиотечному" виду, выложу в Коллекции.

serzh82saratov пишет:

А если пользователь поставит свой SetWinEventHook?

Их можно ставить сколько угодно, такие хуки не пропускают через себя события, а просто отслеживают их.

Символьные кнопки выдают vk0sc0.

У тебя, наверно, русская раскладка по умолчанию стоит. В русской почему-то не считывает, исправлю.

Подскажи, почему неработают мои в х64? Позавчера я честно пытался переделать.

Не, не заставишь

??? Всё работает в некомпилированном виде. Сделано для теста, чтоб не создавать мусор.

Я, наверно, чего-то не понял. Я думал, ини-файлы нужны, чтобы сохранять хоткеи от сессии к сессии. Для чего они там вообще? И как они работают, если путь невалидный?

Кстати что значит звёздочка после параметра?

Говорит о том, что функция в данном параметре принимает массив параметров. Нужно, когда заранее неизвестно, сколько параметров понадобится передавать.

При деактивации окна нажатые модификаторы (без кнопки) остаются прописанными, а надо бы сброс на слово "нет" по аналогии.

Тут дело вкуса, это ведь просто демонстрационный контрол, пользователю он не нужен.

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

7

Re: AHK: Замена стандартного элемента управления "Hotkey"

teadrinker пишет:

Ассоциированная переменная не уникальна, они могут быть одинаковыми в разных GUI. Придётся тогда в функцию и идентификатор GUI передавать, что несколько усложняет использование.

Так в описании так и написано HF_Hotkey( "GuiName:MyHotkey1"). Содержимое переменной нужно только в момент вызова метки, так что ошибки не будет.

WriteIni:  
    Gui Show, , %  A_GuiControl " = " %A_GuiControl% 
    return

Если надо сохранять более длительно, то нетрудно это учесть и задать разные имена переменных.

teadrinker пишет:

Это ещё и потому, что используется огромное количество глобальных переменных. Не ровён час, пользователь может с чем-то пересечься, таким образом получатся совершенно "необъяснимые" глюки.

Описание пишет:

Все названия функций, подпрограмм и глобальных переменных имеют префикс "HF_".

Это тоже нетрудно учесть.

teadrinker пишет:

Не, не заставишь

Очень жаль, я сам не могу понять в чём дело. Ну да и бог с ним х64 интерпретатором.

teadrinker пишет:

Я, наверно, чего-то не понял. Я думал, ини-файлы нужны, чтобы сохранять хоткеи от сессии к сессии. Для чего они там вообще? И как они работают, если путь невалидный?

Почему ты думаешь что путь невалидный? Всё сохраняется как положено. Ини файлом служит текстовый файл самого скрипта, в чём тут проблема? Самих по себе хоткеев там нет, просто демонстрация правильности записи, и обратного их представления в Edit при перезапуске скрипта.

/*
[Section]
MyHotkey1=Space  
MyHotkey2=^!vk46  
MyHotkey3=vk44  
*/
teadrinker пишет:

Говорит о том, что функция в данном параметре принимает массив параметров. Нужно, когда заранее неизвестно, сколько параметров понадобится передавать.

Мало что понял, объясни подробнее, например по строкам:

HotkeyInit(handles*)
{
   global oHK_VarsArray := {handles: handles}
   
   hEdit := oHK_VarsArray.handles.1
teadrinker пишет:

Тут дело вкуса, это ведь просто демонстрационный контрол, пользователю он не нужен.

Думаю тут дело правила. Кому нужны модификаторы без конечной клавиши? Оно и в Винде и в AutoHotkey так. Модификаторы должны сбрасыватся если нет конечной клавиши.
Может ты меня не так понял, я про это

LWin + LAlt + LShift + LCtrl + 

оно остаётся не в демонстрационном контроле. Плюс в моём варианте переменная в таком случае очищается.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

8

Re: AHK: Замена стандартного элемента управления "Hotkey"

serzh82saratov пишет:

Так в описании так и написано HF_Hotkey( "GuiName:MyHotkey1").

Так это к вопросу о простоте использования . Кроме переменной нужно ещё и GUI прописывать. Имхо, хэндл проще.

Это тоже нетрудно учесть.

Ну я и говорю, много чего учитывать нужно .

Ини файлом служит текстовый файл самого скрипта

Ну вот видишь, даже я ничего не понял, куда там несчастному пользователю!

Мало что понял, объясни подробнее, например по строкам:

MyFunc("раз", "два", "три")

MyFunc(params*)
{
   for k,v in params
      MsgBox, % v
}

оно остаётся не в демонстрационном контроле.

Ты, может, код из почтового сообщения взял? Там была такая ошибка, отредактировано.

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

9

Re: AHK: Замена стандартного элемента управления "Hotkey"

teadrinker пишет:

Так это к вопросу о простоте использования . Кроме переменной нужно ещё и GUI прописывать. Имхо, хэндл проще.

Ну зато hwnd в опции не надо дописывать

teadrinker пишет:

Ну вот видишь, даже я ничего не понял, куда там несчастному пользователю!

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

teadrinker пишет:

MyFunc("раз", "два", "три")

MyFunc(params*)
{
   for k,v in params
      MsgBox, % v
}

А, понял. Тут params это одномерный (не ассоциативный) массив. Не понял только строку

HK_VarsArray := {handles: handles}

Массив обычно объявляется так

HK_VarsArray := {}
teadrinker пишет:

Ты, может, код из почтового сообщения взял? Там была такая ошибка, отредактировано.

Точно нет. Ещё раз проверил код из 4 сообщения.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

10

Re: AHK: Замена стандартного элемента управления "Hotkey"

А такой код как работает?

Gui, Add, Edit, hwndhEdit1 gHotkey w150 h20 Center
Gui, Add, Edit, hwndhEdit2 gHotkey w150 h20 Center
Gui, Add, Edit, vShowHotkey w150 h20 Center
Gui, Show

HotkeyInit(HotkeyString, hEdit1, hEdit2)   ; передаём в функцию переменную для передачи информации
return                                     ; и хендлы нужных контролов через запятую

Hotkey:
   VarSetCapacity(HotkeyString, -1)
   GuiControl, %A_Gui%:, ShowHotkey, % HotkeyString
   
;  Hotkey, % HotkeyString, HKLabel, On   ; раскомментировать для установки хоткея
   return
   
HKLabel:
   MsgBox, Вы нажали горячую клавишу %A_ThisHotkey%
   return

GuiClose:
   ExitApp

HotkeyInit(ByRef info, handles*)
{
   global oHK_VarsArray := {handles: handles}
   
   VarSetCapacity(info, 50)
   oHK_VarsArray.pInfo := &info
   
   hGui := DllCall("GetParent", Ptr, handles.1, Ptr)
   
   ControlGetFocus, Var, ahk_id %hGui%
   GuiControlGet, OutputVar, %hGui%:Hwnd, % Var
   
   for k,v in handles
   {
      ControlSetText,, Нет, % "ahk_id" v
      if (OutputVar = v)
         oHK_VarsArray.hHook := SetWindowsHookEx()
            , oHK_VarsArray.hControl := v
   }
   
   SetWinEventHook(0x8005, 0x8005, 0, RegisterCallback("HookProc", "F"),0,0,0)   ; EVENT_OBJECT_FOCUS := 0x8005
}

SetWindowsHookEx()
{
   Return DllCall("SetWindowsHookEx" . (A_IsUnicode ? "W" : "A")
      , Int, WH_KEYBOARD_LL := 13
      , Ptr, RegisterCallback("LowLevelKeyboardProc", "Fast")
      , Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
      , UInt, 0, Ptr)
}

LowLevelKeyboardProc(nCode, wParam, lParam)
{
   global oHK_VarsArray
   static WM_KEYDOWN := 0x100, WM_KEYUP := 0x101, WM_SYSKEYDOWN := 0x104, WM_SYSKEYUP := 0x105
      , prevMessage, prevKey, keys, EndKey, KeysArray := {Ctrl: "^", Alt: "!", Shift: "+", Win: "#"}
   
   SetBatchLines, -1
   SetFormat, IntegerFast, H
   Message := wParam, Extended := NumGet(lParam+0, 8, "UInt") & 1
   sc := Extended << 8 | NumGet(lParam+0, 4, "UInt"), vk := NumGet(lParam+0, 0, "UInt")
   key := GetKeyName("vk" SubStr(vk, 3) "sc" SubStr(sc, 3))

   if (wParam = prevMessage && key = prevKey)
      Return nCode < 0 ? DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam) : 1
   
   prevMessage := wParam, prevKey := key
   
   if key in LControl,RControl
      key := SubStr(key, 1, 1) . "Ctrl"
   
   if (Message = WM_KEYDOWN || Message = WM_SYSKEYDOWN)
   {
      if (keys != "" && EndKey)
         keys := EndKey := ""
      
      if key in LCtrl,RCtrl,LAlt,RAlt,LShift,RShift,LWin,RWin
      {
         if !InStr(keys, key)
            keys := key . " + " . keys
      }
      else if (SubStr(keys, -1) = "+ " || keys = "")
         keys .= key
            , oHK_VarsArray.EndKey := "vk" . SubStr(vk, 3) . "sc" . SubStr(sc, 3)
   }
   
   if (Message = WM_KEYUP || Message = WM_SYSKEYUP)
   {
      if key in LCtrl,RCtrl,LAlt,RAlt,LShift,RShift,LWin,RWin
         keys := RegExReplace(keys, key . " \+ ")
      else if (keys != "")
         EndKey := 1
         
      if !EndKey
         SetTimer, SetText, -30
      
      Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam)
   }

   if !EndKey
      SetTimer, SetText, -30
   Return nCode < 0 ? DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam) : 1
   
SetText:
   SetBatchLines, -1
   if (keys != "" && keys != "Нет" && Substr(keys, -1) != "+ ")
   {
      String := RegExReplace(keys, "\s")
      Loop, parse, String, +
      {
         IsSym := ""
         for k,v in KeysArray
            if InStr(A_LoopField, k)
               HKString .= (SubStr(A_LoopField, 1, 1) = "L" ? "<" : ">") . v, IsSym := 1
         
         if !IsSym
            HKString .= oHK_VarsArray.EndKey
      }
      StrPut(HKString, oHK_VarsArray.pInfo)
   }
   ControlSetText,, % keys = "" ? "Нет" : keys, % "ahk_id" oHK_VarsArray.hControl
   return
}

SetWinEventHook(eventMin, eventMax, hmodWinEventProc, lpfnWinEventProc, idProcess, idThread, dwFlags)
{
   return DllCall("SetWinEventHook" , UInt, eventMin
                                    , UInt, eventMax
                                    , Ptr, hmodWinEventProc
                                    , Ptr, lpfnWinEventProc
                                    , UInt, idProcess
                                    , UInt, idThread
                                    , UInt, dwFlags, Ptr)
}

HookProc(hWinEventHook, event, hwnd)
{
   global oHK_VarsArray
   
   for k,v in oHK_VarsArray
      if (k = "handles")
         for m,n in v
            if (hwnd = n)
               IsValue := 1, oHK_VarsArray.hControl := n
   
   if (IsValue && !oHK_VarsArray.hHook)
      oHK_VarsArray.hHook := SetWindowsHookEx()
   else if (!IsValue && oHK_VarsArray.hHook)
      DllCall("UnhookWindowsHookEx", Ptr, oHK_VarsArray.hHook), oHK_VarsArray.hHook := ""
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

11

Re: AHK: Замена стандартного элемента управления "Hotkey"

А такой код как работает?

Плохо. Выяснилось также что они не сбрасываются и для других.
То есть нажимаем в 1 поле LShift + LCtrl + и деактивируем окно. LShift + LCtrl + остаются в поле. Активируем окно, во втором поле нажимаем (например) Space, и прописывается LShift + LCtrl + Space.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

12

Re: AHK: Замена стандартного элемента управления "Hotkey"

То-есть, проблема в том, что если деактивировать окно, удерживая клавиши, они остаются в поле? И всё? Если не деактивировать, всё нормально?

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

13

Re: AHK: Замена стандартного элемента управления "Hotkey"

Ну в общем, да.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

14

Re: AHK: Замена стандартного элемента управления "Hotkey"

serzh82saratov пишет:

А такой код как работает?

Плохо.

Ну ты строгий! Исправлю

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

15

Re: AHK: Замена стандартного элемента управления "Hotkey"

Gui, Add, Edit, hwndhEdit1 gHotkey w150 h20 Center
Gui, Add, Edit, hwndhEdit2 gHotkey w150 h20 Center
Gui, Add, Edit, vShowHotkey w150 h20 Center
Gui, Show

HotkeyInit(HotkeyString, hEdit1, hEdit2)   ; передаём в функцию переменную для передачи информации
return                                     ; и хендлы нужных контролов через запятую

Hotkey:
   VarSetCapacity(HotkeyString, -1)
   GuiControl, %A_Gui%:, ShowHotkey, % HotkeyString
   
;  Hotkey, % HotkeyString, HKLabel, On   ; раскомментировать для установки хоткея
   return
   
HKLabel:
   MsgBox, Вы нажали горячую клавишу %A_ThisHotkey%
   return

GuiClose:
   ExitApp

HotkeyInit(ByRef info, handles*)
{
   global oHK_VarsArray := {handles: handles}
   
   VarSetCapacity(info, 50)
   oHK_VarsArray.pInfo := &info
   
   hGui := DllCall("GetParent", Ptr, handles.1, Ptr)
   
   ControlGetFocus, Var, ahk_id %hGui%
   GuiControlGet, OutputVar, %hGui%:Hwnd, % Var
   
   for k,v in handles
   {
      ControlSetText,, Нет, % "ahk_id" v
      if (OutputVar = v)
         oHK_VarsArray.hHook := SetWindowsHookEx()
            , oHK_VarsArray.hControl := v
   }
   
   SetWinEventHook(0x8005, 0x8005, 0, RegisterCallback("HookProc", "F"),0,0,0)   ; EVENT_OBJECT_FOCUS := 0x8005
}

SetWindowsHookEx()
{
   Return DllCall("SetWindowsHookEx" . (A_IsUnicode ? "W" : "A")
      , Int, WH_KEYBOARD_LL := 13
      , Ptr, RegisterCallback("LowLevelKeyboardProc", "Fast")
      , Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
      , UInt, 0, Ptr)
}

LowLevelKeyboardProc(nCode, wParam, lParam)
{
   global oHK_VarsArray
   static WM_KEYDOWN := 0x100, WM_KEYUP := 0x101, WM_SYSKEYDOWN := 0x104, WM_SYSKEYUP := 0x105
      , prevMessage, prevKey, keys, EndKey, KeysArray := {Ctrl: "^", Alt: "!", Shift: "+", Win: "#"}
   
   SetBatchLines, -1
   SetFormat, IntegerFast, H
   Message := wParam, Extended := NumGet(lParam+0, 8, "UInt") & 1
   sc := Extended << 8 | NumGet(lParam+0, 4, "UInt"), vk := NumGet(lParam+0, 0, "UInt")
   key := GetKeyName("vk" SubStr(vk, 3) "sc" SubStr(sc, 3))

   if (wParam = prevMessage && key = prevKey)
      Return nCode < 0 ? DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam) : 1
   
   prevMessage := wParam, prevKey := key
   
   if key in LControl,RControl
      key := SubStr(key, 1, 1) . "Ctrl"
   
   if (Message = WM_KEYDOWN || Message = WM_SYSKEYDOWN)
   {
      if (keys != "" && EndKey)
         keys := EndKey := ""
      
      if key in LCtrl,RCtrl,LAlt,RAlt,LShift,RShift,LWin,RWin
      {
         if !InStr(keys, key)
            keys := key . " + " . keys
      }
      else if (SubStr(keys, -1) = "+ " || keys = "")
         keys .= key
            , oHK_VarsArray.EndKey := "vk" . SubStr(vk, 3) . "sc" . SubStr(sc, 3)
   }
   
   if (Message = WM_KEYUP || Message = WM_SYSKEYUP)
   {
      if key in LCtrl,RCtrl,LAlt,RAlt,LShift,RShift,LWin,RWin
         keys := RegExReplace(keys, key . " \+ ")
      else if (keys != "")
         EndKey := 1
         
      if !EndKey
         SetTimer, SetText, -30
      
      Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam)
   }

   SetTimer, SetText, -30
   Return nCode < 0 ? DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam) : 1
   
SetText:
   if (keys != "" && keys != "Нет" && Substr(keys, -1) != "+ ")
   {
      String := RegExReplace(keys, "\s")
      Loop, parse, String, +
      {
         IsSym := ""
         for k,v in KeysArray
            if InStr(A_LoopField, k)
               HKString .= (SubStr(A_LoopField, 1, 1) = "L" ? "<" : ">") . v, IsSym := 1
         
         if !IsSym
            HKString .= oHK_VarsArray.EndKey
      }
      StrPut(HKString, oHK_VarsArray.pInfo)
   }
   ControlSetText,, % keys = "" ? "Нет" : keys, % "ahk_id" oHK_VarsArray.hControl
   return
}

SetWinEventHook(eventMin, eventMax, hmodWinEventProc, lpfnWinEventProc, idProcess, idThread, dwFlags)
{
   return DllCall("SetWinEventHook" , UInt, eventMin
                                    , UInt, eventMax
                                    , Ptr, hmodWinEventProc
                                    , Ptr, lpfnWinEventProc
                                    , UInt, idProcess
                                    , UInt, idThread
                                    , UInt, dwFlags, Ptr)
}

HookProc(hWinEventHook, event, hwnd)
{
   global oHK_VarsArray
   
   for k,v in oHK_VarsArray.handles
      if (hwnd = v)
         IsValue := 1, oHK_VarsArray.hControl := v
   
   if (IsValue && !oHK_VarsArray.hHook)
      oHK_VarsArray.hHook := SetWindowsHookEx()
   else if (!IsValue && oHK_VarsArray.hHook)
   {
      DllCall("UnhookWindowsHookEx", Ptr, oHK_VarsArray.hHook), oHK_VarsArray.hHook := ""
      
      for k,v in oHK_VarsArray.handles
      {
         ControlGetText, Text,, ahk_id %v%
         if SubStr(Text, -1) = "+ "
            ControlSetText,, Нет, ahk_id %v%
      }
   }
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

16

Re: AHK: Замена стандартного элемента управления "Hotkey"

Плохо. Выяснилось также что они не сбрасываются и для других.
То есть нажимаем в 1 поле LShift + LCtrl + и деактивируем окно. LShift + LCtrl + остаются в поле. Активируем окно, во втором поле нажимаем (например) Space, и прописывается LShift + LCtrl + Space.

Осталась проблема:

Активируем окно, во втором поле нажимаем (например) Space, и прописывается LShift + LCtrl + Space.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

17

Re: AHK: Замена стандартного элемента управления "Hotkey"

serzh82saratov пишет:

Осталась проблема:

Честно говоря, не понял. У меня всё нормально работает. Что нажато, то и прописывается. Опиши подробнее.

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

18 (изменено: serzh82saratov, 2013-08-14 22:20:13)

Re: AHK: Замена стандартного элемента управления "Hotkey"

Даже не знаю как ещё описать. В новом коде оказалось что всё тоже самое просто через раз:

То есть нажимаем в 1 поле LShift + LCtrl + и деактивируем окно. LShift + LCtrl + остаются в поле. Активируем окно, во втором поле нажимаем (например) Space, и прописывается LShift + LCtrl + Space.

В 1 поле держим нажатыми LShift + LCtrl, деактивируем окно. В поле один (теперь через раз) остаётся

LShift + LCtrl + 

это не гуд. Иногда всё таки пишется слово "Нет".
Далее:
Осталось: после этого активируем окно (не важно LShift + LCtrl + остались прописаны или нет в 1 поле), во 2 поле нажимаем (например) Space, и о чудо - прописывается LShift + LCtrl + Space. А нажата была только Space. И это тоже не гуд.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

19

Re: AHK: Замена стандартного элемента управления "Hotkey"

Действительно, чудо. У меня всё нормально работает на любом интерпретаторе. Win 7 64. А ты уверен, что это не последствия работы какого-то твоего скрипта, где остаются неотжатыми клавиши?

Если кто ещё читает этот пост, можете протестить последний код?

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

20

Re: AHK: Замена стандартного элемента управления "Hotkey"

Удалось поймать. У меня выходит глюк, если нажать модификаты при активном контроле, удерживая их, деактивировать окно, затем отпустить нажатые клавиши. Так, или ещё как-то?

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

21

Re: AHK: Замена стандартного элемента управления "Hotkey"

То есть нажимаем в 1 поле LShift + LCtrl + и деактивируем окно. LShift + LCtrl + остаются в поле.

Удалось поймать.

Теперь это надо ловить.
---
Но это:

Активируем окно, во втором поле нажимаем (например) Space, и прописывается LShift + LCtrl + Space.

всегда после таких удержаний

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

22

Re: AHK: Замена стандартного элемента управления "Hotkey"

А так?

Gui, Add, Edit, hwndhEdit1 gHotkey w150 h20 Center
Gui, Add, Edit, hwndhEdit2 gHotkey w150 h20 Center
Gui, Add, Edit, vShowHotkey w150 h20 Center
Gui, Show

HotkeyInit(HotkeyString, hEdit1, hEdit2)   ; передаём в функцию переменную для передачи информации
return                                     ; и хендлы нужных контролов через запятую

Hotkey:
   VarSetCapacity(HotkeyString, -1)
   GuiControl, %A_Gui%:, ShowHotkey, % HotkeyString
   
;  Hotkey, % HotkeyString, HKLabel, On   ; раскомментировать для установки хоткея
   return
   
HKLabel:
   MsgBox, Вы нажали горячую клавишу %A_ThisHotkey%
   return

GuiClose:
   ExitApp

HotkeyInit(ByRef info, handles*)
{
   global oHK_VarsArray := {handles: handles}
   
   VarSetCapacity(info, 50)
   oHK_VarsArray.pInfo := &info
   
   hGui := DllCall("GetParent", Ptr, handles.1, Ptr)
   
   ControlGetFocus, Var, ahk_id %hGui%
   GuiControlGet, OutputVar, %hGui%:Hwnd, % Var
   
   for k,v in handles
   {
      ControlSetText,, Нет, % "ahk_id" v
      if (OutputVar = v)
         oHK_VarsArray.hHook := SetWindowsHookEx()
            , oHK_VarsArray.hControl := v
   }
   
   SetWinEventHook(0x8005, 0x8005, 0, RegisterCallback("HookProc", "F"),0,0,0)   ; EVENT_OBJECT_FOCUS := 0x8005
}

SetWindowsHookEx()
{
   Return DllCall("SetWindowsHookEx" . (A_IsUnicode ? "W" : "A")
      , Int, WH_KEYBOARD_LL := 13
      , Ptr, RegisterCallback("LowLevelKeyboardProc", "Fast")
      , Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
      , UInt, 0, Ptr)
}

LowLevelKeyboardProc(nCode, wParam, lParam)
{
   global oHK_VarsArray
   static WM_KEYDOWN := 0x100, WM_KEYUP := 0x101, WM_SYSKEYDOWN := 0x104, WM_SYSKEYUP := 0x105
      , prevMessage, prevKey, EndKey
   
   SetBatchLines, -1
   SetFormat, IntegerFast, H
   Message := wParam, Extended := NumGet(lParam+0, 8, "UInt") & 1
   sc := Extended << 8 | NumGet(lParam+0, 4, "UInt"), vk := NumGet(lParam+0, 0, "UInt")
   key := GetKeyName("vk" SubStr(vk, 3) "sc" SubStr(sc, 3))

   if (wParam = prevMessage && key = prevKey)
      Return nCode < 0 ? DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam) : 1
   
   prevMessage := wParam, prevKey := key
   
   if key in LControl,RControl
      key := SubStr(key, 1, 1) . "Ctrl"
   
   if (Message = WM_KEYDOWN || Message = WM_SYSKEYDOWN)
   {
      if (oHK_VarsArray.keys != "" && EndKey)
         oHK_VarsArray.keys := EndKey := ""
      
      if key in LCtrl,RCtrl,LAlt,RAlt,LShift,RShift,LWin,RWin
      {
         if !InStr(oHK_VarsArray.keys, key)
            oHK_VarsArray.keys := key . " + " . oHK_VarsArray.keys
      }
      else if (SubStr(oHK_VarsArray.keys, -1) = "+ " || oHK_VarsArray.keys = "")
         oHK_VarsArray.keys .= key
            , oHK_VarsArray.EndKey := "vk" . SubStr(vk, 3) . "sc" . SubStr(sc, 3)
   }
   
   if (Message = WM_KEYUP || Message = WM_SYSKEYUP)
   {
      if key in LCtrl,RCtrl,LAlt,RAlt,LShift,RShift,LWin,RWin
         oHK_VarsArray.keys := RegExReplace(oHK_VarsArray.keys, key . " \+ ")
      else if (oHK_VarsArray.keys != "")
         EndKey := 1
         
      if !EndKey
         SetTimer, SetText, -30
      
      Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam)
   }

   SetTimer, SetText, -30
   Return nCode < 0 ? DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam) : 1
   
SetText:
   keys := oHK_VarsArray.keys
   if (keys != "" && keys != "Нет" && Substr(keys, -1) != "+ ")
   {
      String := RegExReplace(keys, "\s")
      Loop, parse, String, +
      {
         IsSym := ""
         for k,v in {Ctrl: "^", Alt: "!", Shift: "+", Win: "#"}
            if InStr(A_LoopField, k)
               HKString .= (SubStr(A_LoopField, 1, 1) = "L" ? "<" : ">") . v, IsSym := 1
         
         if !IsSym
            HKString .= oHK_VarsArray.EndKey
      }
      StrPut(HKString, oHK_VarsArray.pInfo)
   }
   ControlSetText,, % keys = "" ? "Нет" : keys, % "ahk_id" oHK_VarsArray.hControl
   return
}

SetWinEventHook(eventMin, eventMax, hmodWinEventProc, lpfnWinEventProc, idProcess, idThread, dwFlags)
{
   return DllCall("SetWinEventHook" , UInt, eventMin
                                    , UInt, eventMax
                                    , Ptr, hmodWinEventProc
                                    , Ptr, lpfnWinEventProc
                                    , UInt, idProcess
                                    , UInt, idThread
                                    , UInt, dwFlags, Ptr)
}

HookProc(hWinEventHook, event, hwnd)
{
   global oHK_VarsArray
   
   for k,v in oHK_VarsArray.handles
      if (hwnd = v)
         IsValue := 1, oHK_VarsArray.hControl := v
   
   if (IsValue && !oHK_VarsArray.hHook)
      oHK_VarsArray.hHook := SetWindowsHookEx()
   else if (!IsValue && oHK_VarsArray.hHook)
   {
      DllCall("UnhookWindowsHookEx", Ptr, oHK_VarsArray.hHook)
      oHK_VarsArray.keys := oHK_VarsArray.hHook := ""
      
      for k,v in oHK_VarsArray.handles
      {
         ControlGetText, Text,, ahk_id %v%
         if SubStr(Text, -1) = "+ "
            ControlSetText,, Нет, ahk_id %v%
      }
   }
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

23

Re: AHK: Замена стандартного элемента управления "Hotkey"

Держишь модификатор (к примеру) LAlt. Нажимаешь Space. Пишется

LAlt + Space

Ещё раз нажимаешь Space (держа далее LAlt), пишется Space.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

24

Re: AHK: Замена стандартного элемента управления "Hotkey"

А теперь нажатые модификаторы при деактивации не залипают?

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

25

Re: AHK: Замена стандартного элемента управления "Hotkey"

А теперь нажатые модификаторы при деактивации не залипают?

Вроде как нет. Но в воздухе летает что то потустороннее. Как то подглючивает, но пока не могу выразить.
---
И ещё, запись хоткеев как vk sc кода работает не для всех кнопок:

vk26sc148:: MsgBox Up ; Кнопка вверх. Она такая не одна.

надо бы как то по другому их записывать

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

26

Re: AHK: Замена стандартного элемента управления "Hotkey"

serzh82saratov пишет:

Но в воздухе летает что то потустороннее.

Ага, нашёл там ошибочку, исправил уже.

И ещё, запись хоткеев как vk sc кода работает не для всех кнопок:

Да, у меня на цифровой клавиатуре тоже срабатывает. Надо подумать.

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

27

Re: AHK: Замена стандартного элемента управления "Hotkey"

Этот вариант работает у вас на х64?

+ открыть спойлер

#SingleInstance Force
Gui, Add, Edit, Center ReadOnly w300 gShow vMyHotkey1 
HF_Hotkey( "MyHotkey1")
Gui, Show
return

Show:  
    Gui Show, , %  A_GuiControl " = " %A_GuiControl% 
    return
    
GuiClose:
    ExitApp
   

HF_Hotkey(HF_Control)  { ;***
    Global
    Loop, Parse, HF_Control, |
    {
        RegExMatch(A_LoopField, "S)(.*:)?\s*(.*)", HF_D)
        GuiControlGet, HF_D3, % HF_D1 "Hwnd", % HF_D2
        HF_D3 := Ceil(HF_D3), HF_Control_%HF_D3% := HF_D2
    }
    If !HF_IsStart 
    {
        SetBatchLines -1
        #InstallKeybdHook
        #InstallMouseHook
        #HotkeyInterval 200
        #MaxHotkeysPerInterval 200
        HF_MButtons := {"vkA4":"Alt","vkA5":"Alt","vkA2":"Ctrl","vkA3":"Ctrl","vkA0":"Shift","vkA1":"Shift","vk5B":"Win","vk5C":"Win"}
        HF_P := {"Alt":"!","Ctrl":"^","Shift":"+","Win":"#"}
        HF_Buttons := "|vkBA|vkBB|vkBC|vkBD|vkBE|vkBF|vkC0|vkDB|vkDC|vkDD|vkDE|vk41|vk42|vk43|vk44|vk45|vk46|vk47|vk48"
                    . "|vk49|vk4A|vk4B|vk4C|vk4D|vk4E|vk4F|vk50|vk51|vk52|vk53|vk54|vk55|vk56|vk57|vk58|vk59|vk5A|"     ; 37 Letter Buttons 
        HF_PressName := "WheelRight|WheelLeft|MButton|WheelDown|WheelUp|XButton1|XButton2" 
        #IF HF_State
        #IF
        Hotkey, IF, HF_State 
        Loop, Parse, HF_PressName, |
            Hotkey, %A_LoopField%, HF_PressName, P3 UseErrorLevel
        Loop, 128
            Hotkey % ((A_Index-1)//32)+1 "Joy" Mod(A_Index-1,32)+1, HF_PressName, P3 UseErrorLevel
        Hotkey, IF  
        OnExit, HF_Exit 
        OnMessage(0x111, "HF_WaitControl")
        HF_IsStart := 1
    }
    Return 
    
    HF_PressName: 
        HF_KeyName := HF_Hotkey := A_ThisHotkey , HF_DelStr := ""
        HF_Prefix := HF_PCtrl HF_PAlt HF_PShift HF_PWin
        %HF_ControlVarName% := HF_Prefix HF_Hotkey
        HF_WriteText := HF_MCtrl HF_MAlt HF_MShift HF_MWin HF_KeyName = ""
        ? "Нет" : HF_MCtrl HF_MAlt HF_MShift HF_MWin HF_KeyName
        SendMessage, 0xC, 0, &HF_WriteText, , ahk_id %HF_ControlHandle%
        Return 
        
    HF_Exit:
        DllCall("UnhookWindowsHookEx", Ptr, HF_State)
        Send {LButton Up}{LCtrl Up}{RCtrl Up}{LShift Up}{RShift Up}{LAlt Up}{RAlt Up}{LWin Up}{RWin Up}
        ExitApp
} ;**

HF_WaitControl( HF_Param, HF_Handle) { ;***
    Global 
    If HF_Control_%HF_Handle% <>
    {
        If (HF_Param >> 16 = 0x100)    ;    EN_SETFOCUS
        {
            HF_ControlVarName := HF_Control_%HF_Handle%
            HF_ControlHandle := HF_Handle
            HF_State := DllCall("SetWindowsHookEx" . (A_IsUnicode ? "W" : "A")
                                , Int, 13    ;    13 - WH_KEYBOARD_LL
                                , Ptr, RegisterCallback("HF_Write", "Fast")
                                , Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
                                , UInt, 0, Ptr)
            HF_DelStr := ""
            PostMessage,0x00B1,,,, ahk_id %HF_ControlHandle%    ;    EM_SETSEL := 0x00B1
            Send, {LButton Up}
            Return
        }
        If (HF_Param >> 16 = 0x200)    ;    EN_KILLFOCUS
        {
            DllCall("UnhookWindowsHookEx" , Ptr, HF_State)
            HF_MCtrl := HF_MAlt := HF_MShift := HF_MWin := HF_Prefix := HF_State := ""
            HF_PCtrl := HF_PAlt := HF_PShift := HF_PWin := ""
            If (HF_DelStr = 1)
                SendMessage, 0xC, 0, "Нет", , ahk_id %HF_ControlHandle%
            Send {LShift Up}{RShift Up}
            Return
        }
    }
    If (HF_Param >> 16 = 0x200)    ;    EN_KILLFOCUS
    { 
        DllCall("UnhookWindowsHookEx", Ptr, HF_State)
        HF_MCtrl := HF_MAlt := HF_MShift := HF_MWin := HF_Prefix := HF_State := ""
        HF_PCtrl := HF_PAlt := HF_PShift := HF_PWin := ""
        Send {LShift Up}{RShift Up}
    }
    Return
} ;**

HF_Write(HF_nCode, HF_wParam, HF_lParam)  { ;***
    Global 
    SetFormat, IntegerFast, H
    HF_VkCode := "vk" SubStr( NumGet(HF_lParam+0, 0, "UInt"), 3)  
        HF_D := NumGet(HF_lParam+0, 8, "UInt") & 1
        HF_D := HF_D << 8 | NumGet(HF_lParam+0, 4, "UInt") 
    HF_SCCode := "sc" SubStr(HF_D, 3)
    IF (HF_wParam = 0x100 || HF_wParam = 0x104)    ;    WM_KEYDOWN := 0x100, WM_SYSKEYDOWN := 0x104
    {
        IF HF_IsMod := HF_MButtons[HF_VkCode]
            GoTo, HF_PressMod
        GoTo, HF_Write
    }
    IF HF_IsMod := HF_MButtons[HF_VkCode]
        GoTo, HF_PressMod_Up
    Return 1

    HF_PressMod_Up:
        HF_M%HF_IsMod% := HF_P%HF_IsMod% := ""
        If ( HF_Hotkey != "" )
            Return 1
        GoTo, HF_Write

    HF_PressMod:
        If ( HF_M%HF_IsMod% != "" )
            Return 1
        HF_M%HF_IsMod% := HF_IsMod "+" , HF_P%HF_IsMod% := HF_P[HF_IsMod]

    HF_Write:
        ( HF_IsMod != "" ) ? ( HF_KeyName := HF_Hotkey := HF_Prefix := "" , HF_DelStr := 1 )
        : ( HF_KeyName := GetKeyName(HF_VkCode HF_SCCode) , HF_DelStr := ""
        , HF_Hotkey := InStr(HF_Buttons, "|" HF_VkCode "|") ? HF_VkCode : HF_KeyName
        , HF_Prefix := HF_PCtrl HF_PAlt HF_PShift HF_PWin )
        %HF_ControlVarName% := HF_Prefix HF_Hotkey
        HF_WriteText := HF_MCtrl HF_MAlt HF_MShift HF_MWin HF_KeyName = "" ? "Нет" 
        : HF_MCtrl HF_MAlt HF_MShift HF_MWin HF_KeyName
        SendMessage, 0xC, 0, &HF_WriteText, , ahk_id %HF_ControlHandle%
        Return 1
} ;**

    ; -------------------------------------- Read --------------------------------------

HF_Read(Key, Section, Path) { ;***
    Global HF_DelStr := ""
    IniRead, Key, % Path, % Section, % Key, % A_Space
    If Key =
        Return "Нет" 
    Return    HF_ReadVar(Key)
} ;**

HF_ReadVar(Key) { ;***
    RegExMatch(Key, "S)^([\^\+!#]*)\{?(.*?)}?$", K)
    Return    (InStr(K1,"^")?"Ctrl+":"")(InStr(K1,"!")?"Alt+":"")
            . (InStr(K1,"+")?"Shift+":"")(InStr(K1,"#")?"Win+":"")
            . (InStr(K2,"vk") ? GetKeyName(K2) : K2)
} ;**

HF_ReadToSend(Key, Section = "", Path = "") { ;***
    If (Section <> "")
        IniRead, Key, % Path, % Section, % Key, % A_Space
    Return RegExReplace( Key, "S)[^\^!\+#].*", "{$0}")
} ;** 
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

28

Re: AHK: Замена стандартного элемента управления "Hotkey"

Со СТРАШНЫМИ глюками.
Если нажать модификатор и отпустить, не нажимая завершающий символ, затем кликнуть мышью по нижележащему окну, твоё остаётся на поверхности, и активируется снова. Вторым кликом утопить его удаётся. Если же кликнуть мышью вне его, удерживая модификаторы, окно вообще невозможно деактивировать. К тому же, в нём остается один из модификаторов с плюсом. После выхода из программы остаются залипшими ранее нажатые модификаторы.

А у тебя же тоже Win7 64, у тебя лучше работает?

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

29

Re: AHK: Замена стандартного элемента управления "Hotkey"

Мой вариант с исправленными недостатками:

Gui, Add, Edit, hwndhEdit1 gHotkey w150 h20 Center
Gui, Add, Edit, hwndhEdit2 gHotkey w150 h20 Center
Gui, Add, Edit, vShowHotkey w150 h20 Center
Gui, Show

global InfoArray := {}   ; будем использовать глобальный массив для передачи информации
HotkeyInit(hEdit1, hEdit2)   ; передаём в функцию хендлы нужных контролов через запятую
return

Hotkey:
   if (InfoArray.HK = "")
      return
   
   GuiControl, %A_Gui%:, ShowHotkey, % InfoArray.HK
   InfoArray.HK := ""
;  Hotkey, % HotkeyString, HKLabel, On   ; раскомментировать для установки хоткея
   return
   
HKLabel:
   MsgBox, Вы нажали горячую клавишу %A_ThisHotkey%
   return

GuiClose:
   ExitApp

HotkeyInit(handles*)
{
   InfoArray := {handles: handles}
   
   hGui := DllCall("GetParent", Ptr, handles.1, Ptr)
   ControlGetFocus, FocusedClassNN, ahk_id %hGui%
   GuiControlGet, FocusedHwnd, %hGui%:Hwnd, % FocusedClassNN
   
   for k,v in handles
   {
      ControlSetText,, Нет, % "ahk_id" v
      if (FocusedHwnd = v)
         InfoArray.hHook := SetWindowsHookEx()
            , InfoArray.hControl := v
   }
   
   SetWinEventHook(0x8005, 0x8005, 0, RegisterCallback("HookProc", "F"),0,0,0)   ; EVENT_OBJECT_FOCUS := 0x8005
}

SetWindowsHookEx()
{
   Return DllCall("SetWindowsHookEx" . (A_IsUnicode ? "W" : "A")
      , Int, WH_KEYBOARD_LL := 13
      , Ptr, RegisterCallback("LowLevelKeyboardProc", "Fast")
      , Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
      , UInt, 0, Ptr)
}

LowLevelKeyboardProc(nCode, wParam, lParam)
{
   static WM_KEYDOWN := 0x100, WM_KEYUP := 0x101, WM_SYSKEYDOWN := 0x104, WM_SYSKEYUP := 0x105
      , prevMessage, prevKey, EndKey
   
   SetBatchLines, -1
   SetFormat, IntegerFast, H
   Message := wParam, Extended := NumGet(lParam+0, 8, "UInt") & 1
   sc := Extended << 8 | NumGet(lParam+0, 4, "UInt")
   vk := NumGet(lParam+0, 0, "UInt")
   key := GetKeyName("vk" SubStr(vk, 3) "sc" SubStr(sc, 3))

   if (Message = prevMessage && key = prevKey)
      Return nCode < 0 ? DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam) : 1
   
   prevMessage := Message, prevKey := key
   
   if key in LControl,RControl
      key := SubStr(key, 1, 1) . "Ctrl"
   if (sc = 0x145)
      key := "NumLock"
   
   if (Message = WM_KEYDOWN || Message = WM_SYSKEYDOWN)
   {
      if key in LCtrl,RCtrl,LAlt,RAlt,LShift,RShift,LWin,RWin
      {
         if EndKey
            InfoArray.keys := EndKey := ""
         
         if !InStr(InfoArray.keys, key)
            InfoArray.keys := key . " + " . InfoArray.keys
      }
      else
      {
         if (SubStr(InfoArray.keys, -1) = "+ " || InfoArray.keys = "")
            InfoArray.keys .= key
         else
            InfoArray.keys := RegExReplace(InfoArray.keys, "(.*?)\S+$", "$1" key)
         
         InfoArray.EndKey := "vk" . SubStr(vk, 3)  . "sc" . SubStr(sc, 3)
      }
   }
   
   if (Message = WM_KEYUP || Message = WM_SYSKEYUP)
   {
      if key in LCtrl,RCtrl,LAlt,RAlt,LShift,RShift,LWin,RWin
         InfoArray.keys := RegExReplace(InfoArray.keys, key . " \+ ")
      else if (InfoArray.keys != "")
         EndKey := 1
         
      if !EndKey
         SetTimer, SetText, -10
      
      Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam)
   }

   SetTimer, SetText, -10
   Return nCode < 0 ? DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam) : 1
   
SetText:
   keys := InfoArray.keys
   if (keys != "" && keys != "Нет" && Substr(keys, -1) != "+ ")
   {
      String := RegExReplace(keys, "\s")
      Loop, parse, String, +
      {
         IsSym := ""
         for k,v in {Ctrl: "^", Alt: "!", Shift: "+", Win: "#"}
            if InStr(A_LoopField, k) && A_LoopField != "CtrlBreak"
               HKString .= (SubStr(A_LoopField, 1, 1) = "L" ? "<" : ">") . v, IsSym := 1
         
         if !IsSym
         {
            if StrLen(A_LoopField) > 1
            {
               if InStr(A_LoopField, "Num")
                  HKString .= RegExReplace(InfoArray.EndKey, ".*(s.*)", "$1")
               else
                  HKString .= A_LoopField
            }
            else
               HKString .= RegExReplace(InfoArray.EndKey, "(.*)s.*", "$1")
         }
      }
      InfoArray.HK := HKString
   }
   ControlSetText,, % keys = "" ? "Нет" : keys, % "ahk_id" InfoArray.hControl
   return
}

SetWinEventHook(eventMin, eventMax, hmodWinEventProc, lpfnWinEventProc, idProcess, idThread, dwFlags)
{
   return DllCall("SetWinEventHook" , UInt, eventMin
                                    , UInt, eventMax
                                    , Ptr, hmodWinEventProc
                                    , Ptr, lpfnWinEventProc
                                    , UInt, idProcess
                                    , UInt, idThread
                                    , UInt, dwFlags, Ptr)
}

HookProc(hWinEventHook, event, hwnd)
{
   for k,v in InfoArray.handles
      if (hwnd = v)
         IsValue := 1, InfoArray.hControl := v
   
   if (IsValue && !InfoArray.hHook)
      InfoArray.hHook := SetWindowsHookEx()
   else if (!IsValue && InfoArray.hHook)
   {
      DllCall("UnhookWindowsHookEx", Ptr, InfoArray.hHook)
      InfoArray.keys := InfoArray.hHook := ""
      
      for k,v in InfoArray.handles
      {
         ControlGetText, Text,, ahk_id %v%
         if SubStr(Text, -1) = "+ "
            ControlSetText,, Нет, ahk_id %v%
      }
   }
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

30

Re: AHK: Замена стандартного элемента управления "Hotkey"

Со СТРАШНЫМИ глюками.

Ага и у меня также. Более того после работы такого чуда перестают работать все хоткеи АНК Ничего не пойму. Подскажи, что за...

Мой вариант с исправленными недостатками:

Теперь хорошо. Что то такое ещё есть... но чуть чуть.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

31

Re: AHK: Замена стандартного элемента управления "Hotkey"

serzh82saratov пишет:

Более того после работы такого чуда перестают работать все хоткеи АНК

teadrinker пишет:

После выхода из программы остаются залипшими ранее нажатые модификаторы.

serzh82saratov пишет:

Что то такое ещё есть... но чуть чуть.

А отсюда поподробнее можно? Мы же не картину обсуждаем!

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

32 (изменено: serzh82saratov, 2013-08-15 23:23:53)

Re: AHK: Замена стандартного элемента управления "Hotkey"

А отсюда поподробнее можно? Мы же не картину обсуждаем!

Если бы я мог заменять субъективное - объективным... Что то не совсем так, а может я и ошибаюсь. Тут практика нужна, а на неё не всегда есть время. Как бы того не хотелось

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

33

Re: AHK: Замена стандартного элемента управления "Hotkey"

А что конкретно побудило сказать тебя, что что-то не так?

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

34

Re: AHK: Замена стандартного элемента управления "Hotkey"

После выхода из программы остаются залипшими ранее нажатые модификаторы.

Не наводит на мысли. Увы

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

35

Re: AHK: Замена стандартного элемента управления "Hotkey"

Ну, если какой-то модификатор остаётся в неотжатом состоянии, горячая клавиша, не рассчитанная на применение с этим модификатором, работать не будет.

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

36

Re: AHK: Замена стандартного элемента управления "Hotkey"

Почему в моём коде, после клика, мимо окна (деактивация) снова происходит активация окна скрипта (кстати такого не было точно, на версиях до AutoHotkey v1.1.11.00). Я всю голову сломал. Пусть весь мой код случайный набор символов. Но почему??

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

37

Re: AHK: Замена стандартного элемента управления "Hotkey"

Может, сообщение SendMessage, 0xC активирует окно? Закомментируй его и проверь.

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

38

Re: AHK: Замена стандартного элемента управления "Hotkey"

Вот ведь (какая-то согласная и...) ...
А ведь отказался при тестах кода от всех остальных вариантов GuiControl, ControlSetText и.т.п.
Спасибо!

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

39 (изменено: serzh82saratov, 2013-08-19 01:52:09)

Re: AHK: Замена стандартного элемента управления "Hotkey"

teadrinker пишет:

Со СТРАШНЫМИ глюками.

teadrinker пишет:

Может, сообщение SendMessage, 0xC активирует окно?

http://xbmc.ru/forum/images/smilies/facepalm.gif http://xbmc.ru/forum/images/smilies/facepalm.gif http://xbmc.ru/forum/images/smilies/facepalm.gif У меня в наглядном примере в метке поля ввода команда Gui Show меняла заголовок, когда SendMessage меняла поле ввода, запускалась метка поля ввода и Gui Show активировала окно. Пипец нубская ошибка. Пойду напьюсь
---------------
Проверь пожалуйста такой вариант:

+ открыть спойлер

#SingleInstance Force
Gui, +AlwaysOnTop +HWNDhGui
Gui, Add, Edit, Center ReadOnly w300 gShow vMyHotkey1 
Gui, Add, Edit, Center ReadOnly w300 gShow vMyHotkey2
HF_Hotkey( "MyHotkey1|MyHotkey2")
Gui, Show
return

Show:  
    Str := A_GuiControl " = " %A_GuiControl% 
    SendMessage, 0xC, 0, &Str, , ahk_id %hGui% 
    return
    
GuiClose:
    ExitApp
  

HF_Hotkey(HF_Control)  { ;***
    Global
    Loop, Parse, HF_Control, |
    {
        RegExMatch(A_LoopField, "S)(.*:)?\s*(.*)", HF_D)
        GuiControlGet, HF_D3, % HF_D1 "Hwnd", % HF_D2
        HF_D3 := Ceil(HF_D3), HF_Control_%HF_D3% := HF_D2
    }
    If !HF_IsStart 
    {
        SetBatchLines -1 
        #HotkeyInterval 200
        #MaxHotkeysPerInterval 200
        HF_MButtons := {"vkA4":"Alt","vkA5":"Alt","vkA2":"Ctrl","vkA3":"Ctrl","vkA0":"Shift","vkA1":"Shift","vk5B":"Win","vk5C":"Win"}
        HF_P := {"Alt":"!","Ctrl":"^","Shift":"+","Win":"#"}
        HF_Buttons := "|vkBA|vkBB|vkBC|vkBD|vkBE|vkBF|vkC0|vkDB|vkDC|vkDD|vkDE|vk41|vk42|vk43|vk44|vk45|vk46|vk47|vk48"
                    . "|vk49|vk4A|vk4B|vk4C|vk4D|vk4E|vk4F|vk50|vk51|vk52|vk53|vk54|vk55|vk56|vk57|vk58|vk59|vk5A|"     ; 37 Letter Buttons 
        HF_PressName := "WheelRight|WheelLeft|MButton|WheelDown|WheelUp|XButton1|XButton2" 
        #IF HF_State
        #IF
        Hotkey, IF, HF_State 
        Loop, Parse, HF_PressName, |
            Hotkey, %A_LoopField%, HF_PressName, P3 UseErrorLevel
        Loop, 128
            Hotkey % ((A_Index-1)//32)+1 "Joy" Mod(A_Index-1,32)+1, HF_PressName, P3 UseErrorLevel
        Hotkey, IF   
        OnMessage(0x111, "HF_WaitControl")
        HF_IsStart := 1
    }
    Return 
    
    HF_PressName: 
        HF_KeyName := HF_Hotkey := A_ThisHotkey , HF_DelStr := ""
        HF_Prefix := HF_PCtrl HF_PAlt HF_PShift HF_PWin
        %HF_ControlVarName% := HF_Prefix HF_Hotkey
        HF_WriteText := HF_MCtrl HF_MAlt HF_MShift HF_MWin HF_KeyName = ""
        ? "Нет" : HF_MCtrl HF_MAlt HF_MShift HF_MWin HF_KeyName
        SendMessage, 0xC, 0, &HF_WriteText, , ahk_id %HF_ControlHandle%
        Return  
} ;**

HF_WaitControl( HF_Param, HF_Handle) { ;***
    Global 
    If HF_Control_%HF_Handle% <>
    {
        If (HF_Param >> 16 = 0x100)    ;    EN_SETFOCUS
        {
            HF_ControlVarName := HF_Control_%HF_Handle%
            HF_ControlHandle := HF_Handle
            HF_State := DllCall("SetWindowsHookEx" . (A_IsUnicode ? "W" : "A")
                                , Int, 13    ;    13 - WH_KEYBOARD_LL
                                , Ptr, RegisterCallback("HF_Write", "Fast")
                                , Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
                                , UInt, 0, Ptr)
            HF_DelStr := ""
            PostMessage,0x00B1,,,, ahk_id %HF_ControlHandle%    ;    EM_SETSEL := 0x00B1
            Send, {LButton Up}
            Return
        }
        If (HF_Param >> 16 = 0x200)    ;    EN_KILLFOCUS
        {
            DllCall("UnhookWindowsHookEx" , Ptr, HF_State)
            HF_MCtrl := HF_MAlt := HF_MShift := HF_MWin := HF_Prefix := HF_State := ""
            HF_PCtrl := HF_PAlt := HF_PShift := HF_PWin := ""
            If (HF_DelStr = 1)
                SendMessage, 0xC, 0, "Нет", , ahk_id %HF_ControlHandle%
            Send {LShift Up}{RShift Up}
            Return
        }
    }
    If (HF_Param >> 16 = 0x200)    ;    EN_KILLFOCUS
    { 
        DllCall("UnhookWindowsHookEx", Ptr, HF_State)
        HF_MCtrl := HF_MAlt := HF_MShift := HF_MWin := HF_Prefix := HF_State := ""
        HF_PCtrl := HF_PAlt := HF_PShift := HF_PWin := ""
        Send {LShift Up}{RShift Up}
    }
    Return
} ;**

HF_Write(HF_nCode, HF_wParam, HF_lParam)  { ;***
    Global
    Critical
    SetFormat, IntegerFast, H
    HF_VkCode := "vk" SubStr( NumGet(HF_lParam+0, 0, "UInt"), 3)   
        HF_D := NumGet(HF_lParam+0, 8, "UInt") & 1
        HF_D := HF_D << 8 | NumGet(HF_lParam+0, 4, "UInt") 
    HF_SCCode := "sc" SubStr(HF_D, 3)  
    IF (HF_wParam = 0x100 || HF_wParam = 0x104)    ;    WM_KEYDOWN := 0x100, WM_SYSKEYDOWN := 0x104
    {
        IF HF_IsMod := HF_MButtons[HF_VkCode]
            GoTo, HF_PressMod
        GoTo, HF_Write
    }
    IF HF_IsMod := HF_MButtons[HF_VkCode]
        GoTo, HF_PressMod_Up
    Return 1

    HF_PressMod_Up:
        HF_M%HF_IsMod% := HF_P%HF_IsMod% := ""
        If ( HF_Hotkey != "" )
            Return 1
        GoTo, HF_Write

    HF_PressMod:
        If ( HF_M%HF_IsMod% != "" )
            Return 1
        HF_M%HF_IsMod% := HF_IsMod "+" , HF_P%HF_IsMod% := HF_P[HF_IsMod]

    HF_Write:
        ( HF_IsMod != "" ) ? ( HF_KeyName := HF_Hotkey := HF_Prefix := "" , HF_DelStr := 1 )
        : ( HF_KeyName := GetKeyName(HF_VkCode HF_SCCode) , HF_DelStr := ""
        , HF_Hotkey := InStr(HF_Buttons, "|" HF_VkCode "|") ? HF_VkCode : HF_KeyName
        , HF_Prefix := HF_PCtrl HF_PAlt HF_PShift HF_PWin )
        %HF_ControlVarName% := HF_Prefix HF_Hotkey
        HF_WriteText := HF_MCtrl HF_MAlt HF_MShift HF_MWin HF_KeyName = "" ? "Нет" 
        : HF_MCtrl HF_MAlt HF_MShift HF_MWin HF_KeyName
        SendMessage, 0xC, 0, &HF_WriteText, , ahk_id %HF_ControlHandle%
        Return 1
} ;**

    ; -------------------------------------- Read --------------------------------------

HF_Read(Key, Section, Path) { ;***
    Global HF_DelStr := ""
    IniRead, Key, % Path, % Section, % Key, % A_Space
    If Key =
        Return "Нет" 
    Return    HF_ReadVar(Key)
} ;**

HF_ReadVar(Key) { ;***
    RegExMatch(Key, "S)^([\^\+!#]*)\{?(.*?)}?$", K)
    Return    (InStr(K1,"^")?"Ctrl+":"")(InStr(K1,"!")?"Alt+":"")
            . (InStr(K1,"+")?"Shift+":"")(InStr(K1,"#")?"Win+":"")
            . (InStr(K2,"vk") ? GetKeyName(K2) : K2)
} ;**

HF_ReadToSend(Key, Section = "", Path = "") { ;***
    If (Section <> "")
        IniRead, Key, % Path, % Section, % Key, % A_Space
    Return RegExReplace( Key, "S)[^\^!\+#].*", "{$0}")
} ;** 

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

40

Re: AHK: Замена стандартного элемента управления "Hotkey"

Ладно, уже завтра, сегодня отдыхаю

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

41

Re: AHK: Замена стандартного элемента управления "Hotkey"

Сейчас работает вроде нормально. Один небольшой недостаток — активируем окно, нажимаем несколько модификаторов, удерживая деактивируем — появляется "нет" — активируем снова — в окне остаётся лишь последний из нажатых модификаторов. Тут должно быть либо чтобы оставалось " нет", либо чтобы присутствовали все ранее нажатые.

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

42

Re: AHK: Замена стандартного элемента управления "Hotkey"

появляется "нет" — активируем снова

остаётся лишь последний из нажатых модификаторов

Не видел такого. Имеется ввиду что например если последний из нажатых модификаторов альт, то после активации нажимаем кнопку, и пишется альт+кнопка?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

43

Re: AHK: Замена стандартного элемента управления "Hotkey"

Нет, именно то, что я написал. Нажимаем только модификаторы, например Ctrl + Alt, удерживаем, деактивируем, продолжая удерживать, снова активируем — в окне остаётся только Alt.

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

44

Re: AHK: Замена стандартного элемента управления "Hotkey"

Понял.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

45

Re: AHK: Замена стандартного элемента управления "Hotkey"

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

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

46

Re: AHK: Замена стандартного элемента управления "Hotkey"

На самом деле главный недостаток обоих вариантов в том, что инициировать "Hotkey" (не важно, один или несколько) можно только один раз, а настоящий контрол можно добавить/удалить в любой момент. На практике, конечно, вряд ли кому понадобится добавлять такой контрол больше раза, но всё же.

Удалось подправить свой вариант так, что он лишён вышеуказанных недостатков, а также не имеет ни одной глобальной переменной.

Gui, Add, Edit, hwndhEdit1 gHotkey w150 h20 Center
fn := HotkeyInit(hEdit1)   ; fn — ссылка на функцию, которая будет получать строку с горячей клавишей

Gui, Add, Edit, vShowHotkey w150 h20 Center
Gui, Show
return

Hotkey:
   GuiControl, %A_Gui%:, ShowHotkey, % HotkeyString := fn.()
;  Hotkey, % HotkeyString, HKLabel, On UseErrorLevel ; раскомментировать для установки хоткея
   return

HKLabel:
   MsgBox, Вы нажали горячую клавишу %A_ThisHotkey%
   return

GuiClose:
   ExitApp

HotkeyInit(handle)
{
   if !IsObject(Create.array.handles)
      SetWinEventHook(0x8005, 0x8005, 0, RegisterCallback("HookProc", "F"),0,0,0)   ; EVENT_OBJECT_FOCUS := 0x8005
         , Create.array.handles := []
   
   Create.array.handles.Insert(handle)
   ControlSetText,, Нет, % "ahk_id" handle
   
   return Func("GetHkString")
}

Class Create
{
   static array := {}
}

GetHkString()
{
   HotkeyString := Create.array.HK
   Create.array.HK := ""
   return HotkeyString
}

SetWinEventHook(eventMin, eventMax, hmodWinEventProc, lpfnWinEventProc, idProcess, idThread, dwFlags)
{
   return DllCall("SetWinEventHook" , UInt, eventMin
                                    , UInt, eventMax
                                    , Ptr, hmodWinEventProc
                                    , Ptr, lpfnWinEventProc
                                    , UInt, idProcess
                                    , UInt, idThread
                                    , UInt, dwFlags, Ptr)
}

HookProc(hWinEventHook, event, hwnd)
{
   for k,v in Create.array.handles
      if (hwnd = v)
         IsValue := 1, Create.array.hControl := v
   
   if (IsValue && !Create.array.hHook)
      Create.array.hHook := SetWindowsHookEx()
   else if (!IsValue && Create.array.hHook)
   {
      DllCall("UnhookWindowsHookEx", Ptr, Create.array.hHook)
      Create.array.keys := Create.array.hHook := ""
   }
   
   for k,v in Create.array.handles
   {
      ControlGetText, Text,, ahk_id %v%
      if SubStr(Text, -1) = "+ "
         ControlSetText,, Нет, ahk_id %v%
   }
}

SetWindowsHookEx()
{
   Return DllCall("SetWindowsHookEx" . (A_IsUnicode ? "W" : "A")
      , Int, WH_KEYBOARD_LL := 13
      , Ptr, RegisterCallback("LowLevelKeyboardProc", "Fast")
      , Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
      , UInt, 0, Ptr)
}

LowLevelKeyboardProc(nCode, wParam, lParam)
{
   static WM_KEYDOWN := 0x100, WM_KEYUP := 0x101, WM_SYSKEYDOWN := 0x104, WM_SYSKEYUP := 0x105
      , EndKey, prevMessage, prevKey
   
   SetBatchLines, -1
   SetFormat, IntegerFast, H
   Message := wParam, Extended := NumGet(lParam+0, 8, "UInt") & 1
   sc := Extended << 8 | NumGet(lParam+0, 4, "UInt")
   vk := NumGet(lParam+0, 0, "UInt")
   key := GetKeyName("vk" SubStr(vk, 3) "sc" SubStr(sc, 3))
   
   if (Message = prevMessage && key = prevKey)
      Return nCode < 0 ? DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam) : 1
   prevMessage := Message, prevKey := key
   
   if key in LControl,RControl
      key := SubStr(key, 1, 1) . "Ctrl"
   if (sc = 0x145)
      key := "NumLock"
   
   if (Message = WM_KEYDOWN || Message = WM_SYSKEYDOWN)
   {
      if key in LCtrl,RCtrl,LAlt,RAlt,LShift,RShift,LWin,RWin
      {
         EndKey ? Create.array.keys := EndKey := ""
         
         if !InStr(Create.array.keys, key)
            Create.array.keys .= key . " + "
      }
      else
      {
         if (SubStr(Create.array.keys, -1) = "+ " || Create.array.keys = "")
            Create.array.keys .= key
         else
            Create.array.keys := RegExReplace(Create.array.keys, "(.*?)\S+$", "$1" key)
         
         Create.array.LastKey := "vk" . SubStr(vk, 3)  . "sc" . SubStr(sc, 3)
      }
   }
   
   if (Message = WM_KEYUP || Message = WM_SYSKEYUP)
   {
      if key in LCtrl,RCtrl,LAlt,RAlt,LShift,RShift,LWin,RWin
         Create.array.keys := RegExReplace(Create.array.keys, key . " \+ ")
      else if (Create.array.keys != "")
         EndKey := 1
         
      if !EndKey
         SetTimer, SetText, -10
      
      Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam)
   }

   SetTimer, SetText, -10
   Return nCode < 0 ? DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam) : 1
   
SetText:
   keys := Create.array.keys, LastKey := Create.array.LastKey
   if (keys != "" && keys != "Нет" && Substr(keys, -1) != "+ ")
   {
      Loop, parse, keys, +, % " "
      {
         IsSym := ""
         for k,v in {Ctrl: "^", Alt: "!", Shift: "+", Win: "#"}
            if InStr(A_LoopField, k) && A_LoopField != "CtrlBreak"
               HKString .= (SubStr(A_LoopField, 1, 1) = "L" ? "<" : ">") . v, IsSym := 1
         
         if !IsSym
         {
            if StrLen(A_LoopField) > 1
               HKString .= InStr(A_LoopField, "Num") ? RegExReplace(LastKey, ".*(s.*)", "$1") : A_LoopField
            else
               HKString .= RegExReplace(LastKey, "(.*)s.*", "$1")
         }
      }
      Create.array.HK := HKString
   }
   ControlSetText,, % keys = "" ? "Нет" : keys, % "ahk_id" Create.array.hControl
   return
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

47

Re: AHK: Замена стандартного элемента управления "Hotkey"

teadrinker, все определяет, только с мультимедиа-клавишами странно себя ведет:
Например, связка модификатор+Volume_Mute остается, только если бысто отпустить клавиши, иначе сбрасывается.
С остальными клавишами порядок.

48

Re: AHK: Замена стандартного элемента управления "Hotkey"

К сожалению, не могу это проверить, у меня клавиатура ещё старая, без медийных клавиш. По идее нужно посмотреть, какие значения vk, sc, key они выдают в функции LowLevelKeyboardProc().

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

49 (изменено: Irbis, 2013-08-20 22:56:44)

Re: AHK: Замена стандартного элемента управления "Hotkey"

sc = 0x100
vk = 0xAD
key = Volume_Mute

sc для всех MM-клавиш одинаковое, vk с 0xA6 (Browser_Back)

50

Re: AHK: Замена стандартного элемента управления "Hotkey"

teadrinker пишет:

Удалось подправить свой вариант так, что он лишён вышеуказанных недостатков, а также не имеет ни одной глобальной переменной.

Такое надо курить
Класс!

Irbis пишет:

все определяет, только с мультимедиа-клавишами странно себя ведет:

При отпускании, клавиша сбрасывается. Нажал Shift+Volume_Up. Volume_Up отпустил остаётся

Shift+

Shift отпустил

Нет

То есть мультимедиа-клавишы не "фиксируются".

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

51

Re: AHK: Замена стандартного элемента управления "Hotkey"

Проблема точно не в коде. Попробовал принудительно подставлять эти значения, добавив в LowLevelKeyboardProc()

   if key not in LCtrl,RCtrl,LAlt,RAlt,LShift,RShift,LWin,RWin
      sc := 0x100,  vk := 0xad,  key := "Volume_Mute"

то всё работает нормально. То есть, какая-то "аппаратная" проблема. Кстати, не единственная. Например, если перевести NumLock в положение On и нажать Shift+клавиша на цифровой клавиатуре, то тоже сбрасывается. Так же себя ведёт и обычный контрол Hotkey. У меня так, по-крайней мере.

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

52

Re: AHK: Замена стандартного элемента управления "Hotkey"

Возможно, проблема в том, что такие клавиши в сочетании с модификаторами не посылают при отпускании WM_KEYUP (или WM_SYSKEYUP). Это можно проверить, добавив в секцию

if (Message = WM_KEYUP || Message = WM_SYSKEYUP)

SoundBeep.

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

53

Re: AHK: Замена стандартного элемента управления "Hotkey"

С ММ клавишами проблем нет в моём варианте. Единственно в сочетаниях с Win некоторые не определяются, как будто их не нажимаешь.

Например, если перевести NumLock в положение On и нажать Shift+клавиша на цифровой клавиатуре, то тоже сбрасывается

Да а такое действительно в любых вариантах кодов.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

54

Re: AHK: Замена стандартного элемента управления "Hotkey"

В общем, дело тёмное

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

55

Re: AHK: Замена стандартного элемента управления "Hotkey"

Ага. А ты говоришь - ТЗ

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

56

Re: AHK: Замена стандартного элемента управления "Hotkey"

Если моё предположение верное, вот так должно работать с медийными клавишами, проверьте:

Gui, Add, Edit, hwndhEdit1 gHotkey w150 h20 Center
fn := HotkeyInit(hEdit1)   ; fn — ссылка на функцию, которая будет получать строку с горячей клавишей

Gui, Add, Edit, vShowHotkey w150 h20 Center
Gui, Show
return

Hotkey:
   GuiControl, %A_Gui%:, ShowHotkey, % HotkeyString := fn.()
;  Hotkey, % HotkeyString, HKLabel, On UseErrorLevel ; раскомментировать для установки хоткея
   return

HKLabel:
   MsgBox, Вы нажали горячую клавишу %A_ThisHotkey%
   return

GuiClose:
   ExitApp

HotkeyInit(handle)
{
   if !IsObject(Create.array.handles)
      SetWinEventHook(0x8005, 0x8005, 0, RegisterCallback("HookProc", "F"),0,0,0)   ; EVENT_OBJECT_FOCUS := 0x8005
         , Create.array.handles := []
   
   Create.array.handles.Insert(handle)
   ControlSetText,, Нет, % "ahk_id" handle
   
   return Func("GetHkString")
}

Class Create
{
   static array := {}
}

GetHkString()
{
   HotkeyString := Create.array.HK
   Create.array.HK := ""
   return HotkeyString
}

SetWinEventHook(eventMin, eventMax, hmodWinEventProc, lpfnWinEventProc, idProcess, idThread, dwFlags)
{
   return DllCall("SetWinEventHook" , UInt, eventMin
                                    , UInt, eventMax
                                    , Ptr, hmodWinEventProc
                                    , Ptr, lpfnWinEventProc
                                    , UInt, idProcess
                                    , UInt, idThread
                                    , UInt, dwFlags, Ptr)
}

HookProc(hWinEventHook, event, hwnd)
{
   for k,v in Create.array.handles
      if (hwnd = v)
         IsValue := 1, Create.array.hControl := v
   
   if (IsValue && !Create.array.hHook)
      Create.array.hHook := SetWindowsHookEx()
   else if (!IsValue && Create.array.hHook)
   {
      DllCall("UnhookWindowsHookEx", Ptr, Create.array.hHook)
      Create.array.keys := Create.array.hHook := ""
   }
   
   for k,v in Create.array.handles
   {
      ControlGetText, Text,, ahk_id %v%
      if SubStr(Text, -1) = "+ "
         ControlSetText,, Нет, ahk_id %v%
   }
}

SetWindowsHookEx()
{
   Return DllCall("SetWindowsHookEx" . (A_IsUnicode ? "W" : "A")
      , Int, WH_KEYBOARD_LL := 13
      , Ptr, RegisterCallback("LowLevelKeyboardProc", "Fast")
      , Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
      , UInt, 0, Ptr)
}

LowLevelKeyboardProc(nCode, wParam, lParam)
{
   static WM_KEYDOWN := 0x100, WM_KEYUP := 0x101, WM_SYSKEYDOWN := 0x104, WM_SYSKEYUP := 0x105
      , EndKey, prevMessage, prevKey
   
   SetBatchLines, -1
   SetFormat, IntegerFast, H
   Message := wParam, Extended := NumGet(lParam+0, 8, "UInt") & 1
   sc := Extended << 8 | NumGet(lParam+0, 4, "UInt")
   vk := NumGet(lParam+0, 0, "UInt")
   key := GetKeyName("vk" SubStr(vk, 3) "sc" SubStr(sc, 3))
   
   if (Message = prevMessage && key = prevKey)
      Return nCode < 0 ? DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam) : 1
   prevMessage := Message, prevKey := key
   
   if key in LControl,RControl
      key := SubStr(key, 1, 1) . "Ctrl"
   if (sc = 0x145)
      key := "NumLock"
   
   if (Message = WM_KEYDOWN || Message = WM_SYSKEYDOWN)
   {
      if key in LCtrl,RCtrl,LAlt,RAlt,LShift,RShift,LWin,RWin
      {
         EndKey ? Create.array.keys := EndKey := ""
         
         if !InStr(Create.array.keys, key)
            Create.array.keys .= key . " + "
      }
      else
      {
         EndKey := 1
         if (SubStr(Create.array.keys, -1) = "+ " || Create.array.keys = "")
            Create.array.keys .= key
         else
            Create.array.keys := RegExReplace(Create.array.keys, "(.*?)\S+$", "$1" key)
         
         Create.array.LastKey := "vk" . SubStr(vk, 3)  . "sc" . SubStr(sc, 3)
      }
   }
   
   if (Message = WM_KEYUP || Message = WM_SYSKEYUP)
   {
      if key in LCtrl,RCtrl,LAlt,RAlt,LShift,RShift,LWin,RWin
         Create.array.keys := RegExReplace(Create.array.keys, key . " \+ ")
         
      if !EndKey
         SetTimer, SetText, -10
      
      Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam)
   }

   SetTimer, SetText, -10
   Return nCode < 0 ? DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam) : 1
   
SetText:
   keys := Create.array.keys, LastKey := Create.array.LastKey
   if (keys != "" && keys != "Нет" && Substr(keys, -1) != "+ ")
   {
      Loop, parse, keys, +, % " "
      {
         IsSym := ""
         for k,v in {Ctrl: "^", Alt: "!", Shift: "+", Win: "#"}
            if InStr(A_LoopField, k) && A_LoopField != "CtrlBreak"
               HKString .= (SubStr(A_LoopField, 1, 1) = "L" ? "<" : ">") . v, IsSym := 1
         
         if !IsSym
         {
            if StrLen(A_LoopField) > 1
               HKString .= InStr(A_LoopField, "Num") ? RegExReplace(LastKey, ".*(s.*)", "$1") : A_LoopField
            else
               HKString .= RegExReplace(LastKey, "(.*)s.*", "$1")
         }
      }
      Create.array.HK := HKString
   }
   ControlSetText,, % keys = "" ? "Нет" : keys, % "ahk_id" Create.array.hControl
   return
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

57 (изменено: serzh82saratov, 2013-08-21 00:41:09)

Re: AHK: Замена стандартного элемента управления "Hotkey"

Нет. Теперь при нажатии ММ кнопка мелькает. То есть исчезает до того как её отпустишь.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

58

Re: AHK: Замена стандартного элемента управления "Hotkey"

Это с модификаторами, или без?

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

59

Re: AHK: Замена стандартного элемента управления "Hotkey"

Только с модификаторами.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

60

Re: AHK: Замена стандартного элемента управления "Hotkey"

А так?

Gui, Add, Edit, hwndhEdit1 gHotkey w150 h20 Center
fn := HotkeyInit(hEdit1)   ; fn — ссылка на функцию, которая будет получать строку с горячей клавишей

Gui, Add, Edit, vShowHotkey w150 h20 Center
Gui, Show
return

Hotkey:
   GuiControl, %A_Gui%:, ShowHotkey, % HotkeyString := fn.()
;  Hotkey, % HotkeyString, HKLabel, On UseErrorLevel ; раскомментировать для установки хоткея
   return

HKLabel:
   MsgBox, Вы нажали горячую клавишу %A_ThisHotkey%
   return

GuiClose:
   ExitApp

HotkeyInit(handle)
{
   if !IsObject(Create.array.handles)
      SetWinEventHook(0x8005, 0x8005, 0, RegisterCallback("HookProc", "F"),0,0,0)   ; EVENT_OBJECT_FOCUS := 0x8005
         , Create.array.handles := []
   
   Create.array.handles.Insert(handle)
   ControlSetText,, Нет, % "ahk_id" handle
   
   return Func("GetHkString")
}

Class Create
{
   static array := {}
}

GetHkString()
{
   HotkeyString := Create.array.HK
   Create.array.HK := ""
   return HotkeyString
}

SetWinEventHook(eventMin, eventMax, hmodWinEventProc, lpfnWinEventProc, idProcess, idThread, dwFlags)
{
   return DllCall("SetWinEventHook" , UInt, eventMin
                                    , UInt, eventMax
                                    , Ptr, hmodWinEventProc
                                    , Ptr, lpfnWinEventProc
                                    , UInt, idProcess
                                    , UInt, idThread
                                    , UInt, dwFlags, Ptr)
}

HookProc(hWinEventHook, event, hwnd)
{
   for k,v in Create.array.handles
      if (hwnd = v)
         IsValue := 1, Create.array.hControl := v
   
   if (IsValue && !Create.array.hHook)
      Create.array.hHook := SetWindowsHookEx()
   else if (!IsValue && Create.array.hHook)
   {
      DllCall("UnhookWindowsHookEx", Ptr, Create.array.hHook)
      Create.array.keys := Create.array.hHook := ""
   }
   
   for k,v in Create.array.handles
   {
      ControlGetText, Text,, ahk_id %v%
      if SubStr(Text, -1) = "+ "
         ControlSetText,, Нет, ahk_id %v%
   }
}

SetWindowsHookEx()
{
   Return DllCall("SetWindowsHookEx" . (A_IsUnicode ? "W" : "A")
      , Int, WH_KEYBOARD_LL := 13
      , Ptr, RegisterCallback("LowLevelKeyboardProc", "Fast")
      , Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
      , UInt, 0, Ptr)
}

LowLevelKeyboardProc(nCode, wParam, lParam)
{
   static WM_KEYDOWN := 0x100, WM_KEYUP := 0x101, WM_SYSKEYDOWN := 0x104, WM_SYSKEYUP := 0x105
      , EndKey, prevMessage, prevKey
   
   SetBatchLines, -1
   SetFormat, IntegerFast, H
   Message := wParam, Extended := NumGet(lParam+0, 8, "UInt") & 1
   sc := Extended << 8 | NumGet(lParam+0, 4, "UInt")
   vk := NumGet(lParam+0, 0, "UInt")
   key := GetKeyName("vk" SubStr(vk, 3) "sc" SubStr(sc, 3))
   
   if key in LControl,RControl
      key := SubStr(key, 1, 1) . "Ctrl"
   if (sc = 0x145)
      key := "NumLock"
   
   if (Message = WM_KEYDOWN || Message = WM_SYSKEYDOWN)
   {
      if key in LCtrl,RCtrl,LAlt,RAlt,LShift,RShift,LWin,RWin
      {
         EndKey ? Create.array.keys := EndKey := ""
         if !InStr(Create.array.keys, key)
            Create.array.keys .= key . " + "
      }
      else
      {
         EndKey := 1
         if (SubStr(Create.array.keys, -1) = "+ " || Create.array.keys = "")
            Create.array.keys .= key
         else
            Create.array.keys := RegExReplace(Create.array.keys, "(.*?)\S+$", "$1" key)
         
         Create.array.LastKey := "vk" . SubStr(vk, 3)  . "sc" . SubStr(sc, 3)
      }
   }
   
   if (Message = WM_KEYUP || Message = WM_SYSKEYUP)
   {
      if key in LCtrl,RCtrl,LAlt,RAlt,LShift,RShift,LWin,RWin
         Create.array.keys := RegExReplace(Create.array.keys, key . " \+ ")
      else
         EndKey := 1
         
      if !EndKey
         SetTimer, SetText, -10
      
      Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam)
   }

   SetTimer, SetText, -10
   Return nCode < 0 ? DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam) : 1
   
SetText:
   keys := Create.array.keys, LastKey := Create.array.LastKey
   if (keys != "" && keys != "Нет" && Substr(keys, -1) != "+ ")
   {
      Loop, parse, keys, +, % " "
      {
         IsSym := ""
         for k,v in {Ctrl: "^", Alt: "!", Shift: "+", Win: "#"}
            if InStr(A_LoopField, k) && A_LoopField != "CtrlBreak"
               HKString .= (SubStr(A_LoopField, 1, 1) = "L" ? "<" : ">") . v, IsSym := 1
         
         if !IsSym
         {
            if StrLen(A_LoopField) > 1
               HKString .= InStr(A_LoopField, "Num") ? RegExReplace(LastKey, ".*(s.*)", "$1") : A_LoopField
            else
               HKString .= RegExReplace(LastKey, "(.*)s.*", "$1")
         }
      }
      Create.array.HK := HKString
   }
   ControlSetText,, % keys = "" ? "Нет" : keys, % "ahk_id" Create.array.hControl
   return
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

61

Re: AHK: Замена стандартного элемента управления "Hotkey"

А так ещё хуже. Мелькает теперь очень быстро и через раз.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

62

Re: AHK: Замена стандартного элемента управления "Hotkey"

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

Gui, Add, Edit, hwndhEdit1 gHotkey w150 h20 Center
fn := HotkeyInit(hEdit1)   ; fn — ссылка на функцию, которая будет получать строку с горячей клавишей

Gui, Add, Edit, vShowHotkey w150 h20 Center
Gui, Show
return

Hotkey:
   GuiControl, %A_Gui%:, ShowHotkey, % HotkeyString := fn.()
;  Hotkey, % HotkeyString, HKLabel, On UseErrorLevel ; раскомментировать для установки хоткея
   return

HKLabel:
   MsgBox, Вы нажали горячую клавишу %A_ThisHotkey%
   return

GuiClose:
   ExitApp

HotkeyInit(handle)
{
   if !IsObject(Create.array.handles)
      SetWinEventHook(0x8005, 0x8005, 0, RegisterCallback("HookProc", "F"),0,0,0)   ; EVENT_OBJECT_FOCUS := 0x8005
         , Create.array.handles := []
   
   Create.array.handles.Insert(handle)
   ControlSetText,, Нет, % "ahk_id" handle
   
   return Func("GetHkString")
}

Class Create
{
   static array := {}
}

GetHkString()
{
   HotkeyString := Create.array.HK
   Create.array.HK := ""
   return HotkeyString
}

SetWinEventHook(eventMin, eventMax, hmodWinEventProc, lpfnWinEventProc, idProcess, idThread, dwFlags)
{
   return DllCall("SetWinEventHook" , UInt, eventMin
                                    , UInt, eventMax
                                    , Ptr, hmodWinEventProc
                                    , Ptr, lpfnWinEventProc
                                    , UInt, idProcess
                                    , UInt, idThread
                                    , UInt, dwFlags, Ptr)
}

HookProc(hWinEventHook, event, hwnd)
{
   for k,v in Create.array.handles
      if (hwnd = v)
         IsValue := 1, Create.array.hControl := v
   
   if (IsValue && !Create.array.hHook)
      Create.array.hHook := SetWindowsHookEx()
   else if (!IsValue && Create.array.hHook)
   {
      DllCall("UnhookWindowsHookEx", Ptr, Create.array.hHook)
      Create.array.keys := Create.array.hHook := ""
   }
   
   for k,v in Create.array.handles
   {
      ControlGetText, Text,, ahk_id %v%
      if SubStr(Text, -1) = "+ "
         ControlSetText,, Нет, ahk_id %v%
   }
}

SetWindowsHookEx()
{
   Return DllCall("SetWindowsHookEx" . (A_IsUnicode ? "W" : "A")
      , Int, WH_KEYBOARD_LL := 13
      , Ptr, RegisterCallback("LowLevelKeyboardProc", "Fast")
      , Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
      , UInt, 0, Ptr)
}

LowLevelKeyboardProc(nCode, wParam, lParam)
{
   static WM_KEYDOWN := 0x100, WM_KEYUP := 0x101, WM_SYSKEYDOWN := 0x104, WM_SYSKEYUP := 0x105
      , EndKey, prevMessage, prevKey
   
   SetBatchLines, -1
   SetFormat, IntegerFast, H
   Message := wParam, Extended := NumGet(lParam+0, 8, "UInt") & 1
   sc := Extended << 8 | NumGet(lParam+0, 4, "UInt")
   vk := NumGet(lParam+0, 0, "UInt")
   key := GetKeyName("vk" SubStr(vk, 3) "sc" SubStr(sc, 3))
   
   if (Message = prevMessage && key = prevKey)
      Return nCode < 0 ? DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam) : 1
   prevMessage := Message, prevKey := key
   
   if key in LControl,RControl
      key := SubStr(key, 1, 1) . "Ctrl"
   if (sc = 0x145)
      key := "NumLock"
   
   if (Message = WM_KEYDOWN || Message = WM_SYSKEYDOWN)
   {
      if key in LCtrl,RCtrl,LAlt,RAlt,LShift,RShift,LWin,RWin
      {
         EndKey ? Create.array.keys := EndKey := ""
         if !InStr(Create.array.keys, key)
            Create.array.keys .= key . " + "
      }
      else
      {
         EndKey := 1
         if (SubStr(Create.array.keys, -1) = "+ " || Create.array.keys = "")
            Create.array.keys .= key
         else
            Create.array.keys := RegExReplace(Create.array.keys, "(.*?)\S+$", "$1" key)
         
         Create.array.LastKey := "vk" . SubStr(vk, 3)  . "sc" . SubStr(sc, 3)
      }
   }
   
   if (Message = WM_KEYUP || Message = WM_SYSKEYUP)
   {
      if key in LCtrl,RCtrl,LAlt,RAlt,LShift,RShift,LWin,RWin
         Create.array.keys := RegExReplace(Create.array.keys, key . " \+ ")
      else
         EndKey := 1
         
      if !EndKey
         SetTimer, SetText, -10
      
      Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam)
   }

   SetTimer, SetText, -10
   Return nCode < 0 ? DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam) : 1
   
SetText:
   keys := Create.array.keys, LastKey := Create.array.LastKey
   if (keys != "" && keys != "Нет" && Substr(keys, -1) != "+ ")
   {
      Loop, parse, keys, +, % " "
      {
         IsSym := ""
         for k,v in {Ctrl: "^", Alt: "!", Shift: "+", Win: "#"}
            if InStr(A_LoopField, k) && A_LoopField != "CtrlBreak"
               HKString .= (SubStr(A_LoopField, 1, 1) = "L" ? "<" : ">") . v, IsSym := 1
         
         if !IsSym
         {
            if StrLen(A_LoopField) > 1
               HKString .= InStr(A_LoopField, "Num") ? RegExReplace(LastKey, ".*(s.*)", "$1") : A_LoopField
            else
               HKString .= RegExReplace(LastKey, "(.*)s.*", "$1")
         }
      }
      Create.array.HK := HKString
   }
   ControlSetText,, % keys = "" ? "Нет" : keys, % "ahk_id" Create.array.hControl
   return
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

63

Re: AHK: Замена стандартного элемента управления "Hotkey"

Тоже самое.
Придётся покупать

И джойстик заодно

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

64

Re: AHK: Замена стандартного элемента управления "Hotkey"

Не, джойстик ни за что.

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

65

Re: AHK: Замена стандартного элемента управления "Hotkey"

Эхх. А я всё надеюсь на хуко - джой от teadrinker.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

66 (изменено: serzh82saratov, 2013-08-21 19:35:37)

Re: AHK: Замена стандартного элемента управления "Hotkey"

Что скажете про работоспособность такого варианта? Вроде бы как, все переменные локальны.

+ открыть спойлер


#SingleInstance Force
Gui, Add, Edit, Center w300 gWriteIni vMyHotkey1
Gui, Add, Edit, Center wp gWriteIni vMyHotkey2
Gui, Add, Edit, wp vEdit
Hotkey_Init("MyHotkey1|MyHotkey2")
Gui, Show
return
 
WriteIni:
    GuiControl, , Edit, % A_GuiControl " = " %A_GuiControl%
    return

GuiClose:
    ExitApp



Hotkey_Init(Control, Read = 0)  {
    Static ControlArr := {}, IsStart
    If (Read)
        Return ControlArr["H" Control]    
    SaveFormat := A_FormatInteger
    SetFormat, IntegerFast, H
    Loop, Parse, Control, |
    {
        RegExMatch(A_LoopField, "S)(.*:)?\s*(.*)", D)  
        GuiControlGet, Hwnd, % D1 "Hwnd", % D2
        ControlArr.Insert("H" Hwnd, D2)
    }
    ControlGetFocus, IsFocus, A
    ControlGet, FocusHwnd, Hwnd,, %IsFocus%, A
    If ControlArr.HasKey("H" FocusHwnd)
        Hotkey_Main("", "", FocusHwnd)
    If (!IsStart)
        Hotkey_SetWinEventHook(0x8005, 0x8005, 0, RegisterCallback("Hotkey_Main", "F"),0,0,0)
        , IsStart := 1   ; EVENT_OBJECT_FOCUS := 0x8005 
    SetFormat, IntegerFast, %SaveFormat%
}

Hotkey_Main(Param1, Param2, Param3) {
    Static Hook, DelStr, VarName, ControlHandle, PrHandle, Hotkey, KeyName
        , MCtrl, MAlt, MShift, MWin, PCtrl, PAlt, PShift, PWin, Prefix
        , Pref := {"Alt":"!","Ctrl":"^","Shift":"+","Win":"#"}
        , Symbols := "|vkBA|vkBB|vkBC|vkBD|vkBE|vkBF|vkC0|vkDB|vkDC|vkDD|vkDE|vk41|vk42|"
                        . "vk43|vk44|vk45|vk46|vk47|vk48|vk49|vk4A|vk4B|vk4C|vk4D|vk4E|"
                        . "vk4F|vk50|vk51|vk52|vk53|vk54|vk55|vk56|vk57|vk58|vk59|vk5A|" 
    SetBatchLines, -1
    If (Param3)
    {
        SaveFormat := A_FormatInteger
        SetFormat, IntegerFast, H
        If ((Name := Hotkey_Init(Param3, 1)) != "")
        {
            If (DelStr)
                SendMessage, 0xC, 0, "Нет", , ahk_id %PrHandle%
            DelStr := 0, VarName := Name, ControlHandle := PrHandle := Param3, Hotkey := " "
            If !Hook
                Hook := Hotkey_SetWindowsHookEx()
            Send {LButton Up} 
            PostMessage,0x00B1,,,, ahk_id %ControlHandle%    ;    EM_SETSEL := 0x00B1
        }
        else If Hook
        {
            DllCall("UnhookWindowsHookEx" , Ptr, Hook)
            MCtrl := MAlt := MShift := MWin := Hook := "", Hotkey := " "
            PCtrl := PAlt := PShift := PWin := Prefix := ""
            If (DelStr)
                SendMessage, 0xC, 0, "Нет", , ahk_id %ControlHandle%
        }
        SetFormat, IntegerFast, %SaveFormat%
        Return
    }
    If (Param1 = "Mod")
    {
        IsMod := Param2 
        If (M%IsMod% != "")
            Return 
        M%IsMod% := IsMod "+", P%IsMod% := Pref[IsMod]
    }
    Else If (Param1 = "ModUp")
    {
        IsMod := Param2, M%IsMod% := P%IsMod% := "" 
        If (Hotkey != "")
            Return 
    }
    (IsMod != "") ? (KeyName := Hotkey := Prefix := "", DelStr := 1)
    : ( KeyName := GetKeyName(Param1 Param2), DelStr := 0
    , Hotkey := InStr(Symbols, "|" Param1 "|") ? Param1 : KeyName
    , Prefix := PCtrl PAlt PShift PWin)
    Hotkey_SetVarName(VarName, Prefix Hotkey)
    WriteText := MCtrl MAlt MShift MWin KeyName = ""
    ? "Нет" : MCtrl MAlt MShift MWin KeyName
    SendMessage, 0xC, 0, &WriteText, , ahk_id %ControlHandle%
    Return 
}

Hotkey_LowLevelKeyboardProc(nCode, wParam, lParam)  {
    Static Mods := {"vkA4":"Alt","vkA5":"Alt","vkA2":"Ctrl","vkA3":"Ctrl"
                ,"vkA0":"Shift","vkA1":"Shift","vk5B":"Win","vk5C":"Win"}
    SetBatchLines, -1
    SaveFormat := A_FormatInteger
    SetFormat, IntegerFast, H
    VkCode := "vk" SubStr( NumGet(lParam+0, 0, "UInt"), 3)
        D := NumGet(lParam+0, 8, "UInt") & 1
        D := D << 8 | NumGet(lParam+0, 4, "UInt")
    SCCode := "sc" SubStr(D, 3)
    SetFormat, IntegerFast, %SaveFormat%
    IF (wParam = 0x100 || wParam = 0x104)    ;    WM_KEYDOWN := 0x100, WM_SYSKEYDOWN := 0x104
    {
        IF IsMod := Mods[VkCode]
            Hotkey_Main("Mod", IsMod, "")
        Else
            Hotkey_Main(VkCode, SCCode, "")
        Return nCode < 0 ? DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam) : 1
    }
   IF ((wParam = 0x101 || wParam = 0x105) && VkCode != "vk5D") ;  WM_KEYUP := 0x101, WM_SYSKEYUP := 0x105, AppsKey = "vk5D"
   {
        IF IsMod := Mods[VkCode]
            Hotkey_Main("ModUp", IsMod, "")
        Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam)
    }
    Return nCode < 0 ? DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam) : 1
}

Hotkey_SetWinEventHook(eventMin, eventMax, hmodWinEventProc, lpfnWinEventProc, idProcess, idThread, dwFlags) {
    Return DllCall("SetWinEventHook" , UInt, eventMin
                                    , UInt, eventMax
                                    , Ptr, hmodWinEventProc
                                    , Ptr, lpfnWinEventProc
                                    , UInt, idProcess
                                    , UInt, idThread
                                    , UInt, dwFlags, Ptr)
}

Hotkey_SetWindowsHookEx() {
   Return DllCall("SetWindowsHookEx" . (A_IsUnicode ? "W" : "A")
      , Int, 13 ; WH_KEYBOARD_LL := 13
      , Ptr, RegisterCallback("Hotkey_LowLevelKeyboardProc", "Fast")
      , Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
      , UInt, 0, Ptr)
}

Hotkey_SetVarName(Name, Value) {
    Global
    %Name% := Value
}

Ещё вопрос:
может ли библиотека считаться библиотекой, если в ней присутствует метка?

Например, если перевести NumLock в положение On и нажать Shift+клавиша на цифровой клавиатуре, то тоже сбрасывается

Я так понял что Shift является аппаратным модификаторов Num-цифр.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

67

Re: AHK: Замена стандартного элемента управления "Hotkey"

В целом всё работает,такие мелкие недостатки:
Клавиши цифровой клавиатуры определяются в зависимости от NumLock-статуса, соответственно, и срабатывать будут также. Можно, конечно, сказать, что это фича, но на практике лишь внесёт путаницу.
Неправильно определяется Ctrl+NumLock.

Глобальная переменная всё же есть:

Hotkey_SetVarName(Name, Value) {
    Global
    %Name% := Value
}

Метка не помешает.

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

68

Re: AHK: Замена стандартного элемента управления "Hotkey"

Тут ещё проблема наших вариантов, если вызвать контекстное меню Edit, то хук снимается. А лучше как и в оригинале исключить меню совсем. Стиля Edit такого ненашёл. На ум приходит только хоткей правой кнопки

Метка не помешает.

А если название переклинется с пользовательским?

Глобальная переменная всё же есть:

Только та, которая уже существует у Edit-ов. Так что не в счёт.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

69

Re: AHK: Замена стандартного элемента управления "Hotkey"

У меня, вроде, не снимается. Можно делать пустой хоткей правой кнопки, когда нужный контрол в фокусе.

serzh82saratov пишет:

А если название переклинется с пользовательским?

Ну так и название функции может пересечься. Ничего, просто интерпретатор выдаст ошибку.

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

70

Re: AHK: Замена стандартного элемента управления "Hotkey"

Неправильно определяется Ctrl+NumLock

Всё правильно,  хоткея ^NumLock нет. Есть ^Pause.

Клавиши цифровой клавиатуры определяются в зависимости от NumLock-статуса, соответственно, и срабатывать будут также. Можно, конечно, сказать, что это фича, но на практике лишь внесёт путаницу.

У меня мини клава. Ничего сказать немогу, но как я понял ты предлагаешь определять не все кнопки цифровой клавиатуры.
На виртуальной клаве в твоём коде также зависимость от NumLock.

У меня, вроде, не снимается.

Поводи мышью по меню.

Можно делать пустой хоткей правой кнопки, когда нужный контрол в фокусе.

Не кашерно как-то. Там хотя бы определять что мышь именно над полем ввода надо, но тоже не айс.

Ну так и название функции может пересечься. Ничего, просто интерпретатор выдаст ошибку.

Насколько я знаю, при использовании библиотек учитывается только префикс названий функций.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

71

Re: AHK: Замена стандартного элемента управления "Hotkey"

Всё правильно,  хоткея ^NumLock нет. Есть ^Pause.

Да, точно.

На виртуальной клаве в твоём коде также зависимость от NumLock.

Не совсем понял. У меня они по сканкодам записываются, а сканкоды в любом статусе NumLock одинаковые.

Там хотя бы определять что мышь именно над полем ввода надо, но тоже не айс.

Почему?

Насколько я знаю, при использовании библиотек учитывается только префикс названий функций.

М-м-м... Учитывается для чего? Если в библиотеке MyLib.ahk есть две функции: одна с названием MyLib(), другая с названием Test(), то последнюю интерпретатор будет учитывать, если предварительно вызвана функция с названием MyLib(). Так что если в коде пользователя окажется определение функции Test(), интерпретатор выдаст ошибку.

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

72

Re: AHK: Замена стандартного элемента управления "Hotkey"

Почему?

Некрасиво. Может как то можно SetWinEventHook ето определять, и не снимать хук.

М-м-м... Учитывается для чего?

Я про либы, которые можно использовать по умолчанию из папки АНК.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

73

Re: AHK: Замена стандартного элемента управления "Hotkey"

Может как то можно SetWinEventHook ето определять, и не снимать хук.

Можно определять класс окна по параметру hwnd, в Win 7 класс меню ahk_class #32768. Но на XP как-то по-другому, вроде, не помню сейчас.

Я про либы, которые можно использовать по умолчанию из папки АНК.

Я про них же. В библиотеке не обязательно все функции должны быть с одним и тем же префиксом.

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

74

Re: AHK: Замена стандартного элемента управления "Hotkey"

Можно определять класс окна по параметру hwnd, в Win 7 класс меню ahk_class #32768. Но на XP как-то по-другому, вроде, не помню сейчас.

EVENT_SYSTEM_MENUPOPUPSTART := 0x0006, EVENT_SYSTEM_MENUPOPUPEND := 0x0007

Так работает. Но WinHide ahk_id %id%, допускает мелькания меню. Думаю дальше что с этим делать.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

75

Re: AHK: Замена стандартного элемента управления "Hotkey"

Если хочешь совсем избавиться от появления меню, тогда либо хоткей на RButton, либо запускать ещё и мышиный хук.

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

76 (изменено: serzh82saratov, 2013-08-22 05:45:03)

Re: AHK: Замена стандартного элемента управления "Hotkey"

С мышиным хуком не особо стабильно получилось, сделал с хоткеем:

+ открыть спойлер

Gui, Add, Edit, Center w300 gWriteIni vMyHotkey1  
Gui, Add, Edit, Center wp gWriteIni vMyHotkey2  
Gui, Add, Edit, wp Center vText
Hotkey_Init(" MyHotkey1| MyHotkey2")
Gui, Show  
Return
 
WriteIni:
    GuiControl, %A_Gui%:, Text, % A_GuiControl " = " %A_GuiControl%
    Return
    
GuiClose: 
    ExitApp

Hotkey_Init(Control, Read = 0)  {
    Static ControlArr := {}, IsStart
    If (Read)
        Return ControlArr["H" Control]    
    SaveFormat := A_FormatInteger
    SetFormat, IntegerFast, H
    Loop, Parse, Control, |
    {
        RegExMatch(A_LoopField, "S)(.*:)?\s*(.*)", D)  
        GuiControlGet, Hwnd, % D1 "Hwnd", % D2
        ControlArr.Insert("H" Hwnd, D2)
    }
    ControlGetFocus, IsFocus, A
    ControlGet, FocusHwnd, Hwnd,, %IsFocus%, A
    If ControlArr.HasKey("H" FocusHwnd)
        Hotkey_Main("", "", FocusHwnd)
    If (!IsStart)  
        , Hotkey_SetWinEventHook(0x8005, 0x8005, 0, RegisterCallback("Hotkey_Main", "F"),0,0,0) 
        , Hotkey_RButton(), IsStart := 1    ; EVENT_OBJECT_FOCUS := 0x8005 
    SetFormat, IntegerFast, %SaveFormat%
}

Hotkey_Main(Param1, Param2, Param3) {
    Static Hook, DelStr, VarName, ControlHandle, PrHandle, Hotkey, KeyName
        , MCtrl, MAlt, MShift, MWin, PCtrl, PAlt, PShift, PWin, Prefix
        , Pref := {"Alt":"!","Ctrl":"^","Shift":"+","Win":"#"}
        , Symbols := "|vkBA|vkBB|vkBC|vkBD|vkBE|vkBF|vkC0|vkDB|vkDC|vkDD|vkDE|vk41|vk42|"
                        . "vk43|vk44|vk45|vk46|vk47|vk48|vk49|vk4A|vk4B|vk4C|vk4D|vk4E|"
                        . "vk4F|vk50|vk51|vk52|vk53|vk54|vk55|vk56|vk57|vk58|vk59|vk5A|" 
    SetBatchLines, -1
    If (Param3)
    {
        SaveFormat := A_FormatInteger
        SetFormat, IntegerFast, H   
        If ((Name := Hotkey_Init(Param3, 1)) != "")
        {        
            If (DelStr)
                SendMessage, 0xC, 0, "Нет", , ahk_id %PrHandle%
            DelStr := 0, VarName := Name, ControlHandle := PrHandle := Param3, Hotkey := " "
            If !Hook
                Hook := Hotkey_SetWindowsHookExK() 
            Send {LButton Up} 
            PostMessage,0x00B1,,,, ahk_id %ControlHandle%    ;    EM_SETSEL := 0x00B1
        }
        else If Hook
        {
            DllCall("UnhookWindowsHookEx" , Ptr, Hook) 
            MCtrl := MAlt := MShift := MWin := Hook := "", Hotkey := " "
            PCtrl := PAlt := PShift := PWin := Prefix := ""
            If (DelStr)
                SendMessage, 0xC, 0, "Нет", , ahk_id %ControlHandle%
        }
        SetFormat, IntegerFast, %SaveFormat%
        Return
    }
    If (Param1 = "Mod")
    {
        IsMod := Param2 
        If (M%IsMod% != "")
            Return 1
        M%IsMod% := IsMod "+", P%IsMod% := Pref[IsMod]
    }
    Else If (Param1 = "ModUp")
    {
        IsMod := Param2, M%IsMod% := P%IsMod% := "" 
        If (Hotkey != "")
            Return 1
    }
    (IsMod != "") ? (KeyName := Hotkey := Prefix := "", DelStr := 1)
    : ( KeyName := GetKeyName(Param1 Param2), DelStr := 0
    , Hotkey := InStr(Symbols, "|" Param1 "|") ? Param1 : KeyName
    , Prefix := PCtrl PAlt PShift PWin), Keys := MCtrl MAlt MShift MWin KeyName
    Hotkey_SetVarName(VarName, Prefix Hotkey)
    WriteText := Keys = "" ? "Нет" : Keys
    SendMessage, 0xC, 0, &WriteText, , ahk_id %ControlHandle%
    Return 1
}

Hotkey_LowLevelKeyboardProc(nCode, wParam, lParam)  {
    Static Mods := {"vkA4":"Alt","vkA5":"Alt","vkA2":"Ctrl","vkA3":"Ctrl"
                ,"vkA0":"Shift","vkA1":"Shift","vk5B":"Win","vk5C":"Win"}
    SetBatchLines, -1
    SaveFormat := A_FormatInteger
    SetFormat, IntegerFast, H
    VkCode := "vk" SubStr( NumGet(lParam+0, 0, "UInt"), 3)
        D := NumGet(lParam+0, 8, "UInt") & 1
        D := D << 8 | NumGet(lParam+0, 4, "UInt")
    SCCode := "sc" SubStr(D, 3)
    SetFormat, IntegerFast, %SaveFormat%
    IF (wParam = 0x100 || wParam = 0x104)    ;    WM_KEYDOWN := 0x100, WM_SYSKEYDOWN := 0x104
    {
        IF IsMod := Mods[VkCode]
            Hotkey_Main("Mod", IsMod, "")
        Else
            Hotkey_Main(VkCode, SCCode, "")
        Return nCode < 0 ? DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam) : 1
    }
   IF ((wParam = 0x101 || wParam = 0x105) && VkCode != "vk5D") ;  WM_KEYUP := 0x101, WM_SYSKEYUP := 0x105, AppsKey = "vk5D"
   {
        IF IsMod := Mods[VkCode]
            Hotkey_Main("ModUp", IsMod, "")
        Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam)
    }
    Return nCode < 0 ? DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam) : 1
}

Hotkey_SetWinEventHook(eventMin, eventMax, hmodWinEventProc, lpfnWinEventProc, idProcess, idThread, dwFlags) {
    Return DllCall("SetWinEventHook" , UInt, eventMin
                                    , UInt, eventMax
                                    , Ptr, hmodWinEventProc
                                    , Ptr, lpfnWinEventProc
                                    , UInt, idProcess
                                    , UInt, idThread
                                    , UInt, dwFlags, Ptr)
}

Hotkey_SetWindowsHookExK() {
    Return DllCall("SetWindowsHookEx" . (A_IsUnicode ? "W" : "A")
        , Int, 13 ; WH_KEYBOARD_LL := 13
        , Ptr, RegisterCallback("Hotkey_LowLevelKeyboardProc", "Fast")
        , Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
        , UInt, 0, Ptr)
}

Hotkey_SetVarName(Name, Value) {
    Global
    %Name% := Value
}

Hotkey_IsHotkeyControl() {
    MouseGetPos,,,, Control, 2 
    Return Hotkey_Init(Control, 1) != ""
} 

Hotkey_RButton() {
    #IF Hotkey_IsHotkeyControl()
    #IF
    Hotkey, IF, Hotkey_IsHotkeyControl()  
    Hotkey, RButton Up, Hotkey_RButton
    Hotkey, IF
    Hotkey_RButton:
        Click
        Return
} 

Кстати, в твоём варианте AppsKey вызывает меню.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

77 (изменено: serzh82saratov, 2013-08-22 19:52:03)

Re: AHK: Замена стандартного элемента управления "Hotkey"

teadrinker пишет:

Кроме того, в коде такой недостаток: в функциях используется несколько OnMessage().

Возможно ли получать те же сообщения что и OnMessage но без оного. Например  RegisterWindowMessage и.т.п.

То есть регистрировать функции скрипта для получения Window Message, без использования OnMessage.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

78 (изменено: serzh82saratov, 2013-08-24 07:34:33)

Re: AHK: Замена стандартного элемента управления "Hotkey"

Выкладываю версию похожую на библиотеку:

+ открыть спойлер

#SingleInstance Force
Ini = %A_ScriptDir%\Hotkey.ini
Gui, +AlwaysOnTop
Gui, Add, Edit, w300 Center gWriteIni vMyHotkey1, % Hotkey_IniRead("1_MyHotkey1", "Section", Ini)
Gui, Add, Edit, Center wp gWriteIni vMyHotkey2,  % Hotkey_IniRead("1_MyHotkey2", "Section", Ini)
Gui, Add, Edit, wp Center vText

Gui, 2:Add, Edit, Center w300 gWriteIni vMyHotkey1, % Hotkey_IniRead("2_MyHotkey1", "Section", Ini)
Gui, 2:Add, Edit, Center wp gWriteIni vMyHotkey2, % Hotkey_IniRead("2_MyHotkey2", "Section", Ini)
Gui, 2:Add, Edit, wp Center vText
Hotkey_Init("MyHotkey1|MyHotkey2|2:MyHotkey1|2:MyHotkey2") 
Gui, 2:Show
Gui, Show, x111
Return 

1::   ;   Извлечение переменных
    ToolTip % "1_MyHotkey1 = " Hotkey_GetVar("MyHotkey1") "`n" "1_MyHotkey2 = " Hotkey_GetVar("MyHotkey2")
    . "`n2_MyHotkey1 = " Hotkey_GetVar("2:MyHotkey1") "`n" "2_MyHotkey2 = " Hotkey_GetVar("2:MyHotkey2")
    Return 

WriteIni:
    GuiControl, %A_Gui%:, Text, % A_Gui "_" A_GuiControl " = " %A_GuiControl%
    IniWrite, % %A_GuiControl%, % Ini, Section, % A_Gui "_" A_GuiControl
    Return

GuiClose:
2GuiClose:
    ExitApp




Hotkey_Init(Control, Read = 0)  {
    Static ControlArr := {}, IsStart, SaveFormat
    If (Read)
        Return ControlArr["H" Control]
    SaveFormat := A_FormatInteger
    SetFormat, IntegerFast, H
    Loop, Parse, Control, |
    {
        RegExMatch(A_LoopField, "S)(.*:)?\s*(.*)", D)
        GuiControlGet, Hwnd, % D1 "Hwnd", % D2
        ControlArr.Insert("H" Hwnd, D2)
        GuiControl, %D1% +ReadOnly, % D2
    }
    SetFormat, IntegerFast, %SaveFormat%
    ControlGetFocus, IsFocus, A
    ControlGet, FocusHwnd, Hwnd,, %IsFocus%, A
    If (FocusHwnd != "" && ControlArr.HasKey("H" FocusHwnd))
        Hotkey_Main("", "", FocusHwnd)
    If (!IsStart)
        Hotkey_SetWinEventHook(0x8005, 0x8005, 0, RegisterCallback("Hotkey_Main", "F"),0,0,0)
        , Hotkey_RButton(), IsStart := 1    ;    EVENT_OBJECT_FOCUS := 0x8005
    Return
}

Hotkey_Main(Param1, Param2, Handle) {
    Static Hook, DelStr, VarName, ControlHandle, PrHandle, Hotkey, KeyName
        , MCtrl, MAlt, MShift, MWin, PCtrl, PAlt, PShift, PWin, Prefix, SaveFormat
        , Pref := {"Alt":"!","Ctrl":"^","Shift":"+","Win":"#"}
        , Symbols := "|vkBA|vkBB|vkBC|vkBD|vkBE|vkBF|vkC0|vkDB|vkDC|vkDD|vkDE|vk41|vk42|"
                         . "vk43|vk44|vk45|vk46|vk47|vk48|vk49|vk4A|vk4B|vk4C|vk4D|vk4E|"
                         . "vk4F|vk50|vk51|vk52|vk53|vk54|vk55|vk56|vk57|vk58|vk59|vk5A|"
    SetBatchLines, -1
    If (Handle)
    {
        SaveFormat := A_FormatInteger
        SetFormat, IntegerFast, H
        If ((Name := Hotkey_Init(Handle, 1)) != "")
        {
            If (DelStr)
                SendMessage, 0xC, 0, "Нет", , ahk_id %PrHandle%
            DelStr := 0, VarName := Name, ControlHandle := PrHandle := Handle
            If (!Hook)
                Hook := Hotkey_SetWindowsHookEx()
            Send {LButton Up}
            PostMessage,0x00B1,,,, ahk_id %ControlHandle%    ;    EM_SETSEL := 0x00B1
        }
        Else If (Hook)
        {
            DllCall("UnhookWindowsHookEx" , Ptr, Hook)
            MCtrl := MAlt := MShift := MWin := Hook := ""
            PCtrl := PAlt := PShift := PWin := Prefix := ""
            If (DelStr)
                SendMessage, 0xC, 0, "Нет", , ahk_id %ControlHandle%
        }
        SetFormat, IntegerFast, %SaveFormat%
        Return
    }

    If (Param1 = "Mod")
    {
        IsMod := Param2
        If (M%IsMod% != "")
            Return 1
        M%IsMod% := IsMod "+", P%IsMod% := Pref[IsMod]
    }
    Else If (Param1 = "ModUp")
    {
        IsMod := Param2, M%IsMod% := P%IsMod% := ""
        If (Hotkey != "")
            Return 1
    }
    (IsMod) ? (KeyName := Hotkey := Prefix := "", DelStr := 1)
    : ( KeyName := GetKeyName(Param1 Param2), DelStr := 0
    ,  Hotkey := InStr(Symbols, "|" Param1 "|") ? Param1 : KeyName
    ,  KeyName := Hotkey = "vkBF" ? "/" : KeyName
    ,  Prefix := PCtrl PAlt PShift PWin)
    Hotkey_SetVarName(VarName, Prefix Hotkey)
    WriteText := MCtrl MAlt MShift MWin KeyName = "" ? "Нет" : MCtrl MAlt MShift MWin KeyName
    SendMessage, 0xC, 0, &WriteText, , ahk_id %ControlHandle%
    Return 1
}

Hotkey_LowLevelKeyboardProc(nCode, wParam, lParam)  {
    Static Mods := {"vkA4":"Alt","vkA5":"Alt","vkA2":"Ctrl","vkA3":"Ctrl"
                ,"vkA0":"Shift","vkA1":"Shift","vk5B":"Win","vk5C":"Win"}, SaveFormat
    SetBatchLines, -1
    SaveFormat := A_FormatInteger
    SetFormat, IntegerFast, H
    VkCode := "vk" SubStr( NumGet(lParam+0, 0, "UInt"), 3)
        D := NumGet(lParam+0, 8, "UInt") & 1, D := D << 8 | NumGet(lParam+0, 4, "UInt")
    SCCode := "sc" SubStr(D, 3)
    SetFormat, IntegerFast, %SaveFormat%
    IF (wParam = 0x100 || wParam = 0x104)    ;    WM_KEYDOWN := 0x100, WM_SYSKEYDOWN := 0x104
        (IsMod := Mods[VkCode]) ? Hotkey_Main("Mod", IsMod, "") : Hotkey_Main(VkCode, SCCode, "")
    Else IF ((wParam = 0x101 || wParam = 0x105) && VkCode != "vk5D") ;  WM_KEYUP := 0x101, WM_SYSKEYUP := 0x105, AppsKey = "vk5D"
        nCode := -0x1, (IsMod := Mods[VkCode]) ? Hotkey_Main("ModUp", IsMod, "") : ""
    Return nCode < 0 ? DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam) : 1
}

Hotkey_SetWinEventHook(eventMin, eventMax, hmodWinEventProc, lpfnWinEventProc, idProcess, idThread, dwFlags) {
    Return DllCall("SetWinEventHook" , UInt, eventMin
                                    , UInt, eventMax
                                    , Ptr, hmodWinEventProc
                                    , Ptr, lpfnWinEventProc
                                    , UInt, idProcess
                                    , UInt, idThread
                                    , UInt, dwFlags, Ptr)
}

Hotkey_SetWindowsHookEx() {
    Return DllCall("SetWindowsHookEx" . (A_IsUnicode ? "W" : "A")
        , Int, 13 ; WH_KEYBOARD_LL := 13
        , Ptr, RegisterCallback("Hotkey_LowLevelKeyboardProc", "Fast")
        , Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
        , UInt, 0, Ptr)
}

Hotkey_SetVarName(Name, Value) {
    Global
    %Name% := Value
}

Hotkey_IsRegControl() {
    MouseGetPos,,,, Control, 2
    Return Hotkey_Init(Control, 1) != ""
}

Hotkey_RButton() {
    #IF Hotkey_IsRegControl()
    #IF
    Hotkey, IF, Hotkey_IsRegControl()
    Hotkey, RButton Up, Hotkey_RButton
    Hotkey, IF
    Return

    Hotkey_RButton:
        Click
        Return
}

    ; -------------------------------------- Format func --------------------------------------

Hotkey_IniRead(Key, Section, Path) {
    IniRead, Key, % Path, % Section, % Key, % A_Space
    Return Hotkey_FormatHKToStr(Key)
}

Hotkey_FormatHKToStr(Key) {
    RegExMatch(Key, "S)^([\^\+!#]*)\{?(.*?)}?$", K)
    Return K2 = "" ? "Нет" : (InStr(K1,"^")?"Ctrl+":"")(InStr(K1,"!")?"Alt+":"")
            . (InStr(K1,"+")?"Shift+":"")(InStr(K1,"#")?"Win+":"")
            . (InStr(K2,"vk") ? GetKeyName(K2) : K2)
}

Hotkey_FormatHKToSend(Key, Section = "", Path = "") {
    If (Section != "")
        IniRead, Key, % Path, % Section, % Key, % A_Space
    Return RegExReplace( Key, "S)[^\^!\+#].*", "{$0}")
}

Hotkey_GetVar(VarName)  {
    RegExMatch(VarName, "S)(.*:)?\s*(.*)", D)
    GuiControlGet, Hwnd, % D1 "Hwnd", % D2
    ControlGetText, Text,, ahk_id %Hwnd%
    Return Hotkey_FormatStrToHK(Text)
}

Hotkey_FormatStrToHK(Str) {
    Static Buttons := ":ж:`;:|vkBA| :=:|vkBB| :б:,:|vkBC| :-:|vkBD| :ю:.:|vkBE|"
        . ":/:|vkBF| :``:ё:|vkC0| :х:[:|vkDB| :\:|vkDC| :ъ:]:|vkDD| :э:':|vkDE|"
        . ":A:|vk41| :B:|vk42| :C:|vk43| :D:|vk44| :E:|vk45| :F:|vk46| :G:|vk47|"
        . ":H:|vk48| :I:|vk49| :J:|vk4A| :K:|vk4B| :L:|vk4C| :M:|vk4D| :N:|vk4E|"
        . ":O:|vk4F| :P:|vk50| :Q:|vk51| :R:|vk52| :S:|vk53| :T:|vk54| :U:|vk55|"
        . ":V:|vk56| :W:|vk57| :X:|vk58| :Y:|vk59| :Z:|vk5A|"

    If (Str = "Нет" || Str = "" || SubStr(Str, 0) ~= "\+|\s+")
        Return ""
    RegExMatch( Str, "S)(.*\+)?(.*)", K)
    If (StrLen(K2) = 1)
        RegExMatch( Buttons, "Si)\Q:" K2 ":\E.*?\|(.*?)\|", vk)
    Return (InStr(K1,"Ctrl+")?"^":"")(InStr(K1,"Alt+")?"!":"")(InStr(K1,"Shift+")?"+":"")
            . (InStr(K1,"Win+")?"#":"") (vk1 = "" ? K2 : vk1)
}

вроде как устранены все обсуждаемые недостатки.

Post's attachments

Hotkey.ahk 8.22 kb, 19 downloads since 2013-08-24 

You don't have the permssions to download the attachments of this post.
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

79

Re: AHK: Замена стандартного элемента управления "Hotkey"

Вроде всё работает, только ini-файлы так и не пишутся.

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

80

Re: AHK: Замена стандартного элемента управления "Hotkey"

только ini-файлы так и не пишутся.

Не понял.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

81 (изменено: serzh82saratov, 2013-08-24 07:09:51)

Re: AHK: Замена стандартного элемента управления "Hotkey"

Это имеешь ввиду:


#SingleInstance Force
Ini = %A_ScriptDir%\Hotkey.ini
Gui, +AlwaysOnTop
Gui, Add, Edit, w300 Center gWriteIni vMyHotkey1, % Hotkey_IniRead("1_MyHotkey1", "Section", Ini)
Gui, Add, Edit, Center wp gWriteIni vMyHotkey2,  % Hotkey_IniRead("1_MyHotkey2", "Section", Ini)
Gui, Add, Edit, wp Center vText

Gui, 2:Add, Edit, Center w300 gWriteIni vMyHotkey1, % Hotkey_IniRead("2_MyHotkey1", "Section", Ini)
Gui, 2:Add, Edit, Center wp gWriteIni vMyHotkey2, % Hotkey_IniRead("2_MyHotkey2", "Section", Ini)
Gui, 2:Add, Edit, wp Center vText
Hotkey_Init("MyHotkey1|MyHotkey2|2:MyHotkey1|2:MyHotkey2") 
Gui, Show, x111
Gui, 2:Show
Return 

1::
    ToolTip % "1_MyHotkey1 = " Hotkey_GetVar("MyHotkey1") "`n" "1_MyHotkey2 = " Hotkey_GetVar("MyHotkey2")
    . "`n2_MyHotkey1 = " Hotkey_GetVar("2:MyHotkey1") "`n" "2_MyHotkey2 = " Hotkey_GetVar("2:MyHotkey2")
    Return 

WriteIni:
    GuiControl, %A_Gui%:, Text, % A_Gui "_" A_GuiControl " = " %A_GuiControl%
    IniWrite, % %A_GuiControl%, % Ini, Section, % A_Gui "_" A_GuiControl
    Return

2GuiClose:
GuiClose:
    ExitApp
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

82

Re: AHK: Замена стандартного элемента управления "Hotkey"

Да, теперь вроде в порядке. Просто к функции должен быть полноценный пример использования.

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

83 (изменено: serzh82saratov, 2013-10-22 01:52:49)

Re: AHK: Замена стандартного элемента управления "Hotkey"

teadrinker

Вариант с кнопками мыши и джойстиков:

+ открыть спойлер

 

    ;    http://forum.script-coding.com/viewtopic.php?pid=72549#p72549


Hotkey_Init(Control, Read = 0)  {
    Static ControlArr := {}, IsStart, SaveFormat
    If (Read)
        Return ControlArr["H" Control]
    SaveFormat := A_FormatInteger
    SetFormat, IntegerFast, H
    Loop, Parse, Control, |
    {
        RegExMatch(A_LoopField, "S)(.*:)?\s*(.*)", D)
        GuiControlGet, Hwnd, % D1 "Hwnd", % D2
        ControlArr.Insert("H" Hwnd, D2)
        GuiControl, %D1% +ReadOnly, % D2
    }
    SetFormat, IntegerFast, %SaveFormat%
    ControlGetFocus, IsFocus, A
    ControlGet, FocusHwnd, Hwnd,, %IsFocus%, A
    If (FocusHwnd != "" && ControlArr.HasKey("H" FocusHwnd))
        Hotkey_Main("", "", FocusHwnd)
    If (!IsStart) 
        Hotkey_SetWinEventHook(0x8005, 0x8005, 0, RegisterCallback("Hotkey_Main", "F"),0,0,0)    ;    EVENT_OBJECT_FOCUS := 0x8005
        , Hotkey_RButton(), Hotkey_ExtKeyInit(), IsStart := 1  
    Return
}

Hotkey_Main(Param1, Param2, Handle) {
    Static Hook, DelStr, VarName, ControlHandle, PrHandle, Hotkey, KeyName
        , MCtrl, MAlt, MShift, MWin, PCtrl, PAlt, PShift, PWin, Prefix, SaveFormat
        , Pref := {"Alt":"!","Ctrl":"^","Shift":"+","Win":"#"}
        , Symbols := "|vkBA|vkBB|vkBC|vkBD|vkBE|vkBF|vkC0|vkDB|vkDC|vkDD|vkDE|vk41|vk42|"
                         . "vk43|vk44|vk45|vk46|vk47|vk48|vk49|vk4A|vk4B|vk4C|vk4D|vk4E|"
                         . "vk4F|vk50|vk51|vk52|vk53|vk54|vk55|vk56|vk57|vk58|vk59|vk5A|"
    SetBatchLines, -1
    If (Handle)
    {
        SaveFormat := A_FormatInteger
        SetFormat, IntegerFast, H
        If ((Name := Hotkey_Init(Handle, 1)) != "")
        {
            If (DelStr)
                SendMessage, 0xC, 0, "Нет", , ahk_id %PrHandle%
            DelStr := 0, VarName := Name, ControlHandle := PrHandle := Handle
            If (!Hook)
                Hook := Hotkey_SetWindowsHookEx(), Hotkey_IsHook(1)
            Send {LButton Up}
            PostMessage,0x00B1,,,, ahk_id %ControlHandle%    ;    EM_SETSEL := 0x00B1
        }
        Else If (Hook)
        {
            DllCall("UnhookWindowsHookEx" , Ptr, Hook)
            MCtrl := MAlt := MShift := MWin := Hook := "", Hotkey_IsHook(0)
            PCtrl := PAlt := PShift := PWin := Prefix := ""
            If (DelStr)
                SendMessage, 0xC, 0, "Нет", , ahk_id %ControlHandle%
        }
        SetFormat, IntegerFast, %SaveFormat%
        Return
    }
    
    If (Param1 = "Mod")
    {
        IsMod := Param2
        If (M%IsMod% != "")
            Return 1
        M%IsMod% := IsMod "+", P%IsMod% := Pref[IsMod]
    }
    Else If (Param1 = "ModUp")
    {
        IsMod := Param2, M%IsMod% := P%IsMod% := ""
        If (Hotkey != "")
            Return 1
    } 
        
    (IsMod) ? (KeyName := Hotkey := Prefix := "", DelStr := 1)
    : ( KeyName := GetKeyName(Param1 Param2), DelStr := 0
    ,  Hotkey := InStr(Symbols, "|" Param1 "|") ? Param1 : KeyName
    ,  KeyName := Hotkey = "vkBF" ? "/" : KeyName
    ,  Prefix := PCtrl PAlt PShift PWin)
    Hotkey_SetVarName(VarName, Prefix Hotkey)
    WriteText := MCtrl MAlt MShift MWin KeyName = "" ? "Нет" : MCtrl MAlt MShift MWin KeyName
    SendMessage, 0xC, 0, &WriteText, , ahk_id %ControlHandle%
    Return 1
    
Hotkey_PressName:  
    KeyName := Hotkey := A_ThisHotkey, DelStr := 0  
    Prefix := PCtrl PAlt PShift PWin
    Hotkey_SetVarName(VarName, Prefix Hotkey)
    WriteText := MCtrl MAlt MShift MWin KeyName = "" ? "Нет" : MCtrl MAlt MShift MWin KeyName
    SendMessage, 0xC, 0, &WriteText, , ahk_id %ControlHandle%
    Return 
}

Hotkey_ExtKeyInit()  {
    MouseKey := "MButton|WheelDown|WheelUp|WheelRight|WheelLeft|XButton1|XButton2"  
    #IF Hotkey_IsHook("Read")
    #IF
    Hotkey, IF, Hotkey_IsHook("Read")
    Loop, Parse, MouseKey, |
        Hotkey, %A_LoopField%, Hotkey_PressName 
    Loop, 128
        Hotkey % ((A_Index-1)//32)+1 "Joy" Mod(A_Index-1,32)+1, Hotkey_PressName, P3 UseErrorLevel
    Hotkey, IF
    Return
}

Hotkey_IsHook(Value)  {
    Static Hook
    If Value = Read
        Return Hook
    Hook := Value
}

Hotkey_LowLevelKeyboardProc(nCode, wParam, lParam)  {
    Static Mods := {"vkA4":"Alt","vkA5":"Alt","vkA2":"Ctrl","vkA3":"Ctrl"
                ,"vkA0":"Shift","vkA1":"Shift","vk5B":"Win","vk5C":"Win"}, SaveFormat
    SetBatchLines, -1
    SaveFormat := A_FormatInteger
    SetFormat, IntegerFast, H
    VkCode := "vk" SubStr( NumGet(lParam+0, 0, "UInt"), 3)
        D := NumGet(lParam+0, 8, "UInt") & 1, D := D << 8 | NumGet(lParam+0, 4, "UInt")
    SCCode := "sc" SubStr(D, 3)
    SetFormat, IntegerFast, %SaveFormat%
    IF (wParam = 0x100 || wParam = 0x104)    ;    WM_KEYDOWN := 0x100, WM_SYSKEYDOWN := 0x104
        (IsMod := Mods[VkCode]) ? Hotkey_Main("Mod", IsMod, "") : Hotkey_Main(VkCode, SCCode, "")
    Else IF ((wParam = 0x101 || wParam = 0x105) && VkCode != "vk5D") ;  WM_KEYUP := 0x101, WM_SYSKEYUP := 0x105, AppsKey = "vk5D"
        nCode := -1, (IsMod := Mods[VkCode]) ? Hotkey_Main("ModUp", IsMod, "") : ""
    Return nCode < 0 ? DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam) : 1
}

Hotkey_SetWinEventHook(eventMin, eventMax, hmodWinEventProc, lpfnWinEventProc, idProcess, idThread, dwFlags) {
    Return DllCall("SetWinEventHook" , UInt, eventMin
                                    , UInt, eventMax
                                    , Ptr, hmodWinEventProc
                                    , Ptr, lpfnWinEventProc
                                    , UInt, idProcess
                                    , UInt, idThread
                                    , UInt, dwFlags, Ptr)
}

Hotkey_SetWindowsHookEx() {
    Return DllCall("SetWindowsHookEx" . (A_IsUnicode ? "W" : "A")
        , Int, 13 ; WH_KEYBOARD_LL := 13
        , Ptr, RegisterCallback("Hotkey_LowLevelKeyboardProc", "Fast")
        , Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
        , UInt, 0, Ptr)
}

Hotkey_SetVarName(Name, Value) {
    Global
    %Name% := Value
}

Hotkey_IsRegControl() {
    MouseGetPos,,,, Control, 2
    Return Hotkey_Init(Control, 1) != ""
}

Hotkey_RButton() {
    #IF Hotkey_IsRegControl()
    #IF
    Hotkey, IF, Hotkey_IsRegControl()
    Hotkey, RButton Up, Hotkey_RButton
    Hotkey, IF
    Return

    Hotkey_RButton:
        Click
        Return
}

    ; -------------------------------------- Format func --------------------------------------

Hotkey_IniRead(Key, Section, Path) {
    IniRead, Key, % Path, % Section, % Key, % A_Space
    Return Hotkey_FormatHKToStr(Key)
}

Hotkey_FormatHKToStr(Key) {
    RegExMatch(Key, "S)^([\^\+!#]*)\{?(.*?)}?$", K)
    Return K2 = "" ? "Нет" : (InStr(K1,"^")?"Ctrl+":"")(InStr(K1,"!")?"Alt+":"")
            . (InStr(K1,"+")?"Shift+":"")(InStr(K1,"#")?"Win+":"")
            . (InStr(K2,"vk") ? GetKeyName(K2) : K2)
}

Hotkey_FormatHKToSend(Key, Section = "", Path = "") {
    If (Section != "")
        IniRead, Key, % Path, % Section, % Key, % A_Space
    Return RegExReplace( Key, "S)[^\^!\+#].*", "{$0}")
}

Hotkey_GetVar(VarName)  {
    RegExMatch(VarName, "S)(.*:)?\s*(.*)", D)
    GuiControlGet, Hwnd, % D1 "Hwnd", % D2
    ControlGetText, Text,, ahk_id %Hwnd%
    Return Hotkey_FormatStrToHK(Text)
}

Hotkey_FormatStrToHK(Str) {
    Static Buttons := ":ж:`;:|vkBA| :=:|vkBB| :б:,:|vkBC| :-:|vkBD| :ю:.:|vkBE|"
        . ":/:|vkBF| :``:ё:|vkC0| :х:[:|vkDB| :\:|vkDC| :ъ:]:|vkDD| :э:':|vkDE|"
        . ":A:|vk41| :B:|vk42| :C:|vk43| :D:|vk44| :E:|vk45| :F:|vk46| :G:|vk47|"
        . ":H:|vk48| :I:|vk49| :J:|vk4A| :K:|vk4B| :L:|vk4C| :M:|vk4D| :N:|vk4E|"
        . ":O:|vk4F| :P:|vk50| :Q:|vk51| :R:|vk52| :S:|vk53| :T:|vk54| :U:|vk55|"
        . ":V:|vk56| :W:|vk57| :X:|vk58| :Y:|vk59| :Z:|vk5A|"

    If (Str = "Нет" || Str = "" || SubStr(Str, 0) ~= "\+|\s+")
        Return ""
    RegExMatch( Str, "S)(.*\+)?(.*)", K)
    If (StrLen(K2) = 1)
        RegExMatch( Buttons, "Si)\Q:" K2 ":\E.*?\|(.*?)\|", vk)
    Return (InStr(K1,"Ctrl+")?"^":"")(InStr(K1,"Alt+")?"!":"")(InStr(K1,"Shift+")?"+":"")
            . (InStr(K1,"Win+")?"#":"") (vk1 = "" ? K2 : vk1)
}

Как думаешь, можно выкладывать как правильный вариант библиотеки?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

84

Re: AHK: Замена стандартного элемента управления "Hotkey"

Ага, думаю, можно просто пост в Колекции отредактировать.

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

85 (изменено: serzh82saratov, 2013-10-22 01:53:13)

Re: AHK: Замена стандартного элемента управления "Hotkey"

teadrinker
Отредактировал.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

86 (изменено: serzh82saratov, 2014-11-03 13:25:16)

Re: AHK: Замена стандартного элемента управления "Hotkey"

Недавно, в не первый раз, появилась задача создать довольно большой массив из кнопок, и их меток с разными префиксами. На основе "Блок функций для разработчика" из шапки (которую привёл в порядок) сделал скрипт для создания разных массивов по нажатию кнопок (Hook), вручную (Add), и автоматически из буфера обмена (Clipboard), добавляя каждую строку как ключ. Также в массиве можно учитывать количество ключей в строке (Items).



    ;  http://forum.script-coding.com/viewtopic.php?pid=83250#p83250

#NoTrayIcon
#SingleInstance Force
#NoEnv
SetBatchLines, -1
ListLines, Off
Menu, Tray, Icon, Shell32.dll, 71

Global Hotkey_TargetFunc := "Write", Hotkey_Hook := 0, Man_Hook, hGui, CountItem := 1

Patterns := [  ["Standart delimiter", "|", "Arr := """, "|""``n" A_Tab ". """, "Key", ""]
    , ["Standart delimiter (no expression)", "|", "Arr = ", , "Key"]
    , [" "]
    , ["Hotkey labels", "::``n" A_Tab "``n" A_Tab "Return``n``n", "", "", "Key", ""]
    , ["Send `%pref`%`{`%hotkey`%`}", "", "Send, ", "", "Key", "", "{", "}"]
    , ["Send array", "", "Arr := `[", "``n" A_Tab "`, ", "Key", "", "{", "}""`, ", """"]
    , [" "]
    , ["Simple", """, """, "Arr := `[""", """``n" A_Tab "`, """, "Key", ""]
    , ["Simple (no quotes)", ", ", "Arr := [", "``n" A_Tab "`, ", "Key", ""]
    , ["Simple (in simple array)", ", ", "Arr := [", "``n" A_Tab "`, ", "[""key1"", ""key2"", ""key3""]", ""]
    , [" "]
    , ["Associative", """: ""`%Value`%""`, """, "Arr := {""", """: ""`%Value`%""``n" A_Tab "`, """, "Key", "Value"]
    , ["Associative (no quotes)", ": `%Value`%`, ", "Arr := {", ": `%Value`%``n" A_Tab "`, ", "Key", "Value"]
    , ["Associative (value simple array)", """: `%Value`%`, """, "Arr := {""", """: `%Value`%``n" A_Tab "`, """
                                                                , "Key", "[""key1"", ""key2"", ""key3""]"]
    , ["Associative (value simple array no quotes)", ": `%Value`%`, ", "Arr := {", ": `%Value`%``n" A_Tab "`, ", "Key", "[key1, key2, key3]"]  ]

/*
    , ["Name", Delimiter, OpenArr, RowDelimiter, "Key", "Value", HK1Delimiter, HK2Delimiter, PrefKey]
*/

For k, v in Patterns
    Delimiters .= v[1] "|"

Gui, Margin, 10, 10
Gui, +AlwaysOnTop +HWNDhGui -DPIScale +ReSize
Gui, Color, E3C47A
Gui, Font, , Verdana
A_ScreenDPI != 120 ? (xo1:=25, xo2:=16, xo3:=21, wres := 591) : (xo1:=16, xo2:=xo3:=15, wres := 582)

Gui, Add, DDL, xm gControlGet vModificators w222, Modificators||Left & Right Modificators
Gui, Add, Text, x+%xo1%, OpenArr:
Gui, Add, Edit, x+15 vOpenArr w270 WantTab

Gui, Add, Text, xm, Delimiter:
Gui, Add, Edit, x95 yp w500 vDelimiter gControlGet WantTab
Gui, Add, DDL, x95 y+2 vDDLPattern +AltSubmit gPattern w500, % RTrim(Delimiters, "|")

Gui, Add, Text, xm y+6, Row`nDelimiter:
Gui, Add, Edit, x95 yp+6 vRowDelimiter w330 gControlGet WantTab
Gui, Add, Text, x+%xo2%, Items:
Gui, Add, Text, x+15 w66 h26 +0x201 Border
Gui, Add, UpDown, Range0-100 vRowLen gControlGet Wrap Horz 16 Border, 2
GuiControl, Move, RowLen, h26 w52

Gui, Add, Text, xm, Pref Key:
Gui, Add, Edit, x95 yp vPrefKey w229 gControlGet WantTab
Gui, Add, Text,  x+%xo3%, `%Value`%
Gui, Add, Edit, x+15 yp vValue w179 gControlGet WantTab

Gui, Add, Text, xm, Key:
Gui, Add, Edit, x95 yp vKey w400 gControlGet WantTab
Gui, Add, Button, x+15 w85 gFrom_Clip vFrom_Clip, Clipboard

Gui, Add, Button, xm+40 vBut_Add w85 gAdd, Add
Gui, Add, Button, x+15 vBut_Hook wp gHook, Hook
Gui, Add, Button, x+125 vBut_Copy wp gCopy, Copy
Gui, Add, Button, x+15 vBut_Clean wp gClean, Clean

Gui, Add, Edit, xm r14 WantTab -Wrap +HScroll vResult hwndhResult w%wres%
GuiControlGet, PosResult, Pos, Result

OnExit, GuiClose
OnMessage(0x6, "WM_ACTIVATE")
DllCall("RegisterShellHookWindow", "UInt", A_ScriptHwnd)
OnMessage(DllCall("RegisterWindowMessage", "str", "SHELLHOOK"), "ShellProc")
SetWinEventHook(0x8005, 0x8005, 0, RegisterCallback("Focus", "F"),0,0,0)    ;    EVENT_OBJECT_FOCUS := 0x8005

Gui, Show
Gui, +MinSize

GuiControl, Choose, DDLPattern, |1
Gui, Submit, NoHide
Hotkey_Control(1)
GuiControl, Focus, Static1
Return

Pattern:
    GuiControlGet DDLPattern
    GuiControl, , Delimiter, % Patterns[DDLPattern, 2]
    GuiControl, , OpenArr, % Patterns[DDLPattern, 3]
    GuiControl, , RowDelimiter, % Patterns[DDLPattern, 4]
    GuiControl, , Key, % Patterns[DDLPattern, 5]
    GuiControl, , Value, % Patterns[DDLPattern, 6]
    HK1Delimiter := Patterns[DDLPattern, 7]
    HK2Delimiter := Patterns[DDLPattern, 8]
    GuiControl, , PrefKey, % Patterns[DDLPattern, 9] 
    ;   GuiControl, Focus, Delimiter
    Return

ControlGet:
    GuiControlGet %A_GuiControl%
    If A_GuiControl = Delimiter
        StringReplace, Delimiter, Delimiter, ``n, `n, 1
    Return

From_Clip:
    TempClipboard := Clipboard
    Gui, +Disabled -AlwaysOnTop
    Loop, parse, TempClipboard, `n, `r
        Write({"Addkey":A_LoopField, "Add":1}*)
    Gui, -Disabled +AlwaysOnTop
    Gui, Show
    Return

Add:
    Write({"Addkey":Key, "Add":1}*)
    Return

Hook:
    Hotkey_Hook := !Hotkey_Hook, Man_Hook := Hotkey_Hook ? 1 : 0
    GuiControl, , But_Hook, % Hotkey_Hook ? "UnHook" : "Hook"
    GuiControl, Disable%Hotkey_Hook%, But_Add
    GuiControl, Disable%Hotkey_Hook%, From_Clip
    Return

Copy:
    GuiControlGet, Result
    Clipboard := Result
    Return

Clean:
    GuiControl, , Result,
    CountItem := 1, PrHK := ""
    Return

ShellProc(nCode, wParam)   {
    If (nCode = 4)
    {
        If (wParam = hGui)
            Man_Hook ? Hotkey_Hook := 1 : 0
        Else If Hotkey_Hook
            Hotkey_Reset()
    }
}

WM_ACTIVATE(wp)   {
    If (wp & 0xFFFF)
            Man_Hook ? Hotkey_Hook := 1 : 0
    Else If (wp & 0xFFFF = 0 && Hotkey_Hook)
        Hotkey_Reset()
}

Focus(hWinEventHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime)   {
    If (Hotkey_Hook && DllCall("GetParent", "UInt", hwnd) = hGui)
    {
        WinGetClass, Class, ahk_id %hwnd%
        If Class = Edit
            GoSub Hook
    }
}

SetWinEventHook(eventMin, eventMax, hmodWinEventProc, lpfnWinEventProc, idProcess, idThread, dwFlags) {
    Return DllCall("SetWinEventHook" , "UInt", eventMin, "UInt", eventMax, "Ptr", hmodWinEventProc
            , "Ptr", lpfnWinEventProc, "UInt", idProcess, "UInt", idThread, "UInt", dwFlags, "Ptr")
}

#If WinActive("ahk_id" hGui) && IsEdit(ClassNN)

Enter:: Control, EditPaste, ``n, %ClassNN%, ahk_id %hGui%

#If

IsEdit(byref ClassNN)    {
    ControlGetFocus, ClassNN, A
    Return ClassNN ~= "^Edit[^7]" ? 1 : 0
}

GuiSize:
    If A_EventInfo != 1
        WinMove, ahk_id %hResult%, , PosResultX, PosResultY, A_GuiWidth-26, A_GuiHeight-PosResultY-10
    Return

GuiClose:
GuiEscape:
    Hotkey_Control(0)
    DllCall("DeregisterShellHookWindow", "UInt", A_ScriptHwnd)
    ExitApp

    ; _________________________________________________ Write _________________________________________________


Write(K*)   {
    Local Prefix, Hotkey, _Delimiter, Mods, KeyName, LR

    If !K.Add
    {
        LR := Modificators = "Modificators" ? "" : "LR"
        Mods := K[LR "Mods"], Prefix := K[LR "Pref"]
        Hotkey := K.HK, KeyName := K.Name
        GuiControl, , Key, % Mods KeyName
        If (PrHK = Prefix Hotkey || Hotkey = "")
            Return
        PrHK := Prefix Hotkey
        GuiControl, , Key, % PrHK "  //  " Mods KeyName
    }
    GuiControlGet Result
    Result := SubStr(Result, StrLen(OpenArr)+1)
    GuiControlGet OpenArr
    If (RowLen && ++CountItem > RowLen && RowDelimiter != "")
    {
        CountItem := 1
        StringReplace, _Delimiter, RowDelimiter, ``n, `n, 1
        StringReplace, _Delimiter, _Delimiter, `%Value`%, %Value%, 1
    }
    Else
        StringReplace, _Delimiter, Delimiter, `%Value`%, %Value%, 1
    GuiControl, -Redraw, Result
    GuiControl, , Result, % OpenArr Result PrefKey Prefix HK1Delimiter Hotkey HK2Delimiter K.Addkey _Delimiter
    SetTimer, GoLastLine, -10
}

GoLastLine:
    SendMessage, 0x0E, , , , ahk_id %hResult%    ;  WM_GETTEXTLENGTH
    PostMessage, 0x00B1, Errorlevel, Errorlevel, , ahk_id %hResult%    ;  EM_SETSEL
    PostMessage, 0xB7,,,, ahk_id %hResult%    ;  EM_SCROLLCARET
    GuiControl, +Redraw, Result
    Return

    ; _________________________________________________ Hotkey Func _________________________________________________

Hotkey_Control(State)  {
    Static IsStart
    If (!IsStart)
        Hotkey_ExtKeyInit(), IsStart := 1
    Hotkey_WindowsHookEx(State)
}

Hotkey_Main(VKCode, SCCode, StateMod = 0, IsMod = 0, OnlyMods = 0)  {
    Static K:={}, ModsOnly, Prefix := {"Alt":"!","Ctrl":"^","Shift":"+","Win":"#"}
        , LRPrefix := {"LAlt":"<!","LCtrl":"<^","LShift":"<+","LWin":"<#"
                ,"RAlt":">!","RCtrl":">^","RShift":">+","RWin":">#"}
        , VkMouse := {"MButton":"vk4","WheelDown":"vk9E","WheelUp":"vk9F","WheelRight":"vk9D"
                ,"WheelLeft":"vk9C","XButton1":"vk5","XButton2":"vk6"}
        , Symbols := "|vkBA|vkBB|vkBC|vkBD|vkBE|vkBF|vkC0|vkDB|vkDC|vkDD|vkDE|vk41|vk42|"
                . "vk43|vk44|vk45|vk46|vk47|vk48|vk49|vk4A|vk4B|vk4C|vk4D|vk4E|"
                . "vk4F|vk50|vk51|vk52|vk53|vk54|vk55|vk56|vk57|vk58|vk59|vk5A|"

    If (OnlyMods)
    {
        If !ModsOnly
            Return 0
        ModsOnly := 0, K.MCtrl := K.MAlt := K.MShift := K.MWin := K.Mods := ""
        K.PCtrl := K.PAlt := K.PShift := K.PWin := K.Pref := ""
        K.PLCtrl := K.PLAlt := K.PLShift := K.PLWin := K.LRPref := ""
        K.PRCtrl := K.PRAlt := K.PRShift := K.PRWin := ""
        K.MLCtrl := K.MLAlt := K.MLShift := K.MLWin := K.LRMods := ""
        K.MRCtrl := K.MRAlt := K.MRShift := K.MRWin := ""
        %Hotkey_TargetFunc%(K*)
        Return 0
    }
    If (StateMod = "Down")
    {
        If (K["M" IsMod] != "")
            Return 1
        sIsMod := SubStr(IsMod, 2)
        K["M" sIsMod] := sIsMod "+", K["P" sIsMod] := Prefix[sIsMod]
        K["M" IsMod] := IsMod "+", K["P" IsMod] := LRPrefix[IsMod]
    }
    Else If (StateMod = "Up")
    {
        sIsMod := SubStr(IsMod, 2)
        K["M" IsMod] := K["P" IsMod] := ""
        If (K["ML" sIsMod] = "" && K["MR" sIsMod] = "")
            K["M" sIsMod] := K["P" sIsMod] := ""
        If (K.HK != "")
            return 1
    }
    K.VK := VKCode, K.SC := SCCode
    K.Mods := K.MCtrl K.MAlt K.MShift K.MWin
    K.LRMods := K.MLCtrl K.MRCtrl K.MLAlt K.MRAlt K.MLShift K.MRShift K.MLWin K.MRWin
    K.TK := GetKeyName(VKCode SCCode), K.TK := K.TK = "" ? VKCode SCCode : K.TK
    (IsMod) ? (K.HK := K.Pref := K.LRPref := K.Name := "", ModsOnly := K.Mods = "" ? 0 : 1)
    : (K.HK := InStr(Symbols, "|" VKCode "|") ? VKCode : K.TK
    , K.Name := K.HK = "vkBF" ? "/" : K.TK
    , K.Pref := K.PCtrl K.PAlt K.PShift K.PWin
    , K.LRPref := K.PLCtrl K.PRCtrl K.PLAlt K.PRAlt K.PLShift K.PRShift K.PLWin K.PRWin
    , ModsOnly := 0)
    %Hotkey_TargetFunc%(K*)
    Return 1

Hotkey_PressName:
    K.Mods := K.MCtrl K.MAlt K.MShift K.MWin
    K.LRMods := K.MLCtrl K.MRCtrl K.MLAlt K.MRAlt K.MLShift K.MRShift K.MLWin K.MRWin
    K.Pref := K.PCtrl K.PAlt K.PShift K.PWin
    K.LRPref := K.PLCtrl K.PRCtrl K.PLAlt K.PRAlt K.PLShift K.PRShift K.PLWin K.PRWin
    K.HK := K.Name := K.TK := A_ThisHotkey, ModsOnly := 0, K.SC := ""
    K.VK := !InStr(A_ThisHotkey, "Joy") ? VkMouse[A_ThisHotkey] : ""
    %Hotkey_TargetFunc%(K*)
    Return 1
}

Hotkey_ExtKeyInit()   {
    MouseKey := "MButton|WheelDown|WheelUp|WheelRight|WheelLeft|XButton1|XButton2"
    #If Hotkey_Hook
    #If
    Hotkey, If, Hotkey_Hook
    Loop, Parse, MouseKey, |
        Hotkey, %A_LoopField%, Hotkey_PressName, P3 UseErrorLevel
    Loop 128
        Hotkey % Ceil(A_Index/32) "Joy" Mod(A_Index-1,32)+1, Hotkey_PressName, P3 UseErrorLevel
    Hotkey, If
}

Hotkey_Reset()   {
    Return Hotkey_Hook := 0, Hotkey_Main("", "", "", "", 1)
}

Hotkey_LowLevelKeyboardProc(nCode, wParam, lParam)   {
    Static Mods := {"vkA4":"LAlt","vkA5":"RAlt","vkA2":"LCtrl","vkA3":"RCtrl"
        ,"vkA0":"LShift","vkA1":"RShift","vk5B":"LWin","vk5C":"RWin"}, SaveFormat

    If !Hotkey_Hook
        Return DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "UInt", wParam, "UInt", lParam)
    SaveFormat := A_FormatInteger
    SetFormat, IntegerFast, H
    VKCode := "vk" SubStr(NumGet(lParam+0, 0, "UInt"), 3)
    sc := NumGet(lParam+0, 8, "UInt") & 1, sc := sc << 8 | NumGet(lParam+0, 4, "UInt")
    SCCode := "sc" SubStr(sc, 3), IsMod := Mods[VKCode]
    SetFormat, IntegerFast, %SaveFormat%
    If (wParam = 0x100 || wParam = 0x104)   ;  WM_KEYDOWN := 0x100, WM_SYSKEYDOWN := 0x104
        IsMod ? Hotkey_Main(VKCode, SCCode, "Down", IsMod) : Hotkey_Main(VKCode, SCCode)
    Else If ((wParam = 0x101 || wParam = 0x105) && VKCode != "vk5D")   ;  WM_KEYUP := 0x101, WM_SYSKEYUP := 0x105, AppsKey = "vk5D"
        nCode := -1, IsMod ? Hotkey_Main(VKCode, SCCode, "Up", IsMod) : ""
    Return nCode < 0 ? DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "UInt", wParam, "UInt", lParam) : 1
}

Hotkey_WindowsHookEx(State)   {
    Static Hook
    If State
        Hook := DllCall("SetWindowsHookEx" . (A_IsUnicode ? "W" : "A")
                , "Int", 13   ;  WH_KEYBOARD_LL
                , "Ptr", RegisterCallback("Hotkey_LowLevelKeyboardProc", "Fast")
                , "Ptr", DllCall("GetModuleHandle", "UInt", 0, "Ptr")
                , "UInt", 0, "Ptr")
    Else
        DllCall("UnhookWindowsHookEx" , "Ptr", Hook), Hook := "", Hotkey_Reset()
}

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

87

Re: AHK: Замена стандартного элемента управления "Hotkey"

Смысл в устранении таких недостатков:
- Буквенные клавиши сохраняются по имени
- Определяются не все клавиши клавиатуры
- Не определяются клавиши мыши и джойстиков

   Левая и правая  кнопки мыши и сейчас не определяются. Апдейт не ожидается?

88

Re: AHK: Замена стандартного элемента управления "Hotkey"

В принципе правую можно и добавить. Но как добавив левую потом деактивировать контрол, Я понятия не имею.

Для себя Вы можете в MouseKey добавьте то что нужно.


Hotkey_ExtKeyInit()  {
    MouseKey := "MButton|WheelDown|WheelUp|WheelRight|WheelLeft|XButton1|XButton2"  
    #IF Hotkey_Arr("Hook")
    #IF
    Hotkey, IF, Hotkey_Arr("Hook")
    Loop, Parse, MouseKey, |
        Hotkey, %A_LoopField%, Hotkey_PressName 
    Loop, 128
        Hotkey % Ceil(A_Index/32) "Joy" Mod(A_Index-1,32)+1, Hotkey_PressName 
    Hotkey, IF
    Return
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

89

Re: AHK: Замена стандартного элемента управления "Hotkey"

serzh82saratov пишет:

В принципе правую можно и добавить. Но как добавив левую потом деактивировать контрол, Я понятия не имею.

  А если только с модификаторами?

90

Re: AHK: Замена стандартного элемента управления "Hotkey"

Логично. Добавил в отдельный вариант.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

91 (изменено: serzh82saratov, 2014-06-28 19:21:56)

Re: AHK: Замена стандартного элемента управления "Hotkey"

teadrinker пишет:

Например, если перевести NumLock в положение On и нажать Shift+клавиша на цифровой клавиатуре, то тоже сбрасывается.

Попробовал решить проблему, ибо действительно нехорошо, что отпадает возможность их назначения, тестируем у кого как.


#SingleInstance Force
#Persistent
#NoEnv
ListLines Off
SetBatchLines -1

Ini = %A_ScriptDir%\Hotkey.ini
Gui, +AlwaysOnTop
Gui, Add, Edit, w300 Center gWriteIni vMyHotkey1   , % Hotkey_IniRead("1_MyHotkey1", "Section", Ini)
Gui, Add, Edit, Center wp gWriteIni vMyHotkey2,  % Hotkey_IniRead("1_MyHotkey2", "Section", Ini)
Gui, Add, Edit, wp Center vText
Hotkey_Init("MyHotkey1|MyHotkey2") 
Gui, Show, x111
Return 

WriteIni:
    GuiControl, %A_Gui%:, Text, % A_Gui "_" A_GuiControl " = " %A_GuiControl%
    IniWrite, % %A_GuiControl%, % Ini, Section, % A_Gui "_" A_GuiControl
    Return

Hotkey_Init(Controls)  {
    Static IsStart 
    SaveFormat := A_FormatInteger
    SetFormat, IntegerFast, H
    Loop, Parse, Controls, |
    {
        RegExMatch(A_LoopField, "S)(.*:)?\s*(.*)", D) 
        GuiControlGet, Hwnd, % (D1 = "" ? "1:" : D1) "Hwnd", %D2%
        Hotkey_Arr(Hwnd, D2, 1)
        GuiControl, %D1%+ReadOnly, %D2%
    }
    SetFormat, IntegerFast, %SaveFormat%
    If !IsStart
        Hotkey_SetWinEventHook(0x8005, 0x8005, 0, RegisterCallback("Hotkey_WinEvent", "F"), 0, 0, 0)   ;  EVENT_OBJECT_FOCUS := 0x8005
        , Hotkey_ExtKeyInit(), Hotkey_SetWindowsHookEx(), IsStart := 1
    ControlGetFocus, IsFocus, A
    ControlGet, FocusHwnd, Hwnd,, %IsFocus%, A 
    If Hotkey_Arr(FocusHwnd)
        Hotkey_WinEvent(0, 0, FocusHwnd)
    Return
}

Hotkey_Main(Param1, Param2=0, Param3=0) {
    Static OnlyMods, VarName, ControlHandle, Hotkey, KeyName
        , MCtrl, MAlt, MShift, MWin, PCtrl, PAlt, PShift, PWin, Prefix 
        , Pref := {"Alt":"!","Ctrl":"^","Shift":"+","Win":"#"}
        , Symbols := "|vkBA|vkBB|vkBC|vkBD|vkBE|vkBF|vkC0|vkDB|vkDC|vkDD|vkDE|vk41|vk42|"
                    . "vk43|vk44|vk45|vk46|vk47|vk48|vk49|vk4A|vk4B|vk4C|vk4D|vk4E|"
                    . "vk4F|vk50|vk51|vk52|vk53|vk54|vk55|vk56|vk57|vk58|vk59|vk5A|" 
 
    If Param1 = GetMod  
        Return MCtrl MAlt MShift MWin = "" ? 0 : 1 
    If Param1 = Control
    { 
        If Param2
        {
            If OnlyMods
                SendMessage, 0xC, 0, "Нет", , ahk_id %ControlHandle%
            OnlyMods := 0, ControlHandle := Param2, VarName := Param3
            If !Hotkey_Arr("Hook")
                Hotkey_Arr("Hook", 1, 1)
            SendInput {LButton Up} 
            PostMessage, 0x00B1, , , , ahk_id %ControlHandle%   ;  EM_SETSEL  
        }
        Else If Hotkey_Arr("Hook")
        {
            Hotkey_Arr("Hook", 0, 1)
            MCtrl := MAlt := MShift := MWin := "" 
            PCtrl := PAlt := PShift := PWin := Prefix := ""
            If OnlyMods
                SendMessage, 0xC, 0, "Нет", , ahk_id %ControlHandle%
        } 
        Return
    } 
    If Param1 = Mod 
    {
        IsMod := Param2
        If (M%IsMod% != "")
            Return 1
        M%IsMod% := IsMod "+", P%IsMod% := Pref[IsMod] 
    }
    Else If Param1 = ModUp 
    {
        IsMod := Param2, M%IsMod% := P%IsMod% := ""
        If (Hotkey != "")
            Return 1
    }  
    (IsMod) ? (KeyName := Hotkey := Prefix := "", OnlyMods := 1)
    : (KeyName := GetKeyName(Param1 Param2)
    ,  Hotkey := InStr(Symbols, "|" Param1 "|") ? Param1 : KeyName
    ,  KeyName := Hotkey = "vkBF" ? "/" : KeyName
    ,  Prefix := PCtrl PAlt PShift PWin, OnlyMods := 0)
    Hotkey_SetVarName(VarName, Prefix Hotkey) 
    WriteText := MCtrl MAlt MShift MWin KeyName = "" ? "Нет" : MCtrl MAlt MShift MWin KeyName
    SendMessage, 0xC, 0, &WriteText, , ahk_id %ControlHandle% 
    Return 1
    
Hotkey_PressName:  
    KeyName := Hotkey := A_ThisHotkey 
    Prefix := PCtrl PAlt PShift PWin
    OnlyMods := 0 
    Hotkey_SetVarName(VarName, Prefix Hotkey)
    WriteText := MCtrl MAlt MShift MWin KeyName  
    SendMessage, 0xC, 0, &WriteText, , ahk_id %ControlHandle%
    Return 
}

Hotkey_WinEvent(hWinEventHook, event, hwnd)   { 
    SaveFormat := A_FormatInteger
    SetFormat, IntegerFast, H
    Name := Hotkey_Arr(hwnd)
    SetFormat, IntegerFast, %SaveFormat% 
    (Name = "") ? Hotkey_Main("Control", 0) : Hotkey_Main("Control", hwnd, Name)
}


Hotkey_ExtKeyInit()  {
    MouseKey := "RButton|MButton|WheelDown|WheelUp|WheelRight|WheelLeft|XButton1|XButton2"  
    #IF Hotkey_Arr("Hook")
    #IF Hotkey_Main("GetMod") 
    #IF
    Hotkey, IF, Hotkey_Arr("Hook")
    Loop, Parse, MouseKey, |
        Hotkey, %A_LoopField%, Hotkey_PressName 
    Loop, 128
        Hotkey % Ceil(A_Index/32) "Joy" Mod(A_Index-1,32)+1, Hotkey_PressName 
    Hotkey, IF, Hotkey_Main("GetMod")
    Hotkey, LButton, Hotkey_PressName 
    Hotkey, IF
    Return
}
  
Hotkey_LowLevelKeyboardProc(nCode, wParam, lParam)  {
    Static Mods := {"vkA4":"Alt","vkA5":"Alt","vkA2":"Ctrl","vkA3":"Ctrl"
            ,"vkA0":"Shift","vkA1":"Shift","vk5B":"Win","vk5C":"Win"}
            , Numpad := "|vk23|vk28|vk22|vk25|vkc|vk2d|vk27|vk24|vk26|vk21|vk2e|"
            , SaveFormat, PrVk
    If !Hotkey_Arr("Hook")
        Return DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "UInt", wParam, "UInt", lParam)
    SaveFormat := A_FormatInteger
    SetFormat, IntegerFast, H
    VkCode := "vk" SubStr(NumGet(lParam+0, 0, "UInt"), 3)
        sc := NumGet(lParam+0, 8, "UInt") & 1, sc := sc << 8 | NumGet(lParam+0, 4, "UInt")
    SCCode := "sc" SubStr(sc, 3)
    SetFormat, IntegerFast, %SaveFormat% 
    IF (wParam = 0x100 || wParam = 0x104)   ;  WM_KEYDOWN := 0x100, WM_SYSKEYDOWN := 0x104
        (IsMod := Mods[VkCode]) ? (InStr(Numpad, "|" PrVk "|") ? (VkCode := "") : Hotkey_Main("Mod", IsMod)) : Hotkey_Main(VkCode, SCCode)
    Else IF ((wParam = 0x101 || wParam = 0x105) && VkCode != "vk5D")   ;  WM_KEYUP := 0x101, WM_SYSKEYUP := 0x105, AppsKey = "vk5D"
        nCode := -1, (IsMod := Mods[VkCode]) ? Hotkey_Main("ModUp", IsMod) : 0
    PrVk := VkCode
    Return nCode < 0 ? DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "UInt", wParam, "UInt", lParam) : 1
}

Hotkey_SetWinEventHook(eventMin, eventMax, hmodWinEventProc, lpfnWinEventProc, idProcess, idThread, dwFlags) {
    Return DllCall("SetWinEventHook" , "UInt", eventMin, "UInt", eventMax, "Ptr", hmodWinEventProc
            , "Ptr", lpfnWinEventProc, "UInt", idProcess, "UInt", idThread, "UInt", dwFlags, "Ptr")
}

Hotkey_SetWindowsHookEx()   { 
    Return DllCall("SetWindowsHookEx" . (A_IsUnicode ? "W" : "A")
        , "Int", 13   ;  WH_KEYBOARD_LL := 13
        , "Ptr", RegisterCallback("Hotkey_LowLevelKeyboardProc", "Fast")
        , "Ptr", DllCall("GetModuleHandle", "UInt", 0, "Ptr")
        , "UInt", 0, "Ptr")
}

Hotkey_SetVarName(Name, Value) {
    Global
    %Name% := Value
} 

Hotkey_Arr(Key, Value="", Write=0)   {
    Static Arr := {}
    If !Write
        Return Arr[Key]
    Arr[Key] := Value 
}

    ; -------------------------------------- Format func --------------------------------------

Hotkey_IniRead(Key, Section, Path) {
    IniRead, Key, % Path, % Section, % Key, % A_Space
    Return Hotkey_FormatHKToStr(Key)
}

Hotkey_FormatHKToStr(Key) {
    RegExMatch(Key, "S)^([\^\+!#]*)\{?(.*?)}?$", K)
    If (K2 = "")
        Return "Нет"
    If InStr(K2, "vk")
        KeyName := K2 = "vkBF" ? "/" : GetKeyName(K2) 
    Else 
        KeyName := K2
    Return (InStr(K1,"^")?"Ctrl+":"")(InStr(K1,"!")?"Alt+":"")
            . (InStr(K1,"+")?"Shift+":"")(InStr(K1,"#")?"Win+":"") KeyName
}

Hotkey_FormatStrToHK(Str) {
    Static Buttons := ":ж:`;:|vkBA| :=:|vkBB| :б:,:|vkBC| :-:|vkBD| :ю:.:|vkBE|"
        . ":/:|vkBF| :``:ё:|vkC0| :х:[:|vkDB| :\:|vkDC| :ъ:]:|vkDD| :э:':|vkDE|"
        . ":A:|vk41| :B:|vk42| :C:|vk43| :D:|vk44| :E:|vk45| :F:|vk46| :G:|vk47|"
        . ":H:|vk48| :I:|vk49| :J:|vk4A| :K:|vk4B| :L:|vk4C| :M:|vk4D| :N:|vk4E|"
        . ":O:|vk4F| :P:|vk50| :Q:|vk51| :R:|vk52| :S:|vk53| :T:|vk54| :U:|vk55|"
        . ":V:|vk56| :W:|vk57| :X:|vk58| :Y:|vk59| :Z:|vk5A|"

    If (Str = "Нет" || Str = "" || SubStr(Str, 0) ~= "\+|\s+")
        Return ""
    RegExMatch(Str, "S)(.*\+)?(.*)", K)
    If (StrLen(K2) = 1)
        RegExMatch(Buttons, "Si)\Q:" K2 ":\E.*?\|(.*?)\|", vk)
    Return (InStr(K1,"Ctrl+")?"^":"")(InStr(K1,"Alt+")?"!":"")
        . (InStr(K1,"Shift+")?"+":"")(InStr(K1,"Win+")?"#":"")(vk1 = "" ? K2 : vk1)
}

Hotkey_FormatHKToSend(Key, Section = "", Path = "") {
    If (Section != "")
        IniRead, Key, % Path, % Section, % Key, % A_Space
    Return RegExReplace(Key, "S)[^\^!\+#].*", "{$0}")
}

Hotkey_GetVar(VarName)  {
    RegExMatch(VarName, "S)(.*:)?\s*(.*)", D) 
    GuiControlGet, Hwnd, % (D1 = "" ? "1:" : D1) "Hwnd", % D2
    ControlGetText, Text,, ahk_id %Hwnd% 
    Return Hotkey_FormatStrToHK(Text)
}

Esc::
GuiClose:
GuiEscape:
    ExitApp

Изменения коснулись только функции Hotkey_LowLevelKeyboardProc.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

92

Re: AHK: Замена стандартного элемента управления "Hotkey"

У меня так же сбрасывается.

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

93

Re: AHK: Замена стандартного элемента управления "Hotkey"

Есть мысли?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

94

Re: AHK: Замена стандартного элемента управления "Hotkey"

У меня подобные сочетания и не назначаются:

+Numpad4::MsgBox 

— не работает.

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

95

Re: AHK: Замена стандартного элемента управления "Hotkey"

Ну это само собой, такого хоткея и нет.
Вместо него:

NumpadLeft::MsgBox 

Тут главный вопрос пока, почему не фиксируется у тебя?
Есть и ещё одна заморочка, но это потом, раз уж этот код не везде работает.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

96

Re: AHK: Замена стандартного элемента управления "Hotkey"

Так а есть ли смысл это копать, если всё равно применить нельзя? Почему не фиксируется — не знаю, уже забыл, как это всё работает, сейчас заново лень разбираться.

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

97

Re: AHK: Замена стандартного элемента управления "Hotkey"

Почему не фиксируется — не знаю, уже забыл, как это всё работает

при физическом зажатии +Numpad4 аппаратно посылается NumpadLeft и Shift ап.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

98

Re: AHK: Замена стандартного элемента управления "Hotkey"

А ты-то какого результата хочешь добиться?

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

99

Re: AHK: Замена стандартного элемента управления "Hotkey"

В принципе всё хорошо, но у тебя на машине не катит, Ты говоришь.
Я, даже не знаю. В принципе результат мне боку.
Ради общего блага наверное.
Для начала если у тебя не фиксируются данные кнопки, то хоть это решить.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

100

Re: AHK: Замена стандартного элемента управления "Hotkey"

Наверное, не имеет смысла, если всё равно нельзя такую горячую клавишу назначить.

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