autohotkey печатание разных букв при быстром нажатии/удержании
При зажатии ы/Ы (sc1F vk53) более чем на keywait_delay секунд должно печататься i/і, при быстром нажатии - ы/Ы. Аналогично ъ/Ъ (sc1B vkDD) -> ї/Ї и э/Э (sc28 vkDE) -> є/Є. Также последовательность "сыы" заменяется на "css" с помощью переменной lastChars
Проблема в том, что отправка других клавиш происходит быстрее, чем успевает отправиться одна из этих заменяемых клавиш, что приводит к нарушению порядка букв, например, вместо "была" - "блыа" (то есть, сначала печатается следующая после "ы" буква, только затем "ы"), "забывала" - "забваыла".
По сути, должно быть так: нажатие "ы" -> последующий ввод останавливается, но сохраняется в буфер -> ожидание-выбор между ы/i -> отправка "ы" -> отправка буфера
Для решения был создан bufIH := InputHook("B V"). При bufIH.VisibleText == false следующие буквы сохраняются в переменную bufChars в функции BufferChar. После отправки "ы" отправляется и bufChars. Но, видимо, другие клавиши после нажатия "ы" успевают отправиться быстрее, чем выполниться
global bufIH
bufIH.VisibleText := false
в функции хоткея HoldKey
#Requires AutoHotkey v2.0
#SingleInstance force
#UseHook true
SetKeyDelay(-1, -1)
keywait_delay := 0.3 ; задержка перед определением русской или украинской буквы
lastChars := ""
bufChars := ""
bufIH := InputHook("B V")
bufIH.OnChar := BufferChar
bufIH.Start()
IsRussianLayout() {
threadId := DllCall("GetWindowThreadProcessId", "Ptr", WinExist("A"), "Ptr", 0)
hkl := DllCall("GetKeyboardLayout", "UInt", threadId, "UInt")
langId := hkl & 0xFFFF
return langId == 0x0419
}
CheckSeq() {
global lastChars
if (StrLower(lastChars) == "сыы") {
SendInput("{BS 3}")
is_capslock := GetKeyState("CapsLock", "T")
is_shift := GetKeyState("Shift", "P")
if is_capslock {
if is_shift {
SendText("css")
} else {
SendText("CSS")
}
} else {
if is_shift {
SendText("CSS")
} else {
SendText("css")
}
}
lastChars := ""
}
}
BufferChar(ih, ch) {
global bufChars
global lastChars
global bufIH
if !bufIH.VisibleText {
bufChars .= ch
}
lastChars .= ch
if (StrLen(lastChars) > 3)
lastChars := SubStr(lastChars, -3)
}
HoldKey(sc, lowerCode, upperCode) {
global bufIH
bufIH.VisibleText := false
global bufChars
global lastChars
if !IsRussianLayout() {
lastChars := ""
SendInput("{Blind}{sc" sc "}")
SendInput(bufChars)
bufIH.VisibleText := true
bufChars := ""
return
}
if !KeyWait("SC" sc, Format("T{:f} U", keywait_delay)){
; долгое зажатие
if GetKeyState("CapsLock", "T") {
SendInput(Format("{Blind}{:s}", upperCode))
} else {
SendInput(Format("{Blind}{:s}", lowerCode))
}
lastChars := ""
SendInput(bufChars)
bufIH.VisibleText := true
bufChars := ""
KeyWait("SC" sc)
} else {
; быстрое нажатие
SendInput("{Blind}{sc" sc "}")
lastChars .= sc == "1F" ? "ы" : ""
if (StrLen(lastChars) > 3)
lastChars := SubStr(lastChars, -3)
CheckSeq()
SendInput(bufChars)
bufIH.VisibleText := true
bufChars := ""
}
}
; ы (sc1F vk53) -> i/і
#MaxThreadsPerHotkey 1
SC1F::HoldKey("1F", "{U+0456}", "{U+0406}")
#MaxThreadsPerHotkey 1
+SC1F::HoldKey("1F", "{U+0406}", "{U+0456}")
; ъ (sc1B vkDD) -> ї/Ї
#MaxThreadsPerHotkey 1
SC1B::HoldKey("1B", "{U+0457}", "{U+0407}")
#MaxThreadsPerHotkey 1
+SC1B::HoldKey("1B", "{U+0407}", "{U+0457}")
; э (sc28 vkDE) -> є/Є
#MaxThreadsPerHotkey 1
SC28::HoldKey("28", "{U+0454}", "{U+0404}")
#MaxThreadsPerHotkey 1
+SC28::HoldKey("28", "{U+0404}", "{U+0454}")
; ю (sc34 vkBE) -> ґ/Ґ
;#MaxThreadsPerHotkey 1
;SC34::HoldKey("34", "{U+0491}", "{U+0490}")
;#MaxThreadsPerHotkey 1
;+SC34::HoldKey("34", "{U+0490}", "{U+0491}")
Persistent()