Re: AHK: Замена стандартного элемента управления "Hotkey"
Немного не так. Перечитай 97.
Ну и например
^+Numpad4
это ведь равно
^NumpadLeft
Win10x64 AhkSpy, Hotkey, ClockGui
Вы не вошли. Пожалуйста, войдите или зарегистрируйтесь.
Немного не так. Перечитай 97.
Ну и например
^+Numpad4
это ведь равно
^NumpadLeft
Не пойму твою мысль. NumpadLeft и ^NumpadLeft нормально определяются и назначаются.
Давай сначала.
У меня так же сбрасывается.
Держишь Shift нажимаешь Numpad4, и
у тебя остаётся
Shift+
или
Shift+Numpad4
или
NumpadLeft
Если Num Lock в положении On, тогда при удержании Shift и нажатии Numpad4 запись Shift+ сбрасывается и появляется NumpadLeft.
Если Num Lock в положении Off, тогда остаётся Shift+NumpadLeft.
Значит всё работает так, как и должно.
Наверное, не имеет смысла, если всё равно нельзя такую горячую клавишу назначить.
Хотя Ты прав, ни к чему это всё.
Хотел добавить в свой буфер обмена, но столкнулся с таким недостатком. Смотрим функцию SetWindowsHookEx(), секцию Remarks:
Before terminating, an application must call the UnhookWindowsHookEx function to free system resources associated with the hook.
Если этого не далать, будет засоряться память, как я понимаю. По-моему, лучше было бы, если бы данный хук устанавливался только при активации связанного контрола, и удалялся при его деактивации.
Кроме того, неплохо было бы добавить возможность указывать связанный контрол через его хэндл, чтобы избежать сложностей при одинаковых названиях переменных контролов в разных окнах.
Ещё заметил у тебя в коде такую странную функцию:
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)
}
В параметрах там hWinEventHook и event, которые, однако, в дальнейшем не используются.
По-моему, лучше было бы, если бы данный хук устанавливался только при активации связанного контрола, и удалялся при его деактивации.
На практике получалось так, что при быстрых сменах фокуса хук неснимался, либо не устанавливался.
Если этого не далать, будет засоряться память, как я понимаю.
Незамечал, такой же подход используется и в AhkSpy, он долго висел в памяти, и хук не снимался.
Кроме того, неплохо было бы добавить возможность указывать связанный контрол через его хэндл, чтобы избежать сложностей при одинаковых названиях переменных контролов в разных окнах.
Это обсуждали, сделано максимально подобно с обычным контролом, а сама проблема решена в библиотеке, там где то есть в описании.
В параметрах там hWinEventHook и event, которые, однако, в дальнейшем не используются.
Ну так нужен ведь только третий параметр, а первые два надо же как то назвать.
Ну так нужен ведь только третий параметр, а первые два надо же как то назвать.
А, с этим ясно.
Это обсуждали, сделано максимально подобно с обычным контролом, а сама проблема решена в библиотеке, там где то есть в описании.
Так а почему всё-таки не сделать вариант с указанием через хэндл? Чтоб можно было и так, и так.
Незамечал, такой же подход используется и в AhkSpy, он долго висел в памяти, и хук не снимался.
Тут не понял. Ты цитату-то из MSDN прочёл? Там говорится, что перед выходом из приложения хук должен сниматься, чтобы освободить системные ресурсы, а в коде это никак не учитывается. Если в AhkSpy тоже этого не делается, значит это ошибка и нужно исправить.
На практике получалось так, что при быстрых сменах фокуса хук неснимался, либо не устанавливался.
Может просто ошибка была?
Ты цитату-то из MSDN прочёл? Там говорится, что перед выходом из приложения хук должен сниматься, чтобы освободить системные ресурсы
Не читал, ибо было исчерпывающе:
По-моему, лучше было бы, если бы данный хук устанавливался только при активации связанного контрола, и удалялся при его деактивации.
Тут явно не имеется ввиду снятие хука именно при закрытии скрипта. Может снова что то я не понял.
Так а почему всё-таки не сделать вариант с указанием через хэндл? Чтоб можно было и так, и так.
Не знаю, тебе лично оно не нужно, а пользователей нет. Да и одинаковые имена контролов сами по себе вносят путаницу в код, и думаю любой программер во второй раз на это наступит.
Не читал
Ну так а почему бы не прочитать?
А это читал:
перед выходом из приложения хук должен сниматься, чтобы освободить системные ресурсы
У тебя это делается? Смотри мой пример, метка Exit.
У тебя это делается?
Это понял что упустил. Просто смутило:
лучше было бы, если бы данный хук устанавливался только при активации связанного контрола
почему это лучше?
Ну потому, что пользователю не нужно было бы заботиться о снятии его при выходе из приложения. Сейчас пример попробую написать по установке/снятию хука при активации контрола.
Сейчас пример попробую написать по установке/снятию хука при активации контрола.
Так это не требуется, я же писал, что это и был первоначальный метод основанный на каком то из твоих скриптов, кажется который для определения скан кодов.
А в чём проблема была?
На практике получалось так, что при быстрых сменах фокуса хук неснимался, либо не устанавливался.
Ну так я и попробую написать пример, в котором всё работает нормально.
Всё работает:
global hEdit1, hEdit2, hHookKeybd
Gui, Add, Edit, hwndhEdit1
Gui, Add, Edit
Gui, Add, Edit, hwndhEdit2
Gui, Show
hHookKeybd := SetKeybdHook()
OnMessage(0x111, "WM_COMMAND")
Return
WM_COMMAND(wp, lp)
{
static EN_SETFOCUS := 0x100, EN_KILLFOCUS := 0x200
if (lp != hEdit1)
Return 0
if (wp >> 16 = EN_SETFOCUS && !hHookKeybd)
hHookKeybd := SetKeybdHook()
if (wp >> 16 = EN_KILLFOCUS)
DllCall("UnhookWindowsHookEx", Ptr, hHookKeybd), hHookKeybd := ""
Return 0
}
SetKeybdHook()
{
Return DllCall("SetWindowsHookEx"
, 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, vk, sc
if (wParam = WM_KEYDOWN)
{
SetFormat, IntegerFast, H
vk := NumGet(lParam + 0, "UInt") . ""
ext := NumGet(lParam + 8, "UInt") & 1
sc := NumGet(lParam + 4, "UInt") | ext << 8 . ""
SetTimer, ShowChar, -10
}
Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam)
ShowChar:
Control, EditPaste, % GetKeyName("vk" vk " sc" sc),, ahk_id %hEdit2%
Return
}
Когда в фокусе первый Edit, хук устанавливается (символы передаются в третий), когда не в фокусе — снимается (символы не передаются). Не зависит от скорости снятия/установки фокуса.
Кроме того, можно отслеживать появление/скрытие/разрушение связанного контрола.
Всё работает:
В таком виде да. Но для задачи требуется намного больше действий, и их выполнение видимо создаёт иногда затруднения. И надо довольно долго тестировать, чтобы увидеть их.
Каких действий? Речь шла только об установке/снятии хука по событию получения/потери контролом фокуса.
Кучи действий для определения всего, что нужно прописать в контрол. Все они висят внутри хука. В случаях когда нажимаешь кнопку и сразу убираешь фокус с контрола, случалось что хук не снимался.
Выполнять эти действия в хуке по таймеру - не вариант, тогда часто пропускаются некоторые нефизические нажатия.
Кстати есть аналог OnExit на WinAPI?
Кучи действий для определения всего, что нужно прописать в контрол. Все они висят внутри хука.
Куча, в смысле — несколько десятков тысяч? Да и зачем в контрол что-то прописывать при снятии фокуса, просто остаётся, как есть. Не уверен на 100%, но скорее всего дело в некорректном коде.
Кстати есть аналог OnExit на WinAPI?
Точно не знаю, как реализован этот механизм (должно быть хук какой-то), но если писать что-то своё, скорее всего, будет конкурировать с родным OnExit. Да, со снятием хука при выходе из приложения будет проблема, если оформлять в виде функции.
Куча, в смысле — несколько десятков тысяч? Да и зачем в контрол что-то прописывать при снятии фокуса, просто остаётся, как есть. Не уверен на 100%, но скорее всего дело в некорректном коде
Те варианты, что у тебя в начале темы, в них точно также иногда не снимался хук.
Ну так я же не говорил, что тот мой код идеален!
Можно внести ещё одно усовершенствование.
Заметьте, если Hotkey задавать в разных окнах, то во всех GUI, имеющих номер этот скрипт работать не будет.
Было бы здорово внести дополнения, учитывающие из какого GUI отправляется нажатие.
Заранее спасибо!
А вы запускали - Код для иллюстрации некоторых воможностей?
Давно когда-то пробовал, но забыл. Сейчас вижу, что работает, но пока разобраться не могу.
Окно определяется с помощью переменной "A_Gui".
И если есть необходимость понимать какое окно, то ведь имена переменных контролов заранее известны.
Что-то у меня не получается правильно обработать прочитанный из .ini хоткей, и назначить его.
В каком виде это надо сделать?
Даже вот так не получается.
MyHotkey1_new := Hotkey_GetVar("MyHotkey1")
Hotkey,%MyHotkey1_new%,PPG
Так в ини файл хоткей записывается в виде АНК синтаксиса. Надо просто использовать то, что в ини файле, просто прочитать.
Понял, спасибо. Пытался использовать сразу, но .ini правильнее.
Заметил, что все мышиные кнопки, включая комбинации с модификаторами, срабатывают при нажатии, а не при отпускании, как это должно быть у мыши.
Можно это как-то исправить?
А, почему так должно быть у мыши?
Как я уже написал, потому что так она функционирует обычно.
Иначе это "сюрприз" для пользователя. Ну, как сделать окно приложения треугольным. Даже, если всё работает отлично, непривычность простого пользователя напрягает и отталкивает.
Для примера. Допустим вы хотите закрыть окно, нажали на крестик, а потом вспомнили, что нужно ещё что сделать. Вы просто привычно отведёте курсор в сторону, отпустите кнопку и сделаете то, что вам нужно в окне, которое так и не закрылось. А если сработает при нажатии, то окна уже не будет.
Стояла у меня как-то "Avira", так там главное окно закрывалось на Down. Иногда очень бесило, если влез в 35-ю по глубине настройку, там что-то изменил, но какой-то штрих забыл, и тут второпях нажал на крестик и ... начинай сначала откапывать эту 35-ю настройку.
Вообще новый элемент, которому посвящена эта тема - штука прекрасная, за что большое спасибо. Но упомянутый момент сильно выбивается из привычных сценариев, что мне кажется неверным.
непривычность простого пользователя напрягает и отталкивает.
Так в чём непривычность? Во всех привычных формах, хоткей назначается именно на нажатие.
Для примера. Допустим вы хотите закрыть окно, нажали на крестик, а потом вспомнили, что нужно ещё что сделать. Вы просто привычно отведёте курсор в сторону, отпустите кнопку и сделаете то, что вам нужно в окне, которое так и не закрылось. А если сработает при нажатии, то окна уже не будет.
Пример неверный. Тут сначала регистрируется нажатие над контролом, и уже далее отпускание над ним же и выполнение действия. То есть аналог выше описанного тобой действия на псевдо коде:
RButton::
Проверка что под курсором нужный контрол
Если ложь то, нажатие RButton (а лучше что хоткей не действителен, читай справку про: "Hotkey, If [, Expression]")
Ожидание отпускания RButton
Проверка что под курсором нужный контрол
Если правда то, выполнение нужного действия
То есть изначальная привязка как раз к нажатию кнопки мыши.
Как я понял, у тебя речь про то, что надо бы добавить хоткеи типа: "RButton Up", но в рамках замены стандартного элемента управления "Hotkey" это невозможно, тут или одно или другое. А привычным считается как раз действия по нажатию на кнопку (пусть даже мыши), а не при её отпускании.
Можно ещё попробовать вникнуть в первый пост этой темы, и сделать всё что душе угодно, но там немного мудрёно.
Хотя если приложить немного фантазии:
IniRead, MyHotkey, % Path, % Section, % Key
if MyHotkey contains LButton,RButton
Hotkey,%MyHotkey% Up,PPG
Else
Hotkey,%MyHotkey%,PPG
то это можно сделать под себя в процедуре назначения хоткеев на старте скрипта, при чтении из ини файла.
Добавил необходимую функцию и описание по вопросу с OnExit.
Объединил обе версии библиотек, в опциях можно выбрать какие кнопки, кроме клавиатурных, ещё требуются.
Тем кто пользуется, советую перечитать описание полностью.
А привычным считается как раз действия по нажатию на кнопку (пусть даже мыши), а не при её отпускании.
В теории - несомненно. Для пользователя - категорически не согласен. Если пользователь действует мышью, то всё должно работать как у мыши, хоть кнопка и используется как хоткей.
Я понял, что осуществить это сложно. Жаль.
Так простой вариант предложен в 138. Чего именно нужно добится, несовсем понятно.
Надо привести свой код, и подробно расписать что нужно, и что не получается. Без конкретики, это не то чтобы сложно, а не возможно.
Ну, в принципе, наверное, да можно вписать такое как в 138 после каждого чтения хоткеев из ini. Кстати с Lbutton c модификаторами всё равно при нажатии сработает.
Кстати с Lbutton c модификаторами всё равно при нажатии сработает.
Нет.
+!Lbutton up::MsgBox
Если я горячих клавиш много, я и не хочу производить сразу производить запись в ini, как лучше преобразовать
WriteIni:
IniWrite, % %A_GuiControl%, % Ini, Section, % A_Gui "_" A_GuiControl
ToolTip % A_Gui ":" A_GuiControl " = " %A_GuiControl%
Return
Я понимаю, что надо всё расположить до "Submit" в подпрограмме обработки "Ok", но как вызывать все данные из нужных Edit?
Я ничё не понял.
В предложенном скрипте изменения сразу вносятся в ini. Как сохранить возможность отмены сразу всех изменений? Надо как-то по другому вписывать в ini. Submit после "Ok" отпадает сразу. Значит надо как-то взять информацию из всех "Edit" с горячими клавишами. Как это лучше всего сделать в общем случае, а не только одного или для четырёх идущих подряд контролов.
одноимённые ассоциированные переменные будут содержать код (в виде "^#+!vk4F") нажатых кнопок.
А кто же вас заставляет записывать сразу?
#NoEnv
ListLines Off
SetBatchLines -1
#SingleInstance Force
OnExit, GuiClose
Ini = %A_ScriptDir%\Hotkey.ini
Gui, +AlwaysOnTop
Gui, Add, Edit, Center w300 vMyHotkey1, % Hotkey_IniRead("MyHotkey1", "Section", Ini)
Gui, Add, Edit, Center wp y+10 vMyHotkey2, % Hotkey_IniRead("MyHotkey2", "Section", Ini)
Gui, Add, Edit, Center wp y+10 vMyHotkey3, % Hotkey_IniRead("MyHotkey3", "Section", Ini)
Gui, Add, Edit, Center wp y+10 vMyHotkey4, % Hotkey_IniRead("MyHotkey4", "Section", Ini)
Gui, Add, Button, y+10 x112 gSave, === ok ===
Controls = MyHotkey1|MyHotkey2|MyHotkey3|MyHotkey4
Hotkey_Init(Controls, "MLRJ")
Gui, Show
Return
Save:
Loop, parse, Controls, |
IniWrite, % Hotkey_GetVar(A_LoopField), % Ini, Section, % A_LoopField
Return
GuiClose:
Hotkey_Exit()
ExitApp
Too many parameters passed to function.
Specifically: Hotkey_Init(Controls, "MLRJ")
Поправил пример, всё таки есть для этого необходимая функция. Без неё если есть 4 назначенных хоткея, а изменить после старта только один, то остальные запишутся как пустые. Думаю логично поправить библиотеку, чтобы при первом чтении переменная тоже назначалась.
У меня нет ошибки, привидите коды скрипта и библиотеки.
Думаю логично поправить библиотеку, чтобы при первом чтении переменная тоже назначалась.
Обновил библиотеку. См. описание Hotkey_IniRead.
Совместимо со старыми скриптами.
Т.е. теперь можно и так:
#NoEnv
ListLines Off
SetBatchLines -1
#SingleInstance Force
OnExit, GuiClose
Ini = %A_ScriptDir%\Hotkey.ini
Gui, +AlwaysOnTop
Gui, Add, Edit, Center w300 vMyHotkey1, % Hotkey_IniRead("MyHotkey1", "Section", Ini, 1)
Gui, Add, Edit, Center wp y+10 vMyHotkey2, % Hotkey_IniRead("MyHotkey2", "Section", Ini, 1)
Gui, Add, Edit, Center wp y+10 vMyHotkey3, % Hotkey_IniRead("MyHotkey3", "Section", Ini, 1)
Gui, Add, Edit, Center wp y+10 vMyHotkey4, % Hotkey_IniRead("MyHotkey4", "Section", Ini, 1)
Gui, Add, Button, y+10 x112 gSave, === ok ===
Controls = MyHotkey1|MyHotkey2|MyHotkey3|MyHotkey4
Hotkey_Init(Controls, "MLRJ")
Gui, Show
Return
Save:
Loop, parse, Controls, |
IniWrite, % %A_LoopField%, % Ini, Section, % A_LoopField
Return
GuiClose:
Hotkey_Exit()
ExitApp
Спасибо, только попробуйте назначить все четыре, а потом запустить ещё раз, изменить только одну горячую клавишу и после "Ok" заглянуть в ini.
Ну и что там будет не так?
У меня все значения, кроме свеженазначенных в ini очищаются. У Вас не так?
Так вы библиотеку обновили? Я же в 151 написал.
Конечно. До этого вообще не запускалось. Ах, код самого скрипта не поменял, думал это тот же. Извиняюсь, буду разбираться.
Не понимаю как так получается. Правильно записывается только изменённое значение. Все остальные в ini вписываются как буквы, а не как vk. Причём только в моём скрипте. В вашем всё работает правильно. Менял 20 раз кодировки, компоновал переменные в строку, разбивал на части, преобразовывал после каждого Edit, но ничего не добился кроме того, что понял, что
1. уже на стадии чтения из ini ошибка.
Gui, Add, Edit, Center wp y+10 vMyHotkey4, % Hotkey_IniRead("MyHotkey4", "Section", Ini, 1)
Hotkey_Init("MyHotkey4", "MLRJ")
У меня тут "MyHotkey4" - пустой, а у Вас vk...
2.при отправке на запись свежеизменённая горячая клавиша записывается как vk..., остальные как буквы,"Win" и тому подобное, как это видится в Edit в Gui.
Что может так влиять?
Причём только в моём скрипте. В вашем всё работает правильно.
Обычно в таких случаях сразу приводят весь свой код.
Что может так влиять?
GuiSubmit?
Если по вашему никак не удаётся перед сохранением избежать GuiSubmit, то я вам уже предлагал этот вариант.
ап: Подправил описание библиотеки, думаю по этому вопросу станет более понятно.
GuiSubmit при закрытии окна Gui сейчас вообще не использую. С Hotkey_GetVar вообще ничего не пишется в ini.
Буду удалять куски кода пока не останется одна строка или пока не найду причину.
Что должно вписываться в Hotkey_GetVar, если у меня несколько таких окон GUI с горячими переменными?
Gui, 2:Add, Edit, Center w300 vMyHotkey1, % Hotkey_IniRead("MyHotkey1", "Section", Ini)
В Hotkey_Init я вписываю так:
Hotkey_Init("2:MyHotkey1|2:MyHotkey2|2:MyHotkey3|2:MyHotkey4", "MLRJ")
Правильно?
Что должно вписываться в Hotkey_GetVar
Hotkey_GetVar(VarName)
VarName - Имя переменной вида "MyHotkey" или "GuiName:MyHotkey".
Извлекает содержимое контрола Edit, типа "Ctrl+Win+Shift+Alt+O", и возвращает в виде "^#+!vk4F".
Один контрол в кавычках, например:
"2:MyHotkey2"
Да, так отлично работает, спасибо. Непонятно что там получалось с Submit, но потом как нибудь разберусь.
GuiSubmit при закрытии окна Gui сейчас вообще не использую.
???
Непонятно что там получалось с Submit, но потом как нибудь разберусь.
(или например после применения GuiSubmit, тогда переменным назначается содержимое Edit)
Возник вопрос. В коде "Hotkey.ahk" несколько раз присутствует слово "Нет". Как будет это отображаться в поле Edit, если виндовс не на русском языке: белорусский, польский, испанский?
Не пробовал, проверьте удалив русский язык в ОС.
В коде "Hotkey.ahk" несколько раз присутствует слово "Нет". Как будет это отображаться в поле Edit, если виндовс не на русском языке?
Я насчитал 5 раз. Сомневаюсь, что оно само переведётся на польский.
Так что если нет возможности или желания определить, например из ресурсов, соответствующее слово для языка системы, надо хотя бы использовать его в скрипте через константу для упрощения локализации.
Сомневаюсь, что оно само переведётся на польский.
Да уж само точно не переведётся. Главное чтобы в наборе символов на ПК, были русские, наверное...
Можно самому заменить все "Нет" на что-то другое, например на "no" или пустые кавычки ""? Не повлияет ли это на работу скрипта?
Нет ли у Вас желания заменить код на другой, где будет использоваться более универсальное "no"?
У меня надобности нет, а вы заменяйте.
Если я заменю все "Нет" на что-то другое, например на "no" или пустые кавычки "", не повлияет ли это на работу скрипта?
Никак "Нет".
Обновил обе библиотеки.
Страховка от залипания хука и пропуска нажатий при привязке "длинной" подпрограммы.
В библиотеке Hotkey на 198 строке в функции Hotkey_Arr вы можете изменить текст который выводится при отсутствии нажатых клавиш.
Static Arr := {TipNo:"Нет"}
Или вы можете её изменять при старте скрипта, перед запуском других функций библиотеки:
Hotkey_Arr("TipNo", "пусто")
Новый вариант:
Опционально добавлено определение левых и правых модификаторов.
Переменные контролов могут быть локальны.
Левую кнопку мыши теперь можно назначить и без модификаторов, нужно просто удерживать правую кнопку перед нажатием левой.
Опция S - Определять только одну нажатую клавишу, то есть без комбинации с модификаторами.
Опция E - Выводить имена символьных клавиш только как при английской раскладке.
Не нашел информации о том, кому этот инструмент может быть полезен. Поэтому, хотел бы поинтересоваться, он найдет свое применение только у разработчика скриптов или же в т.ч. у их активных пользователей? Попробовал запустить код из последнего поста, но получил ошибку.
Gui, Add, Edit, w300 Center gWriteIni vMyHotkey1, % Hotkey_IniRead("1_MyHotkey1", "Section", Ini)
"Call to nonexistent function."
в т.ч. у их активных пользователей
Да
"Call to nonexistent function."
Нужно #include библиотеку в скрипт или копировать файл библиотеки в папку библиотек (не знаю где она, не пользуюсь).
Alectric, файл библиотеки нашел, извиняюсь. Пожалуйста, опишите цель использования простым языком. Т.к. описание работы без описания цели использования, к сожалению, для меня говорит о малом.
Это расширенная версия элемента управления Hotkey.
Известно, что встроенный элемент управления GUI - "Hotkey" имеет большие ограничения по количеству определяемых клавиш.
В таком случае, попробую разобраться.
Не нашел информации о том, кому этот инструмент может быть полезен.
Вот последний пример. Кстати там же можете спросить у ТС как он запустил код, чаще всего новички друг друга лучше понимают.
Пожалуйста, опишите цель использования простым языком. Т.к. описание работы без описания цели использования, к сожалению, для меня говорит о малом.
Так а для чего тогда вы нашли эту тему?
Попробовал запустить код из последнего поста
Я удалил тот пост, код там рабочий, но если будете использовать библиотеку, то лучше сразу привыкать к новой версии, она более функциональна.
Поэтому, хотел бы поинтересоваться, он найдет свое применение только у разработчика скриптов или же в т.ч. у их активных пользователей?
Для разработчиков первый пост этой темы, а библиотека подразумевалась для всех. Само собой для того чтобы освоить новую (тем более первую) для себя библиотеку, потребуются усилия.
Новые изменения:
Теперь для каждого контрола указываются свои опции.
teadrinker, по вопросу своего OnExit.
Как такой костыль:
Func() {
Static mem := New OnExit
}
class OnExit
{
__Delete() {
MsgBox % A_ThisFunc
}
}
Return
Получается что даже не требует (от пользователя) предварительного вызова функций.
Я уже, к сожаленью, потерял нить. Но что касается OnExit, то теперь можно прописывать их сколько угодно в виде функций в любом месте скрипта, и даже указывать приоритет выполнения.
А да, забыл про изменения, хотя помнится что читал. Но...
Я уже, к сожаленью, потерял нить.
Суть была в том что пользователь может отменить мой вызов метки, указав после свой OnExit. В принципе сейчас это тоже возможно, я пишу:
OnExit("Hotkey_Exit")
а после этого пользователь:
OnExit("Hotkey_Exit",0)
хотя конечно это уже мало вероятно.
Думаю, такой вероятностью можно спокойно пренебречь.
Так и сделал, добавил в библиотеку OnExit.
Вы не могли бы привести пример минимального скрипта, позволяющего установить пару хоткеев и запускающего по ним какой-нибудь MsgBox? "иногда приходится писать знакомым небольшие скрипты" - что-то такое. Ссылка из 182 сообщения ведет на нерабочий пример (По крайней мере в последней версиии Hotkey.ahk нет ф-ии Hotkey_ValueFromName() ).
Пример в описании показывает GUI, определяющий нажатые кнопки и записывающий их в ini.
Установился хоткей или нет? Если установился, почему ничего не запускает?
Или нужно использовать стандартный элемент Hotkey, а библиотека только для удобного сохранения/представления в GUI?
Я конечно прошу прощения за свою тупость и лень, но хочется сразу начать использовать, а уж потом разбираться в 26 функциях библиотеки.
Пример в описании показывает GUI, определяющий нажатые кнопки и записывающий их в ini.
Всё верно, большего и не требуется.
Установился хоткей или нет?
Нет.
Или нужно использовать стандартный элемент Hotkey, а библиотека только для удобного сохранения/представления в GUI?
Так и стандартный элемент Hotkey только для этого... Нет?
Приведите свой минимальный код установки хоткеев со стандартным элементом Hotkey, я вам переделаю под библиотеку.
serzh82saratov
В примере ниже создается окно, в котором можно задать хоткей (не важно куда и как он сохраняется) так же есть кнопка сброса. Подскажите пожалуйста. Как обновить переменную в GUI не перезапуская само окно.
modkey1 = !sc28
Gui, Add, Edit, hwndhmodkey1, % Hotkey_HKToStr(modkey1)
Gui, Add, Button, Reset
Gui, Show
Return
ButtonReset:
modkey1 = sc26
Return
Да, нужно такое добавить, модифицировал Hotkey_Set, кстати прочитайте про неё, в случаях когда есть кнопка "сохранить", назначать отображение лучше ей, если по какой-то причине не используется Hotkey_Read.
modkey1 = !sc28
Gui, Add, Edit, hwndhmodkey1 r1 w222, % Hotkey_Set("modkey1", modkey1)
Gui, Add, Button, , Reset
Hotkey_Register(["modkey1",hmodkey1,"KMLRJD"])
Gui, Show
Return
ButtonReset:
modkey1 := "sc26"
Hotkey_Set("modkey1", modkey1)
Return
Совсем запутался, не могу сохранения настроить. Сброс сохраняет, а заданный хоткей не сохраняет. В чем проблема?
modkey1 = !sc28 Gui, Add, Edit, hwndhmodkey1 r1 w222, % Hotkey_Set("modkey1", modkey1) Gui, Add, Button, , Save Gui, Add, Button, , Reset Hotkey_Register(["modkey1",hmodkey1,"KMLRJD"]) Gui, Show Return ButtonSave: IniWrite, % modkey1, % PathIni, ModKey, modkey1 Return ButtonReset: modkey1 := "sc26" Hotkey_Set("modkey1", modkey1) Return
А кто сказал что ваша переменная modkey1 будет назначаться в библиотеке?
ButtonSave:
Hotkey_IniWrite("modkey1", "ModKey", PathIni)
В описании есть только понятие связанного имени, к переменным оно не имеет отношения.
Так же как и в вашем коде переменная и её название не имеет смысла.
Gui, Add, Edit, hwndhmodkey1 r1 w222, % Hotkey_Set("modkey1", "!sc28")
Gui, Add, Button, , Save
Gui, Add, Button, , Reset
Hotkey_Register(["modkey1",hmodkey1,"KMLRJD"])
Gui, Show
Return
ButtonSave:
Hotkey_IniWrite("modkey1", "ModKey", PathIni)
Return
ButtonReset:
Hotkey_Set("modkey1", "sc26")
Return
Часто при нескольких полях ввода требуется чтобы хоткеи в них не повторялись.
Сделал тестовую версию, в опциях контрола указываем G и сразу за ним номер группы. Если вопрос интересен, прошу протестировать и отписатся.
Hotkey_Register(Controls*) {
Static IsStart
Local k, v, g, g1
For k, v in Controls
{
Hotkey_ID(v[2], v[1]), Hotkey_ID(v[1], v[2])
Hotkey_Options(v[2], v[3] = "" ? "K" : v[3])
Hotkey_Value(v[2], Hotkey_Value(v[1]))
PostMessage, 0x00CF, 1, , , % "ahk_id" v[2] ; EM_SETREADONLY
If RegExMatch(v[3], "i)G(\d+)", g)
Hotkey_Group("Set", v[1], g1)
}
If IsStart
Return Hotkey_IsRegFocus()
#HotkeyInterval 0
Hotkey_SetWinEventHook(0x8005, 0x8005, 0, RegisterCallback("Hotkey_EventFocus", "F"), 0, 0, 0) ; EVENT_OBJECT_FOCUS := 0x8005
Hotkey_InitHotkeys(), Hotkey_IsRegFocus(), IsStart := 1
}
Hotkey_Main(Param1, Param2 = "") {
Static OnlyMods, ControlHandle, Hotkey, KeyName, K := {}
, Prefix := {"LAlt":"<!","LCtrl":"<^","LShift":"<+","LWin":"<#"
,"RAlt":">!","RCtrl":">^","RShift":">+","RWin":">#"
,"Alt":"!","Ctrl":"^","Shift":"+","Win":"#"}
, EngSym := {"sc2":"1","sc3":"2","sc4":"3","sc5":"4","sc6":"5","sc7":"6"
,"sc8":"7","sc9":"8","scA":"9","scB":"0","scC":"-","scD":"="
,"sc10":"Q","sc11":"W","sc12":"E","sc13":"R","sc14":"T","sc15":"Y"
,"sc16":"U","sc17":"I","sc18":"O","sc19":"P","sc1A":"[","sc1B":"]"
,"sc1E":"A","sc1F":"S","sc20":"D","sc21":"F","sc22":"G","sc23":"H"
,"sc24":"J","sc25":"K","sc26":"L","sc27":"`;","sc28":"'","sc29":"``"
,"sc2B":"\","sc2C":"Z","sc2D":"X","sc2E":"C","sc2F":"V","sc30":"B"
,"sc31":"N","sc32":"M","sc33":",","sc34":".","sc35":"/"}
Local IsMod, Text
If Param1 = GetMod
Return K.MLCtrl K.MRCtrl K.MLAlt K.MRAlt K.MLShift K.MRShift K.MLWin K.MRWin K.MCtrl K.MAlt K.MShift K.MWin
If Param2
{
If OnlyMods
{
SendMessage, 0xC, 0, "" Hotkey_Arr("Empty"), , ahk_id %ControlHandle%
OnlyMods := 0, K := {}
}
ControlHandle := Param2
Hotkey_Arr("Hook", Hotkey_Options(ControlHandle))
PostMessage, 0x00B1, -1, -1, , ahk_id %ControlHandle% ; EM_SETSEL
}
Else If Hotkey_Arr("Hook")
{
Hotkey_Arr("Hook", 0), K := {}
If OnlyMods
SendMessage, 0xC, 0, "" Hotkey_Arr("Empty"), , ahk_id %ControlHandle%
SetTimer, Hotkey_IsRegFocus, -200
}
Return
Hotkey_Mods:
If InStr(Hotkey_Arr("Hook"), "S")
GoTo Hotkey_View
IsMod := InStr(Hotkey_Arr("Hook"), "D") ? A_ThisHotkey : SubStr(A_ThisHotkey, 2)
If (K["M" IsMod] != "")
Return
K["M" IsMod] := IsMod "+", K["P" IsMod] := Prefix[IsMod]
GoTo Hotkey_ViewMod
Hotkey_ModsUp:
If InStr(Hotkey_Arr("Hook"), "S")
Return
IsMod := InStr(Hotkey_Arr("Hook"), "D") ? SubStr(A_ThisHotkey, 1, -3) : SubStr(A_ThisHotkey, 2, -3)
K["M" IsMod] := "", K["P" IsMod] := ""
If (Hotkey != "")
Return
Hotkey_ViewMod:
Hotkey := "", OnlyMods := 1, Hotkey_Value(Hotkey_ID(ControlHandle), K.Prefix Hotkey), Hotkey_Value(ControlHandle, K.Prefix Hotkey)
K.Mods := K.MLCtrl K.MRCtrl K.MLAlt K.MRAlt K.MLShift K.MRShift K.MLWin K.MRWin K.MCtrl K.MAlt K.MShift K.MWin
Text := K.Mods = "" ? Hotkey_Arr("Empty") : K.Mods
SendMessage, 0xC, 0, &Text, , ahk_id %ControlHandle%
Return
Hotkey_View:
Hotkey_ViewSC:
If (A_ThisLabel = "Hotkey_ViewSC")
KeyName := Hotkey_Arr("OnlyEngSym") ? EngSym[A_ThisHotkey] : Format("{:U}", GetKeyName(A_ThisHotkey))
Else
KeyName := A_ThisHotkey
Hotkey := A_ThisHotkey, OnlyMods := 0
K.Prefix := K.PLCtrl K.PRCtrl K.PLAlt K.PRAlt K.PLShift K.PRShift K.PLWin K.PRWin K.PCtrl K.PAlt K.PShift K.PWin
Hotkey_Value(Hotkey_ID(ControlHandle), K.Prefix Hotkey), Hotkey_Value(ControlHandle, K.Prefix Hotkey)
K.Mods := K.MLCtrl K.MRCtrl K.MLAlt K.MRAlt K.MLShift K.MRShift K.MLWin K.MRWin K.MCtrl K.MAlt K.MShift K.MWin
Text := K.Mods KeyName = "" ? Hotkey_Arr("Empty") : K.Mods KeyName
SendMessage, 0xC, 0, &Text, , ahk_id %ControlHandle%
If Hotkey_Group("Get", Hotkey_ID(ControlHandle)) && Hotkey_Group("SaveCheck", ControlHandle)
SetTimer, Hotkey_Group, -70
Return
}
Hotkey_InitHotkeys() {
Local S_FormatInteger, Name
Static nmMods := "LAlt|RAlt|LCtrl|RCtrl|LShift|RShift|LWin|RWin"
, nmMouse := "MButton|WheelDown|WheelUp|WheelRight|WheelLeft|XButton1|XButton2"
, scSymb := "2|3|4|5|6|7|8|9|A|B|C|D|10|11|12|13|14|15|16|17|18|19|1A|1B|1E|1F|"
. "20|21|22|23|24|25|26|27|28|29|2B|2C|2D|2E|2F|30|31|32|33|34|35"
, scNoSymb := "1|E|F|1C|37|39|3A|3B|3C|3D|3E|3F|40|41|42|43|44|45|46|47|48|49|4A|4B|4C|4D|4E|4F|50|51|52|53|54|"
. "57|58|63|64|65|66|67|68|69|6A|6B|6C|6D|6E|76|11C|135|147|148|149|14B|14D|14F|150|151|152|153|15D"
, vkOther := "3|13|5F|60|61|62|63|64|65|66|67|68|69|6E|A6|A7|A8|A9|AA|AB|AC|AD|AE|AF|B0|B1|B2|B3|B4|B5|B6|B7"
#IF Hotkey_IsRegControl()
#IF Hotkey_Hook("K")
#IF Hotkey_Hook("M")
#IF Hotkey_Hook("L") && GetKeyState("RButton", "P")
#IF Hotkey_Hook("R")
#IF Hotkey_Hook("J") && !Hotkey_Main("GetMod")
#IF Hotkey_Arr("Hook") && !Hotkey_Hook("K")
#IF
Hotkey, IF, Hotkey_Hook("M")
Loop, Parse, nmMouse, |
Hotkey, % A_LoopField, Hotkey_View
Hotkey, IF, Hotkey_Hook("K")
Loop, Parse, nmMods, |
{
Hotkey, % A_LoopField, Hotkey_Mods
Hotkey, % A_LoopField " Up", Hotkey_ModsUp
}
Loop, Parse, scSymb, |
Hotkey, % "sc" A_LoopField, Hotkey_ViewSC
Loop, Parse, scNoSymb, |
Hotkey, % GetKeyName("sc" A_LoopField), Hotkey_View
Loop, Parse, vkOther, |
Hotkey, % GetKeyName("vk" A_LoopField), Hotkey_View
Hotkey, IF, Hotkey_Hook("L") && GetKeyState("RButton"`, "P")
Hotkey, LButton, Hotkey_View
Hotkey, IF, Hotkey_Hook("R")
Hotkey, RButton, Hotkey_View
S_FormatInteger := A_FormatInteger
SetFormat, IntegerFast, D
Hotkey, IF, Hotkey_Hook("J") && !Hotkey_Main("GetMod")
Loop, 128
Hotkey % Ceil(A_Index / 32) "Joy" Mod(A_Index - 1, 32) + 1, Hotkey_View
SetFormat, IntegerFast, %S_FormatInteger%
Hotkey, IF, Hotkey_IsRegControl()
Hotkey, RButton, Hotkey_RButton
Hotkey, RButton Up, Hotkey_Return
Hotkey, IF, Hotkey_Arr("Hook") && !Hotkey_Hook("K")
Hotkey, AppsKey Up, Hotkey_Return
Hotkey, +F10, Hotkey_Return
Hotkey, IF
Return
Hotkey_RButton:
Click
Hotkey_Return:
Return
}
Hotkey_IsRegControl() {
Local Control
MouseGetPos,,,, Control, 2
Return Hotkey_ID(Control) != ""
}
Hotkey_IsRegFocus() {
Local ControlNN, hFocus
ControlGetFocus, ControlNN, A
ControlGet, hFocus, Hwnd, , %ControlNN%, A
Hotkey_ID(hFocus) != "" ? Hotkey_Main("Control", hFocus) : 0
}
Hotkey_EventFocus(hWinEventHook, event, hwnd) {
Hotkey_ID(hwnd) != "" ? Hotkey_Main("Control", hwnd) : Hotkey_Main("Control")
}
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")
}
; -------------------------------------- Save and get --------------------------------------
Hotkey_Arr(P*) {
Static Arr := {"Empty":"Нет"}
Return P.MaxIndex() = 1 ? Arr[P[1]] : (Arr[P[1]] := P[2])
}
Hotkey_ID(P*) {
Static Arr := {}
Return P.MaxIndex() = 1 ? Arr[P[1]] : P.MaxIndex() = 2 ? (Arr[P[1]] := P[2]) : Arr.Delete(P[1])
}
Hotkey_Value(P*) {
Static Arr := {}
Return P.MaxIndex() = 1 ? Arr[P[1]] : P.MaxIndex() = 2 ? (Arr[P[1]] := P[2]) : Arr.Delete(P[1])
}
Hotkey_Options(P*) {
Static Arr := {}
Return P.MaxIndex() = 1 ? Arr[P[1]] : P.MaxIndex() = 2 ? (Arr[P[1]] := P[2]) : Arr.Delete(P[1])
}
Hotkey_ChangeOption(ID, Option) {
Local Hwnd
Hwnd := (ID + 0 != "") ? ID : Hotkey_ID(ID)
Return Hotkey_Options(Hwnd, Option)
}
Hotkey_Hook(Option) {
Return Hotkey_Arr("Hook") && !!InStr(Hotkey_Arr("Hook"), Option)
}
Hotkey_Group(Key = "", p1 = "", p2 = "") {
Local Name, k, v, n, m
Static NG := {}, GN := [], Blink := [], SaveCheck := [], i := 0
If (Key = "") {
For k, Name in SaveCheck
If (Hotkey_Value(Name) != "")
For k, n in GN[NG[Name]] {
If (Hotkey_Value(n) != "" && n != Name && Hotkey_Value(n) = Hotkey_Value(Name)) {
; Control, Disable, , , % "ahk_id" Hotkey_ID(Name)
DllCall("ShowWindow", "ptr", Hotkey_ID(n), "Int", 4)
Blink[Hotkey_ID(n)] := 1, i := 7, Hotkey_Set(Name)
SetTimer, Hotkey_BlinkControl, -50
; Control, Enable, , , % "ahk_id" Hotkey_ID(Name)
}
}
SaveCheck := []
}
Else If (Key = "Set")
NG[p1] := p2, IsObject(GN[p2]) ? GN[p2].Push(p1) : GN[p2] := [p1]
Else If (Key = "SaveCheck")
Return 1, SaveCheck[p1] := Hotkey_ID(p1)
Else If (Key = "Get")
Return NG[p1] != ""
Else If (Key = "CheckAll") {
For k, v in GN
For k, n in v
If (Hotkey_Value(n) != "")
For k, m in v
If (n != m && Hotkey_Value(n) = Hotkey_Value(m))
Hotkey_Set(m)
}
Return
Hotkey_BlinkControl:
For k in Blink
; Control, % Mod(i, 2) ? "Show" : "Hide", , , % "ahk_id" k
DllCall("ShowWindow", "ptr", k, "Int", Mod(i, 2) ? 4 : 0)
If (--i > 0) || !(Blink := [])
SetTimer, Hotkey_BlinkControl, -50
Return
}
Hotkey_Delete(ID, Destroy=0) {
Local Hwnd, Name, hFocus, ControlNN
(ID + 0 = "") ? (Hwnd := Hotkey_ID(ID), Name := ID) : (Hwnd := ID, Name := Hotkey_ID(ID))
Hotkey_ID(Hwnd, "", 1), Hotkey_ID(Name, "", 1)
Hotkey_Value(Hwnd, "", 1), Hotkey_Value(Name, "", 1)
Hotkey_Options(Hwnd, "", 1)
ControlGetFocus, ControlNN, A
ControlGet, hFocus, Hwnd, , %ControlNN%, A
(hFocus = Hwnd ? Hotkey_Main("Control") : 0)
If Destroy
DllCall("DestroyWindow", "Ptr", Hwnd)
Else
PostMessage, 0x00CF, 0, , , % "ahk_id" Hwnd ; EM_SETREADONLY
Return Hwnd
}
Hotkey_Set(Name, Value="") {
Text := Value = "" ? Hotkey_Arr("Empty") : Hotkey_HKToStr(Value)
SendMessage, 0xC, 0, &Text, , % "ahk_id" Hotkey_ID(Name)
Return Hotkey_HKToStr(Value), Hotkey_Value(Name, Value), Hotkey_Value(Hotkey_ID(Name), Value)
}
Hotkey_Read(Name, Section = "", FilePath = "") {
Local HK
HK := Hotkey_IniRead(Name, Section, FilePath), Hotkey_Value(Name, HK)
Return Hotkey_HKToStr(HK)
}
Hotkey_IniPath(Path = "") {
Return Path = "" ? Hotkey_Arr("IniPath") : Hotkey_Arr("IniPath", Path)
}
Hotkey_IniSection(Section = "") {
Return Section = "" ? Hotkey_Arr("IniSection") : Hotkey_Arr("IniSection", Section)
}
Hotkey_IniRead(Name, Section = "", FilePath = "") {
Local Data
IniRead, Data, % FilePath = "" ? Hotkey_IniPath() : FilePath, % Section = "" ? Hotkey_IniSection() : Section, % Name, % A_Space
Return Data
}
Hotkey_IniWrite(ID, Section = "", FilePath = "") {
Local Key
Key := (ID + 0 = "") ? ID : Hotkey_ID(ID)
If (Key != "")
IniWrite, % Hotkey_Value(ID), % FilePath = "" ? Hotkey_IniPath() : FilePath, % Section = "" ? Hotkey_IniSection() : Section, % Key
}
; -------------------------------------- Format --------------------------------------
; http://forum.script-coding.com/viewtopic.php?pid=105023#p105023
Hotkey_HKToStr(HK) {
Static LRPrefix := [["<^","LCtrl"],[">^","RCtrl"],["<!","LAlt"],[">!","RAlt"]
,["<+","LShift"],[">+","RShift"],["<#","LWin"],[">#","RWin"]]
, Prefix := [["^","Ctrl"],["!","Alt"],["+","Shift"],["#","Win"]]
, EngSym := {"sc2":"1","sc3":"2","sc4":"3","sc5":"4","sc6":"5","sc7":"6"
,"sc8":"7","sc9":"8","scA":"9","scB":"0","scC":"-","scD":"="
,"sc10":"Q","sc11":"W","sc12":"E","sc13":"R","sc14":"T","sc15":"Y"
,"sc16":"U","sc17":"I","sc18":"O","sc19":"P","sc1A":"[","sc1B":"]"
,"sc1E":"A","sc1F":"S","sc20":"D","sc21":"F","sc22":"G","sc23":"H"
,"sc24":"J","sc25":"K","sc26":"L","sc27":"`;","sc28":"'","sc29":"``"
,"sc2B":"\","sc2C":"Z","sc2D":"X","sc2E":"C","sc2F":"V","sc30":"B"
,"sc31":"N","sc32":"M","sc33":",","sc34":".","sc35":"/"
,"vk31":"1","vk32":"2","vk33":"3","vk34":"4","vk35":"5","vk36":"6"
,"vk37":"7","vk38":"8","vk39":"9","vk30":"0","vkBD":"-","vkBB":"="
,"vk51":"Q","vk57":"W","vk45":"E","vk52":"R","vk54":"T","vk59":"Y"
,"vk55":"U","vk49":"I","vk4F":"O","vk50":"P","vkDB":"[","vkDD":"]"
,"vk41":"A","vk53":"S","vk44":"D","vk46":"F","vk47":"G","vk48":"H"
,"vk4A":"J","vk4B":"K","vk4C":"L","vkBA":"`;","vkDE":"'","vkC0":"``"
,"vkDC":"\","vk5A":"Z","vk58":"X","vk43":"C","vk56":"V","vk42":"B"
,"vk4E":"N","vk4D":"M","vkBC":",","vkBE":".","vkBF":"/"}
Local K, K1, K2, I, V, M, R
RegExMatch(HK, "S)^\s*([~\*\$\^\+!#<>]*)\{?(.*?)}?\s*$", K)
If (K2 = "")
Return "" Hotkey_Arr("Empty")
If (InStr("|" K2, "|sc", 1) || InStr("|" K2, "|vk", 1))
K2 := Hotkey_Arr("OnlyEngSym") && EngSym.HasKey(K2) ? EngSym[K2] : Format("{:U}", GetKeyName(K2))
If (K1 != "")
For I, V in K1 ~= "[<>]" ? LRPrefix : Prefix
K1 := StrReplace(K1, V[1], "", R), R && (M .= V[2] "+")
Return M . (StrLen(K2) = 1 ? Format("{:U}", K2) : K2)
}
Hotkey_HKToSend(HK, Section = "", FilePath = "") {
Static LRPrefix := [["<^","LCtrl"],[">^","RCtrl"],["<!","LAlt"],[">!","RAlt"]
,["<+","LShift"],[">+","RShift"],["<#","LWin"],[">#","RWin"]]
, Prefix := [["^","LCtrl"],["!","LAlt"],["+","LShift"],["#","LWin"]]
Local K, K1, K2, I, V, M1, M2, R
If (HK = "")
Return
If (Section != "")
IniRead, HK, % FilePath = "" ? Hotkey_IniPath() : FilePath, % Section, % HK, % A_Space
RegExMatch(HK, "S)^\s*([~\*\$\^\+!#<>]*)\{?(.*?)}?\s*$", K)
If (K1 != "")
For I, V in K1 ~= "[<>]" ? LRPrefix : Prefix
K1 := StrReplace(K1, V[1], "", R)
, R ? (M1 .= "{" V[2] " Down}", M2 .= "{" V[2] " Up}") : 0
Return M1 . "{" K2 "}" . M2
}
В данном примере в трёх контролах нельзя назначить одинаковые хоткеи, так как они указаны в одной группе.
#NoEnv
#SingleInstance Force
Hotkey_Arr("OnlyEngSym", True)
Hotkey_IniPath(A_ScriptDir "\Hotkey.ini")
Hotkey_IniSection("Hotkeys")
Gui, Add, Edit, Center w333 y+10 r1 hwndh1 gSave, % Hotkey_Read("Hotkey1")
Gui, Add, Edit, Center wp y+10 r1 hwndh2 gSave, % Hotkey_Read("Hotkey2")
Gui, Add, Edit, Center wp y+10 r1 hwndh3 gSave, % Hotkey_Read("Hotkey3")
Hotkey_Register(["Hotkey1",h1,"KMLRJDG1"],["Hotkey2",h2,"KMLRJDG1"],["Hotkey3",h3,"KMLRJDG1"])
Gui, Show, , Hotkey Gui
Return
Save(Hwnd) {
Hotkey_IniWrite(Hwnd)
}
GuiClose() {
ExitApp
}
Если по какой то причине надо проверить все контролы на повторы, и если они есть, то стереть их, надо вызвать:
Hotkey_Group("CheckAll")
Сделал тестовую версию, в опциях контрола указываем G и сразу за ним номер группы. Если вопрос интересен, прошу протестировать и отписатся.
Даже очень интересно, тестирую, позже отпишусь.
Заметил если хоткей назначен типа "Alt+F1" то хоткей типа "LAlt+F1" можно спокойно назначить. По логике вещей хоткеи разные, но в принципе их можно оба запустить левым альтом.
Заметил если хоткей назначен типа "Alt+F1" то хоткей типа "LAlt+F1"можно спокойно назначить. По логике вещей хоткеи разные, но в принципе их можно оба запустить левым альтом.
Да, верно, это попробуйте.
Hotkey_Register(Controls*) {
Static IsStart
Local k, v, g, g1
For k, v in Controls
{
Hotkey_ID(v[2], v[1]), Hotkey_ID(v[1], v[2])
Hotkey_Options(v[2], v[3] = "" ? "K" : v[3])
Hotkey_Value(v[2], Hotkey_Value(v[1]))
PostMessage, 0x00CF, 1, , , % "ahk_id" v[2] ; EM_SETREADONLY
If RegExMatch(v[3], "i)G(\d+)", g)
Hotkey_Group("Set", v[1], g1)
}
If IsStart
Return Hotkey_IsRegFocus()
#HotkeyInterval 0
Hotkey_SetWinEventHook(0x8005, 0x8005, 0, RegisterCallback("Hotkey_EventFocus", "F"), 0, 0, 0) ; EVENT_OBJECT_FOCUS := 0x8005
Hotkey_InitHotkeys(), Hotkey_IsRegFocus(), IsStart := 1
}
Hotkey_Main(Param1, Param2 = "") {
Static OnlyMods, ControlHandle, Hotkey, KeyName, K := {}
, Prefix := {"LAlt":"<!","LCtrl":"<^","LShift":"<+","LWin":"<#"
,"RAlt":">!","RCtrl":">^","RShift":">+","RWin":">#"
,"Alt":"!","Ctrl":"^","Shift":"+","Win":"#"}
, EngSym := {"sc2":"1","sc3":"2","sc4":"3","sc5":"4","sc6":"5","sc7":"6"
,"sc8":"7","sc9":"8","scA":"9","scB":"0","scC":"-","scD":"="
,"sc10":"Q","sc11":"W","sc12":"E","sc13":"R","sc14":"T","sc15":"Y"
,"sc16":"U","sc17":"I","sc18":"O","sc19":"P","sc1A":"[","sc1B":"]"
,"sc1E":"A","sc1F":"S","sc20":"D","sc21":"F","sc22":"G","sc23":"H"
,"sc24":"J","sc25":"K","sc26":"L","sc27":"`;","sc28":"'","sc29":"``"
,"sc2B":"\","sc2C":"Z","sc2D":"X","sc2E":"C","sc2F":"V","sc30":"B"
,"sc31":"N","sc32":"M","sc33":",","sc34":".","sc35":"/"}
Local IsMod, Text
If Param1 = GetMod
Return K.MLCtrl K.MRCtrl K.MLAlt K.MRAlt K.MLShift K.MRShift K.MLWin K.MRWin K.MCtrl K.MAlt K.MShift K.MWin
If Param2
{
If OnlyMods
{
SendMessage, 0xC, 0, "" Hotkey_Arr("Empty"), , ahk_id %ControlHandle%
OnlyMods := 0, K := {}
}
ControlHandle := Param2
Hotkey_Arr("Hook", Hotkey_Options(ControlHandle))
PostMessage, 0x00B1, -1, -1, , ahk_id %ControlHandle% ; EM_SETSEL
}
Else If Hotkey_Arr("Hook")
{
Hotkey_Arr("Hook", 0), K := {}
If OnlyMods
SendMessage, 0xC, 0, "" Hotkey_Arr("Empty"), , ahk_id %ControlHandle%
SetTimer, Hotkey_IsRegFocus, -200
}
Return
Hotkey_Mods:
If InStr(Hotkey_Arr("Hook"), "S")
GoTo Hotkey_View
IsMod := InStr(Hotkey_Arr("Hook"), "D") ? A_ThisHotkey : SubStr(A_ThisHotkey, 2)
If (K["M" IsMod] != "")
Return
K["M" IsMod] := IsMod "+", K["P" IsMod] := Prefix[IsMod]
GoTo Hotkey_ViewMod
Hotkey_ModsUp:
If InStr(Hotkey_Arr("Hook"), "S")
Return
IsMod := InStr(Hotkey_Arr("Hook"), "D") ? SubStr(A_ThisHotkey, 1, -3) : SubStr(A_ThisHotkey, 2, -3)
K["M" IsMod] := "", K["P" IsMod] := ""
If (Hotkey != "")
Return
Hotkey_ViewMod:
Hotkey := "", OnlyMods := 1, Hotkey_Value(Hotkey_ID(ControlHandle), K.Prefix Hotkey), Hotkey_Value(ControlHandle, K.Prefix Hotkey)
K.Mods := K.MLCtrl K.MRCtrl K.MLAlt K.MRAlt K.MLShift K.MRShift K.MLWin K.MRWin K.MCtrl K.MAlt K.MShift K.MWin
Text := K.Mods = "" ? Hotkey_Arr("Empty") : K.Mods
SendMessage, 0xC, 0, &Text, , ahk_id %ControlHandle%
Return
Hotkey_View:
Hotkey_ViewSC:
If (A_ThisLabel = "Hotkey_ViewSC")
KeyName := Hotkey_Arr("OnlyEngSym") ? EngSym[A_ThisHotkey] : Format("{:U}", GetKeyName(A_ThisHotkey))
Else
KeyName := A_ThisHotkey
Hotkey := A_ThisHotkey, OnlyMods := 0
K.Prefix := K.PLCtrl K.PRCtrl K.PLAlt K.PRAlt K.PLShift K.PRShift K.PLWin K.PRWin K.PCtrl K.PAlt K.PShift K.PWin
Hotkey_Value(Hotkey_ID(ControlHandle), K.Prefix Hotkey), Hotkey_Value(ControlHandle, K.Prefix Hotkey)
K.Mods := K.MLCtrl K.MRCtrl K.MLAlt K.MRAlt K.MLShift K.MRShift K.MLWin K.MRWin K.MCtrl K.MAlt K.MShift K.MWin
Text := K.Mods KeyName = "" ? Hotkey_Arr("Empty") : K.Mods KeyName
SendMessage, 0xC, 0, &Text, , ahk_id %ControlHandle%
If Hotkey_Group("Get", Hotkey_ID(ControlHandle)) && Hotkey_Group("SaveCheck", ControlHandle)
SetTimer, Hotkey_Group, -70
Return
}
Hotkey_InitHotkeys() {
Local S_FormatInteger, Name
Static nmMods := "LAlt|RAlt|LCtrl|RCtrl|LShift|RShift|LWin|RWin"
, nmMouse := "MButton|WheelDown|WheelUp|WheelRight|WheelLeft|XButton1|XButton2"
, scSymb := "2|3|4|5|6|7|8|9|A|B|C|D|10|11|12|13|14|15|16|17|18|19|1A|1B|1E|1F|"
. "20|21|22|23|24|25|26|27|28|29|2B|2C|2D|2E|2F|30|31|32|33|34|35"
, scNoSymb := "1|E|F|1C|37|39|3A|3B|3C|3D|3E|3F|40|41|42|43|44|45|46|47|48|49|4A|4B|4C|4D|4E|4F|50|51|52|53|54|"
. "57|58|63|64|65|66|67|68|69|6A|6B|6C|6D|6E|76|11C|135|147|148|149|14B|14D|14F|150|151|152|153|15D"
, vkOther := "3|13|5F|60|61|62|63|64|65|66|67|68|69|6E|A6|A7|A8|A9|AA|AB|AC|AD|AE|AF|B0|B1|B2|B3|B4|B5|B6|B7"
#IF Hotkey_IsRegControl()
#IF Hotkey_Hook("K")
#IF Hotkey_Hook("M")
#IF Hotkey_Hook("L") && GetKeyState("RButton", "P")
#IF Hotkey_Hook("R")
#IF Hotkey_Hook("J") && !Hotkey_Main("GetMod")
#IF Hotkey_Arr("Hook") && !Hotkey_Hook("K")
#IF
Hotkey, IF, Hotkey_Hook("M")
Loop, Parse, nmMouse, |
Hotkey, % A_LoopField, Hotkey_View
Hotkey, IF, Hotkey_Hook("K")
Loop, Parse, nmMods, |
{
Hotkey, % A_LoopField, Hotkey_Mods
Hotkey, % A_LoopField " Up", Hotkey_ModsUp
}
Loop, Parse, scSymb, |
Hotkey, % "sc" A_LoopField, Hotkey_ViewSC
Loop, Parse, scNoSymb, |
Hotkey, % GetKeyName("sc" A_LoopField), Hotkey_View
Loop, Parse, vkOther, |
Hotkey, % GetKeyName("vk" A_LoopField), Hotkey_View
Hotkey, IF, Hotkey_Hook("L") && GetKeyState("RButton"`, "P")
Hotkey, LButton, Hotkey_View
Hotkey, IF, Hotkey_Hook("R")
Hotkey, RButton, Hotkey_View
S_FormatInteger := A_FormatInteger
SetFormat, IntegerFast, D
Hotkey, IF, Hotkey_Hook("J") && !Hotkey_Main("GetMod")
Loop, 128
Hotkey % Ceil(A_Index / 32) "Joy" Mod(A_Index - 1, 32) + 1, Hotkey_View
SetFormat, IntegerFast, %S_FormatInteger%
Hotkey, IF, Hotkey_IsRegControl()
Hotkey, RButton, Hotkey_RButton
Hotkey, RButton Up, Hotkey_Return
Hotkey, IF, Hotkey_Arr("Hook") && !Hotkey_Hook("K")
Hotkey, AppsKey Up, Hotkey_Return
Hotkey, +F10, Hotkey_Return
Hotkey, IF
Return
Hotkey_RButton:
Click
Hotkey_Return:
Return
}
Hotkey_IsRegControl() {
Local Control
MouseGetPos,,,, Control, 2
Return Hotkey_ID(Control) != ""
}
Hotkey_IsRegFocus() {
Local ControlNN, hFocus
ControlGetFocus, ControlNN, A
ControlGet, hFocus, Hwnd, , %ControlNN%, A
Hotkey_ID(hFocus) != "" ? Hotkey_Main("Control", hFocus) : 0
}
Hotkey_EventFocus(hWinEventHook, event, hwnd) {
Hotkey_ID(hwnd) != "" ? Hotkey_Main("Control", hwnd) : Hotkey_Main("Control")
}
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")
}
; -------------------------------------- Save and get --------------------------------------
Hotkey_Arr(P*) {
Static Arr := {"Empty":"Нет"}
Return P.MaxIndex() = 1 ? Arr[P[1]] : (Arr[P[1]] := P[2])
}
Hotkey_ID(P*) {
Static Arr := {}
Return P.MaxIndex() = 1 ? Arr[P[1]] : P.MaxIndex() = 2 ? (Arr[P[1]] := P[2]) : Arr.Delete(P[1])
}
Hotkey_Value(P*) {
Static Arr := {}
Return P.MaxIndex() = 1 ? Arr[P[1]] : P.MaxIndex() = 2 ? (Arr[P[1]] := P[2]) : Arr.Delete(P[1])
}
Hotkey_Options(P*) {
Static Arr := {}
Return P.MaxIndex() = 1 ? Arr[P[1]] : P.MaxIndex() = 2 ? (Arr[P[1]] := P[2]) : Arr.Delete(P[1])
}
Hotkey_ChangeOption(ID, Option) {
Local Hwnd, Name, g, g1
(ID + 0 = "") ? (Hwnd := Hotkey_ID(ID), Name := ID) : (Hwnd := ID, Name := Hotkey_ID(ID))
If RegExMatch(Hotkey_Options(Hwnd), "i)G(\d+)", g)
Hotkey_Group("Delete", Name)
If RegExMatch(Option, "i)G(\d+)", g)
Hotkey_Group("Set", Name, g1)
Return Hotkey_Options(Hwnd, Option)
}
Hotkey_Hook(Option) {
Return Hotkey_Arr("Hook") && !!InStr(Hotkey_Arr("Hook"), Option)
}
Hotkey_Delete(ID, Destroy=0) {
Local Hwnd, Name, hFocus, ControlNN
(ID + 0 = "") ? (Hwnd := Hotkey_ID(ID), Name := ID) : (Hwnd := ID, Name := Hotkey_ID(ID))
Hotkey_Group("Delete", Name)
Hotkey_ID(Hwnd, "", 1), Hotkey_ID(Name, "", 1)
Hotkey_Value(Hwnd, "", 1), Hotkey_Value(Name, "", 1)
Hotkey_Options(Hwnd, "", 1)
ControlGetFocus, ControlNN, A
ControlGet, hFocus, Hwnd, , %ControlNN%, A
(hFocus = Hwnd ? Hotkey_Main("Control") : 0)
If Destroy
DllCall("DestroyWindow", "Ptr", Hwnd)
Else
PostMessage, 0x00CF, 0, , , % "ahk_id" Hwnd ; EM_SETREADONLY
Return Hwnd
}
Hotkey_Set(Name, Value="") {
Local Text
Text := Hotkey_HKToStr(Value)
SendMessage, 0xC, 0, &Text, , % "ahk_id" Hotkey_ID(Name)
Return Text, Hotkey_Value(Name, Value), Hotkey_Value(Hotkey_ID(Name), Value)
}
Hotkey_Read(Name, Section = "", FilePath = "") {
Local HK
HK := Hotkey_IniRead(Name, Section, FilePath), Hotkey_Value(Name, HK)
Return Hotkey_HKToStr(HK)
}
Hotkey_IniPath(Path = "") {
Return Path = "" ? Hotkey_Arr("IniPath") : Hotkey_Arr("IniPath", Path)
}
Hotkey_IniSection(Section = "") {
Return Section = "" ? Hotkey_Arr("IniSection") : Hotkey_Arr("IniSection", Section)
}
Hotkey_IniRead(Name, Section = "", FilePath = "") {
Local Data
IniRead, Data, % FilePath = "" ? Hotkey_IniPath() : FilePath, % Section = "" ? Hotkey_IniSection() : Section, % Name, % A_Space
Return Data
}
Hotkey_IniWrite(ID, Section = "", FilePath = "") {
Local Key
Key := (ID + 0 = "") ? ID : Hotkey_ID(ID)
If (Key != "")
IniWrite, % Hotkey_Value(ID), % FilePath = "" ? Hotkey_IniPath() : FilePath, % Section = "" ? Hotkey_IniSection() : Section, % Key
}
; -------------------------------------- Group --------------------------------------
Hotkey_Group(Key = "", p1 = "", p2 = "") {
Local Name, Value, k, v, n, m
Static NG := {}, GN := [], Blink := [], SaveCheck := [], i := 0
If (Key = "") {
For k, Name in SaveCheck {
If ((Value := Hotkey_Value(Name)) != "")
For m, n in GN[NG[Name]] {
If (n != Name && Hotkey_Equal(Value, Hotkey_Value(n))) {
DllCall("ShowWindowAsync", "Ptr", Hotkey_ID(n), "Int", 0)
Blink[Hotkey_ID(n)] := 1, i := 5, Hotkey_Set(Name)
SetTimer, Hotkey_BlinkControl, -50
}
}
SaveCheck.Delete(k)
}
}
Else If (Key = "Set")
NG[p1] := p2, IsObject(GN[p2]) ? GN[p2].Push(p1) : GN[p2] := [p1]
Else If (Key = "SaveCheck")
Return 1, SaveCheck[p1] := Hotkey_ID(p1)
Else If (Key = "Get")
Return NG[p1] != ""
Else If (Key = "CheckAll") {
For k, v in GN
For k, n in v
If ((Value := Hotkey_Value(n)) != "")
For k, m in v
If (n != m && Hotkey_Equal(Value, Hotkey_Value(m)))
Hotkey_Set(m)
}
Else If (Key = "Delete") {
For k, v in GN[NG[p1]]
If (v = p1) {
GN[NG[p1]].RemoveAt(k)
Break
}
NG.Delete(p1)
}
Return
Hotkey_BlinkControl:
For k in Blink
DllCall("ShowWindowAsync", "Ptr", k, "Int", Mod(i, 2) ? 4 : 0)
If (--i > 0) || !(Blink := [])
SetTimer, Hotkey_BlinkControl, -50
Return
}
Hotkey_Equal(HK1, HK2) {
If (HK2 = "")
Return 0
If (HK1 = HK2)
Return 1
If !(HK1 ~= "S)[\^\+!#]") || !(HK2 ~= "S)[\^\+!#]")
Return 0
If (HK1 ~= "S)[<>]") && (HK2 ~= "S)[<>]")
Return 0
Return (Hotkey_ModsSub(HK1) = Hotkey_ModsSub(HK2))
}
Hotkey_ModsSub(Value) {
If !(Value ~= "[<>]")
Return Value
Value := StrReplace(Value, "<")
Value := StrReplace(Value, ">")
Value := StrReplace(Value, "^^", "^", , 1)
Value := StrReplace(Value, "!!", "!", , 1)
Value := StrReplace(Value, "++", "+", , 1)
Return StrReplace(Value, "##", "#", , 1)
}
; -------------------------------------- Format --------------------------------------
; http://forum.script-coding.com/viewtopic.php?pid=105023#p105023
Hotkey_HKToStr(HK) {
Static LRPrefix := [["<^","LCtrl"],[">^","RCtrl"],["<!","LAlt"],[">!","RAlt"]
,["<+","LShift"],[">+","RShift"],["<#","LWin"],[">#","RWin"]]
, Prefix := [["^","Ctrl"],["!","Alt"],["+","Shift"],["#","Win"]]
, EngSym := {"sc2":"1","sc3":"2","sc4":"3","sc5":"4","sc6":"5","sc7":"6"
,"sc8":"7","sc9":"8","scA":"9","scB":"0","scC":"-","scD":"="
,"sc10":"Q","sc11":"W","sc12":"E","sc13":"R","sc14":"T","sc15":"Y"
,"sc16":"U","sc17":"I","sc18":"O","sc19":"P","sc1A":"[","sc1B":"]"
,"sc1E":"A","sc1F":"S","sc20":"D","sc21":"F","sc22":"G","sc23":"H"
,"sc24":"J","sc25":"K","sc26":"L","sc27":"`;","sc28":"'","sc29":"``"
,"sc2B":"\","sc2C":"Z","sc2D":"X","sc2E":"C","sc2F":"V","sc30":"B"
,"sc31":"N","sc32":"M","sc33":",","sc34":".","sc35":"/"
,"vk31":"1","vk32":"2","vk33":"3","vk34":"4","vk35":"5","vk36":"6"
,"vk37":"7","vk38":"8","vk39":"9","vk30":"0","vkBD":"-","vkBB":"="
,"vk51":"Q","vk57":"W","vk45":"E","vk52":"R","vk54":"T","vk59":"Y"
,"vk55":"U","vk49":"I","vk4F":"O","vk50":"P","vkDB":"[","vkDD":"]"
,"vk41":"A","vk53":"S","vk44":"D","vk46":"F","vk47":"G","vk48":"H"
,"vk4A":"J","vk4B":"K","vk4C":"L","vkBA":"`;","vkDE":"'","vkC0":"``"
,"vkDC":"\","vk5A":"Z","vk58":"X","vk43":"C","vk56":"V","vk42":"B"
,"vk4E":"N","vk4D":"M","vkBC":",","vkBE":".","vkBF":"/"}
Local K, K1, K2, I, V, M, R
RegExMatch(HK, "S)^\s*([~\*\$\^\+!#<>]*)\{?(.*?)}?\s*$", K)
If (K2 = "")
Return "" Hotkey_Arr("Empty")
If (InStr("|" K2, "|sc", 1) || InStr("|" K2, "|vk", 1))
K2 := Hotkey_Arr("OnlyEngSym") && EngSym.HasKey(K2) ? EngSym[K2] : Format("{:U}", GetKeyName(K2))
If (K1 != "")
For I, V in K1 ~= "[<>]" ? LRPrefix : Prefix
K1 := StrReplace(K1, V[1], "", R), R && (M .= V[2] "+")
Return M . (StrLen(K2) = 1 ? Format("{:U}", K2) : K2)
}
Hotkey_HKToSend(HK, Section = "", FilePath = "") {
Static LRPrefix := [["<^","LCtrl"],[">^","RCtrl"],["<!","LAlt"],[">!","RAlt"]
,["<+","LShift"],[">+","RShift"],["<#","LWin"],[">#","RWin"]]
, Prefix := [["^","LCtrl"],["!","LAlt"],["+","LShift"],["#","LWin"]]
Local K, K1, K2, I, V, M1, M2, R
If (HK = "")
Return
If (Section != "")
IniRead, HK, % FilePath = "" ? Hotkey_IniPath() : FilePath, % Section, % HK, % A_Space
RegExMatch(HK, "S)^\s*([~\*\$\^\+!#<>]*)\{?(.*?)}?\s*$", K)
If (K1 != "")
For I, V in K1 ~= "[<>]" ? LRPrefix : Prefix
K1 := StrReplace(K1, V[1], "", R)
, R ? (M1 .= "{" V[2] " Down}", M2 .= "{" V[2] " Up}") : 0
Return M1 . "{" K2 "}" . M2
}
Да, верно, это попробуйте.
Спасибо, работает. В целом проблем в общем-то не было, по крайней мере с тем функционалом, что я использую.
serzh82saratov
Здравствует. Скажите пожалуйста, можно сделать функцию при которой можно задавать только кнопки модификаторы?
Есть опция "S". Если не то, то зачем только одни модификаторы?
Вы кстати версией из 196 поста пользуетесь, думаю оставить только её?
Есть опция "S". Если не то, то зачем только одни модификаторы?
Вы кстати версией из 196 поста пользуетесь, думаю оставить только её?
Опция "S" в принципе подходит, но не совсем. В некоторых случаях нужно задавать модификатор отдельно, который работает в связке с другими хоткеями. Например один модификатор работает для группы хоткеев. Так-как в этом поле нужно задать только модификатор, то задание других кнопок приведет к неработоспособности скрипта.
Вы кстати версией из 196 поста пользуетесь, думаю оставить только её?
Да пользуюсь, проблем не наблюдал. Есть небольшая неприятность. Когда назначаешь уже существующий хоткей, то этот хоткей мигает где-то слева (не всегда) видимо зависит от расположения самого поля. С чем это связано - незнаю, скорей всего из-за криворукости общего кода.
Add:
криворукости общего кода
По моему я не очень корректно вывозился. Я имел ввиду своего
Здравствует. Скажите пожалуйста, можно сделать функцию при которой можно задавать только кнопки модификаторы?
Можно сделать свой костыль - функцию для контрола, переделка библиотеки под такую опцию, на первый взгляд слишком усложнить её.
#NoEnv
#SingleInstance Force
Hotkey_IniPath(A_ScriptDir "\Hotkey.ini")
Gui, Add, Edit, Center w60 r1 hwndhMyHotkey1 gOnlyMods, % Hotkey_Read("MyHotkey1", "Section")
Gui, Add, Edit, Center w60 r1 hwndhMyHotkey2 gOnlyMods, % Hotkey_Read("MyHotkey2", "Section")
Hotkey_Register(["MyHotkey1",hMyHotkey1,"SK"],["MyHotkey2",hMyHotkey2,"SK"])
Gui, Show
Return
OnlyMods(CtrlHwnd) {
If !(Hotkey_Value(CtrlHwnd) ~= "^(L|R)(Alt|Ctrl|Shift|Win)$")
Hotkey_Set(Hotkey_ID(CtrlHwnd))
Hotkey_IniWrite(CtrlHwnd, "Section")
}
GuiClose() {
ExitApp
}
Есть небольшая неприятность. Когда назначаешь уже существующий хоткей, то этот хоткей мигает где-то слева (не всегда)
Это не баг, это фича, чтобы было понятно с каким совпадение.
Потому плохо что не всегда мигает, точнее мигать должен только тот, который в одной группе, с тем в котором повтор.
Мы же говорим про использование новой опции "G(номер группы)"?