Тема: AHK: Случайное срабатывание capslock при переключении языков
Добрый день. Задача стоит такая: переключение языка по капслук, включение/выключение режима капслук по Альт+капслук, реверс неверной раскладки (ghbdtn ? привет) по контрол+капслук. И следующее, капс + любые клавиши = мои функции, к примеру, капс + hjkl — Vim-подобная навигация. НО! Если добавить в скрипт (все написано в одном файле) эти функции, т.е. капс+ клавиши, то капс начинает глючить при переключении языков, т.е. он включает нижний/верхний регистр символов. Проблема не в функции переключения. Для примера, нажимаем очень быстро любые кнопки на клавиатуре и нажимаем на капс, результат:
uiouщшuoiгoiuщшuoiгщшгщuщшгщшuшщгiouшщuioгшщuioгoiuшщuioг
Как видим, все в порядке. Далее, добавляем в скрипт строку:
; раскладка вима для навигации
CapsLock & h:: send {Left}
И делаем то же самое, результат:
uoiUIOuIOUoiuoiГЩШгЩШГшщгщшuiГШЩГшouOuoiuOIUiouOIUIOгШЩГшщгшUIOuiou
Почему так? Это пример был тестовый, на деле же, капс лук в стандартном режиме срабатывает иногда.
Приведу свой код, функции взяты с форумов:
; Контекстное меню + wasd - навигация
AppsKey & w:: send {PgUp}
Return
AppsKey & s:: send {PgDn}
Return
AppsKey & a:: send {Home}
Return
AppsKey & d:: send {End}
Return
;-------------------------------------------------------------
; Контекстное меню + таб - неразрывный абзац.
AppsKey & tab:: send {ASC 255}{ASC 255}{ASC 255}{ASC 255}
;-------------------------------------------------------------
; вставка кавычек
~!,:: send «»{Left}
Return
~!.:: send «»{Left}
Return
~!':: send ""{Left}
Return
;-------------------------------------------------------------
; вствка длинного тире (альт + минус)
~!-:: —
Return
;-------------------------------------------------------------
; ДВОЙНОЕ нажатие windows — запуск диспетчера задач
~LWin::
if (A_PriorHotkey <> "~LWin" or A_TimeSincePriorHotkey > 230)
; если предыдущая клавиша - не LWin,
; или со времени нажатия win прошло больше 230 миллисекунд, то...
{
KeyWait, LWin
;ожидать, пока клавиша не будет отпущена
;(чтобы исключить срабатывание от простого удержания нажатой клавиши)
Return ; закончить обработку горячей клавиши после отжатия клавиши
}
KeyWait, LWin
Run taskmgr.exe
Return
;-------------------------------------------------------------
; обычная работа клавиши контекстного меню
~AppsKey::send, {AppsKey}
Return
;-------------------------------------------------------------
!CapsLock::
{
GetKeyState, state, CapsLock, T ; D if CapsLock is ON or U otherwise.
state := GetKeyState("Capslock", "T") ; True if CapsLock is ON, false otherwise.
if(state)
{
SetCapsLockState, off
Return
}
if(not state)
{
SetCapsLockState, on
Return
}
}
$CapsLock::LangSwitch(2)
;$CapsLock up::LangSwitch(2)
LangSwitch( iKeyDownUp=0 )
{
static tickLast
IfEqual,iKeyDownUp,1
{ tickLast=%A_TickCount%
return
}
IfEqual,iKeyDownUp,2
If( A_TickCount-tickLast>900 )
return
HKL:=DllCall("GetKeyboardLayout", "uint",GetThreadOfWindow(), "uint")
HKLnum:=DllCall("GetKeyboardLayoutList","uint",0,"uint",0)
VarSetCapacity( HKLlist, HKLnum*4, 0 )
DllCall("GetKeyboardLayoutList","uint",HKLnum,"uint",&HKLlist)
loop,%HKLnum%
{ if( NumGet( HKLlist, (A_Index-1)*4 ) = HKL )
{ HKL:=NumGet( HKLlist, mod(A_Index,HKLnum)*4 )
break
}
}
ControlGetFocus,ctl,A
SendMessage,0x50,0,HKL,%ctl%,A ;WM_INPUTLANGCHANGEREQUEST
;show traytip
LOCALE_SENGLANGUAGE=0x1001
LOCALE_SENGCOUNTRY=0x1002
VarSetCapacity( sKbd, 260, 0 )
VarSetCapacity( sCountry, 260, 0 )
DllCall("GetLocaleInfo","uint",HKL>>16,"uint",LOCALE_SENGLANGUAGE, "str",sKbd, "uint",260)
DllCall("GetLocaleInfo","uint",HKL & 0xFFFF,"uint",LOCALE_SENGCOUNTRY, "str",sCountry, "uint",260)
traytip,%sKbd%,%sCountry%
SetTimer,REMOVE_TOOLTIP,5000 ;0.5 second
return
REMOVE_TOOLTIP:
SetTimer,REMOVE_TOOLTIP,off
traytip
return
}
;returns first thread for the <processID>
;sets optional <List> to pipe | separated thread list for the <processID>
GetProcessThreadOrList( processID, byRef list="" )
{
;THREADENTRY32 {
THREADENTRY32_dwSize=0 ; DWORD
THREADENTRY32_cntUsage = 4 ;DWORD
THREADENTRY32_th32ThreadID = 8 ;DWORD
THREADENTRY32_th32OwnerProcessID = 12 ;DWORD
THREADENTRY32_tpBasePri = 16 ;LONG
THREADENTRY32_tpDeltaPri = 20 ;LONG
THREADENTRY32_dwFlags = 24 ;DWORD
THREADENTRY32_SIZEOF = 28
TH32CS_SNAPTHREAD=4
hProcessSnap := DllCall("CreateToolhelp32Snapshot","uint",TH32CS_SNAPTHREAD, "uint",0)
ifEqual,hProcessSnap,-1, return
VarSetCapacity( thE, THREADENTRY32_SIZEOF, 0 )
NumPut( THREADENTRY32_SIZEOF, thE )
ret=-1
if( DllCall("Thread32First","uint",hProcessSnap, "uint",&thE ))
loop
{
if( NumGet( thE ) >= THREADENTRY32_th32OwnerProcessID + 4)
if( NumGet( thE, THREADENTRY32_th32OwnerProcessID ) = processID )
{ th := NumGet( thE, THREADENTRY32_th32ThreadID )
IfEqual,ret,-1
ret:=th
list .= th "|"
}
NumPut( THREADENTRY32_SIZEOF, thE )
if( DllCall("Thread32Next","uint",hProcessSnap, "uint",&thE )=0)
break
}
DllCall("CloseHandle","uint",hProcessSnap)
StringTrimRight,list,list,1
return ret
}
; Returns thread owning specified window handle
; default = Active window
GetThreadOfWindow( hWnd=0 )
{
IfEqual,hWnd,0
hWnd:=WinExist("A")
DllCall("GetWindowThreadProcessId", "uint",hWnd, "uintp",id)
GetProcessThreadOrList( id, threads )
IfEqual,threads,
return 0
CB:=RegisterCallback("GetThreadOfWindowCallBack","Fast")
lRet=0
lParam:=hWnd
loop,parse,threads,|
{ NumPut( hWnd, lParam )
DllCall("EnumThreadWindows", "uint",A_LoopField, "uint",CB, "uint",&lParam)
if( NumGet( lParam )=true )
{ lRet:=A_LoopField
break
}
}
DllCall("GlobalFree", "uint", CB)
return lRet
}
GetThreadOfWindowCallBack( hWnd, lParam )
{
IfNotEqual,hWnd,% NumGet( 0+lParam )
return true
NumPut( true, 0+lParam )
return 0
}
LControl & $CapsLock::RecodeTextENRU()
RecodeTextENRU()
{
StringCaseSense On
AutoTrim,Off
clipSave:=clipAnsi()
send ^{Insert}
sleep,50
dest=
text:=clipAnsi()
StringCaseSense,On
prevCharToEN=0
; АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ
RUtoEN=F<DULT:PBQRKVYJGHCNEA{WXIO}SM">Zf,dult;pbqrkvyjghcnea[wxio]sm'.z
RUtoSP1=хъжэбюХЪЖЭБЮ.,/"№;:?
RUtoSP2=[];',.{}:"<>/?|@#$^&
;" ABCDEFGHIJKLMNOPQRSTUVWXYZ
ENtoRU=ФИСВУАПРШОЛДЬТЩЗЙКЫЕГМЦЧНЯфисвуапршолдьтщзйкыегмцчня
loop,parse,text
{
destChar=%A_LoopField%
; check explicit (non punctuations) ranges
ifGreaterOrEqual,A_LoopField,А
prevCharToEN=1
else if A_LoopField between A and Z
prevCharToEN=0
else if A_LoopField between a and z
prevCharToEN=0
; to Russian
ifEqual,prevCharToEN,0
{ StringGetPos,i,RUtoEN,%A_LoopField%
ifEqual,ErrorLevel,0
Transform,destChar,chr,% i + 0xC0
else
{ StringGetPos,i,RUtoSP2,%A_LoopField%
ifEqual,ErrorLevel,0
StringMid,destChar,RUtoSP1,% i+1, 1
}
}
; to English because nothing changed
ifEqual,destChar,%A_LoopField%
{
StringGetPos,i,ENtoRU,%A_LoopField%
ifEqual,ErrorLevel,0
Transform,destChar,chr,% i + (i>=26 ? 71 : 65)
else ; check .,;':"[]{}
{ StringGetPos,i,RUtoSP1,%A_LoopField%
ifEqual,ErrorLevel,0,StringMid,destChar,RUtoSP2,% i+1, 1
}
ifNotEqual,destChar,%A_LoopField%
prevCharToEN=1
}
dest=%dest%%destChar%
}
; decide compatibility of unicode clipboard
WinGetClass,cls,A
if cls in TMsgEditor,wndclass_desked_gsk
{
ControlGetFocus,cls,A
ifInString,cls,TXTRichEdit
clipSetUnicode(dest)
else
Clipboard=%dest%
}
else
clipSetUnicode(dest)
sleep,50
send +{Insert}
sleep 50
clipSetUnicode(clipSave)
LangSwitch()
}
; read unicode clipboard into ansi string
clipAnsi()
{
StringLen,L,Clipboard
L:=(L+1)*4
transform,ca_Clip,unicode
varSetCapacity(ca_WideText,L,0)
varSetCapacity(ca_AnsiText,L,0)
; Convert UTF-8 to UTF-16. CP_UTF8=65001
if dllCall("MultiByteToWideChar",uint,65001, uint,0, str,ca_Clip
, uint,-1, str,ca_WideText, uint,L/2)
dllCall("WideCharToMultiByte",uint,0, uint,0, str,ca_WideText
, uint,-1, str,ca_AnsiText, uint,L/2, uint,0, uint,0)
; Convert UTF-16 to ANSI. CP_ACP=0
return ca_AnsiText
}
;--------------------------------------------------------------
; copy ansi string to clipboard in unicode mode
clipSetUnicode(cu_AnsiText)
{
StringLen,L,cu_AnsiText
L:=(L+1)*4
varSetCapacity(cu_WideText,L,0)
varSetCapacity(cu_UTFtext,L,0)
; ANSI to UTF-16. CP_ACP=0
if dllCall("MultiByteToWideChar",uint,0, uint,0, str,cu_AnsiText
, uint,-1, str,cu_WideText, uint,L/2)
dllCall("WideCharToMultiByte",uint,65001, uint,0, str,cu_WideText
, uint,-1, str,cu_UTFtext, uint,L/2, uint,0, uint,0)
; Convert UTF-16 to UTF-8. CP_UTF8=65001
transform,clipboard,unicode,%cu_UTFtext%
}
; раскладка вима для навигации
CapsLock & h:: send {Left}

