To do this, I call the following hotkeys:
Ctrl + Shift + Left
Ctrl + Insert
... process ...
Shift + Insert
It's unstable. I tried for a long time to adjust the pauses between keystrokes, but there is no pattern in the behavior, the action occurs every other time. Now I would like to use this for the AutoCompletion program. The program on AutoIt3 works reliably, it will work 10 times out of 10. It has a key sticking check, but that's not the point, even if the code below fails the second time, but it fails the first time. That is, key sticking can be excluded.
Code: Select all
; AZJIO
; convert text typed in the wrong keyboard layout
EnableExplicit
Global En$ = "`qwertyuiop[]asdfghjkl;'zxcvbnm,./~QWERTYUIOP{}ASDFGHJKL:" + Chr(34) + "|ZXCVBNM<>?@#$^&"
Global Ru$ = "ёйцукенгшщзхъфывапролджэячсмитьбю.ЁЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭ/ЯЧСМИТЬБЮ," + Chr(34) + "№;:?"
Global EnT$ = "qwertyuiopasdfghjklzxcvbnm"
Global RuT$ = "ёйцукенгшщзхъфывапролджэячсмитьбю"
Global Lang = 0
Global Dim aSel.s{1}(0)
#GadgetHK = 0
#GadgetBtn = 1
#HK_ID = 1001
Define HotkeyCode
Define VirtKey
Define ModKey
; Macro MAKELONG(loword, hiword)
; (hiword << 16 | loword)
; EndMacro
Procedure.s TrimLeft(*a, n)
Protected *p.string = @*a
*p\s = Right(*p\s, Len(*p\s) - n)
EndProcedure
Procedure StrToArrLetter(Array Arr.s{1}(1), String$)
Protected LenStr, i
LenStr = Len(String$)
If LenStr
ReDim Arr(LenStr - 1)
PokeS(Arr(), String$, -1, #PB_String_NoZero)
EndIf
ProcedureReturn
EndProcedure
Procedure.s GetKey(HotkeyCode)
Protected HiW, Key.s
HiW = HotkeyCode >> 16
If HiW & #HOTKEYF_CONTROL
Key + " + Ctrl"
EndIf
If HiW & #HOTKEYF_SHIFT
Key + " + Shift"
EndIf
If HiW & #HOTKEYF_ALT
Key + " + Alt"
EndIf
Key + " + " + Chr(HotkeyCode & $FFFF)
TrimLeft(@Key, 3)
ProcedureReturn Key
EndProcedure
Procedure GetModKey(MOD)
Protected ModKey = 0
If MOD & #HOTKEYF_SHIFT
ModKey | #MOD_SHIFT
EndIf
If MOD & #HOTKEYF_CONTROL
ModKey | #MOD_CONTROL
EndIf
If MOD & #HOTKEYF_ALT
ModKey | #MOD_ALT
EndIf
ProcedureReturn ModKey
EndProcedure
; Ctrl + Insert
Procedure SendHotKey2(mod, key, sleep = 20, sleep1=1)
keybd_event_(mod,0,#KEYEVENTF_EXTENDEDKEY,0)
Delay(sleep1)
keybd_event_(key, 0, #KEYEVENTF_EXTENDEDKEY, 0)
Delay(sleep)
keybd_event_(key,0,#KEYEVENTF_KEYUP | #KEYEVENTF_EXTENDEDKEY,0)
Delay(sleep1)
keybd_event_(mod,0,#KEYEVENTF_KEYUP | #KEYEVENTF_EXTENDEDKEY,0)
EndProcedure
; Ctrl + Insert
; I was hoping that it would work faster
Procedure SendHotKeyCtrlIns(sleep = 20, sleep1=110)
Protected hWnd = GetForegroundWindow_()
; keybd_event_(#VK_CONTROL,0,0,0)
SendMessage_(hWnd, #WM_KEYDOWN, #VK_CONTROL, 0)
Delay(sleep1)
SendMessage_(hWnd, #WM_KEYDOWN, #VK_INSERT, 0)
Delay(sleep1)
SendMessage_(hWnd, #WM_KEYUP, #VK_INSERT, 0)
Delay(sleep1)
; keybd_event_(#VK_CONTROL,0,#KEYEVENTF_KEYUP,0)
SendMessage_(hWnd, #WM_KEYUP, #VK_CONTROL, 0)
EndProcedure
; Ctrl + Shift + Left
; Procedure SendHotKeyCtrlShiftL(sleep = 20, sleep1=3)
; keybd_event_(#VK_CONTROL,0,0,0)
; Delay(sleep1)
; keybd_event_(#VK_SHIFT,0,0,0)
; Delay(sleep1)
; keybd_event_(#VK_LEFT, 0, 0, 0)
; Delay(sleep)
; keybd_event_(#VK_LEFT,0,#KEYEVENTF_KEYUP,0)
; Delay(sleep1)
; keybd_event_(#VK_SHIFT,0,#KEYEVENTF_KEYUP,0)
; Delay(sleep1)
; keybd_event_(#VK_CONTROL,0,#KEYEVENTF_KEYUP,0)
; EndProcedure
; Ctrl + Shift + Left
Procedure SendHotKeyCtrlShiftL(sleep = 20, sleep1=3)
keybd_event_(#VK_SHIFT,0,#KEYEVENTF_EXTENDEDKEY,0)
Delay(sleep1)
keybd_event_(#VK_CONTROL,0,#KEYEVENTF_EXTENDEDKEY,0)
Delay(sleep1)
keybd_event_(#VK_LEFT, 0, #KEYEVENTF_EXTENDEDKEY, 0)
Delay(sleep)
keybd_event_(#VK_LEFT,0,#KEYEVENTF_KEYUP | #KEYEVENTF_EXTENDEDKEY,0)
Delay(sleep1)
keybd_event_(#VK_SHIFT,0,#KEYEVENTF_KEYUP | #KEYEVENTF_EXTENDEDKEY,0)
Delay(sleep1)
keybd_event_(#VK_CONTROL,0,#KEYEVENTF_KEYUP | #KEYEVENTF_EXTENDEDKEY,0)
EndProcedure
Procedure _Re(mode)
Protected Old_bufer$, Selected_Text$, Letter$, i, New_Text$, n, Layout
Old_bufer$ = GetClipboardText()
SetClipboardText("")
SendHotKey2(#VK_CONTROL, #VK_INSERT, 110, 50)
; SendHotKeyCtrlIns()
Selected_Text$ = GetClipboardText()
If Not Len(Left(Selected_Text$ ,1))
SendHotKeyCtrlShiftL()
Delay(90)
SendHotKey2(#VK_CONTROL, #VK_INSERT, 110, 50)
; SendHotKeyCtrlIns()
Delay(30)
Selected_Text$ = GetClipboardText()
EndIf
If Not Len(Left(Selected_Text$ ,1))
ProcedureReturn
EndIf
; ищем справа-налево последний валидный символ в тексте, по которому можно определить язык
Lang = 0
Letter$ = Mid(Selected_Text$, i, 1)
For i = Len(Selected_Text$) To 1 Step -1
If FindString(EnT$, Letter$)
Lang = 409
Break
EndIf
If FindString(RuT$, Letter$)
Lang = 419
Break
EndIf
Next
If Not Lang
ProcedureReturn
EndIf
StrToArrLetter(aSel(), Selected_Text$)
New_Text$ = ""
Select mode
Case 0
; if Russian, then change to English.
If Lang = 419
For i = 0 To ArraySize(aSel())
n = FindString(Ru$, aSel(i), 1, #PB_String_CaseSensitive)
If n = 0
New_Text$ + aSel(i)
Else
New_Text$ + Mid(En$, n, 1)
EndIf
Next
Layout = LoadKeyboardLayout_("00000409", #KLF_ACTIVATE)
SendMessage_(GetForegroundWindow_(), #WM_INPUTLANGCHANGEREQUEST, 1, Layout)
; if English, then change to Russian
ElseIf Lang = 409
For i = 0 To ArraySize(aSel())
n = FindString(En$, aSel(i), 1, #PB_String_CaseSensitive)
If n = 0
New_Text$ + aSel(i)
Else
New_Text$ + Mid(Ru$, n, 1)
EndIf
Next
Layout = LoadKeyboardLayout_("00000419", #KLF_ACTIVATE)
SendMessage_(GetForegroundWindow_(), #WM_INPUTLANGCHANGEREQUEST, 1, Layout)
EndIf
; Case 1
; SendHotKey2(#VK_CONTROL, #VK_INSERT, 200, 100)
; Case 2
; SendHotKey2(#VK_SHIFT, #VK_HOME)
; Delay(100)
; SendHotKey2(#VK_CONTROL, #VK_INSERT, 200, 100)
EndSelect
If New_Text$ <> Selected_Text$
SetClipboardText(New_Text$)
Delay(10)
SendHotKey2(#VK_SHIFT, #VK_INSERT, 110, 30)
Else
keybd_event_(#VK_RIGHT, 0, 0, 0)
Delay(10)
keybd_event_(#VK_RIGHT,0,#KEYEVENTF_KEYUP,0)
EndIf
; Delay(90)
; SendKeys(0,"PureBasic 5.70 LTS (x86) - я текст корекция.pb","{CONTROLDOWN}{INSERT}{CONTROLUP}")
; Selected_Text$ = GetClipboardText()
EndProcedure
If OpenWindow(0, 0, 0, 240, 70, "Gadget Hotkeys", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ShortcutGadget(#GadgetHK, 10, 10, 200, 25, #PB_Shortcut_Alt | #PB_Shortcut_J)
; SetGadgetState(0 , #PB_Shortcut_Control | #PB_Shortcut_B) ; can be inserted this way
ButtonGadget(#GadgetBtn, 10, 40, 100, 28, "Apply")
Repeat
Select WaitWindowEvent()
Case #WM_HOTKEY
Select EventwParam()
Case #HK_ID
_Re(0)
Debug "Intercepted hotkey 1"
Case 2
Debug "Intercepted hotkey 2"
Case 3
Debug "Intercepted hotkey 3"
EndSelect
Case #PB_Event_Gadget
Select EventGadget()
Case #GadgetBtn
HotkeyCode = GetGadgetState(#GadgetHK)
If Not HotkeyCode
Debug "Cancel the hotkey (Backspace)"
UnregisterHotKey_(WindowID(0), #HK_ID)
EndIf
Debug HotkeyCode
VirtKey = HotkeyCode & $FFFF ; LoWord
ModKey = GetModKey(HotkeyCode >> 16)
Debug GetKey(HotkeyCode)
; Debug SendMessage_(GadgetID(#GadgetHK), #HKM_GETHOTKEY, 0, 0)
; If MAKELONG(loword, hiword)
UnregisterHotKey_(WindowID(0), #HK_ID) ; reassignment works without unregisteringreassignment works without unregistering
If Not RegisterHotKey_(WindowID(0), #HK_ID, ModKey, VirtKey)
Debug "Failed to register hotkey"
EndIf
EndSelect
Case #PB_Event_CloseWindow
UnregisterHotKey_(WindowID(0), #HK_ID)
CloseWindow(0)
End
EndSelect
ForEver
EndIf
.
Code: Select all
; AZJIO
; convert text typed in the wrong keyboard layout
EnableExplicit
Global En$ = "`qwertyuiop[]asdfghjkl;'zxcvbnm,./~QWERTYUIOP{}ASDFGHJKL:" + Chr(34) + "|ZXCVBNM<>?@#$^&"
Global Ru$ = "ёйцукенгшщзхъфывапролджэячсмитьбю.ЁЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭ/ЯЧСМИТЬБЮ," + Chr(34) + "№;:?"
Global EnT$ = "qwertyuiopasdfghjklzxcvbnm"
Global RuT$ = "ёйцукенгшщзхъфывапролджэячсмитьбю"
Global Lang = 0
Global Dim aSel.s{1}(0)
#GadgetHK = 0
#GadgetBtn = 1
#HK_ID = 1001
Define HotkeyCode
Define VirtKey
Define ModKey
; Macro MAKELONG(loword, hiword)
; (hiword << 16 | loword)
; EndMacro
Procedure.s TrimLeft(*a, n)
Protected *p.string = @*a
*p\s = Right(*p\s, Len(*p\s) - n)
EndProcedure
Procedure StrToArrLetter(Array Arr.s{1}(1), String$)
Protected LenStr, i
LenStr = Len(String$)
If LenStr
ReDim Arr(LenStr - 1)
PokeS(Arr(), String$, -1, #PB_String_NoZero)
EndIf
ProcedureReturn
EndProcedure
Procedure.s GetKey(HotkeyCode)
Protected HiW, Key.s
HiW = HotkeyCode >> 16
If HiW & #HOTKEYF_CONTROL
Key + " + Ctrl"
EndIf
If HiW & #HOTKEYF_SHIFT
Key + " + Shift"
EndIf
If HiW & #HOTKEYF_ALT
Key + " + Alt"
EndIf
Key + " + " + Chr(HotkeyCode & $FFFF)
TrimLeft(@Key, 3)
ProcedureReturn Key
EndProcedure
Procedure GetModKey(MOD)
Protected ModKey = 0
If MOD & #HOTKEYF_SHIFT
ModKey | #MOD_SHIFT
EndIf
If MOD & #HOTKEYF_CONTROL
ModKey | #MOD_CONTROL
EndIf
If MOD & #HOTKEYF_ALT
ModKey | #MOD_ALT
EndIf
ProcedureReturn ModKey
EndProcedure
Global Dim KeyArray.INPUT( 0 )
Global *G_key.INPUT = @KeyArray( 0 )
*G_key\type = #INPUT_KEYBOARD
Procedure ReleaseKey()
While GetAsyncKeyState_(#VK_SHIFT)
*G_key\ki\wVk = #VK_SHIFT
*G_key\ki\dwFlags = #KEYEVENTF_KEYUP
SendInput_( 1, KeyArray(), 40 )
Delay(100)
Wend
While GetAsyncKeyState_(#VK_CONTROL)
*G_key\ki\wVk = #VK_CONTROL
*G_key\ki\dwFlags = #KEYEVENTF_KEYUP
SendInput_( 1, KeyArray(), 40 )
Delay(100)
Wend
While GetAsyncKeyState_(#VK_MENU)
*G_key\ki\wVk = #VK_MENU
*G_key\ki\dwFlags = #KEYEVENTF_KEYUP
SendInput_( 1, KeyArray(), 40 )
Delay(100)
Wend
EndProcedure
Procedure SendNormalKey( keycode )
*G_key\ki\wVk = keycode
*G_key\ki\dwFlags = 0 ; 0 for key press.
SendInput_( 1, KeyArray(), 40 )
*G_key\ki\wVk = keycode
*G_key\ki\dwFlags = #KEYEVENTF_KEYUP ; #KEYEVENTF_KEYUP for key release.
SendInput_( 1, KeyArray(), 40 )
EndProcedure
Procedure SendSpecialKey( keycode, special_keycode )
ReleaseKey()
*G_key\ki\wVk = special_keycode
*G_key\ki\dwFlags = 0
SendInput_( 1, KeyArray(), 40 )
*G_key\ki\wVk = keycode
*G_key\ki\dwFlags = 0
SendInput_( 1, KeyArray(), 40 )
*G_key\ki\wVk = keycode
*G_key\ki\dwFlags = #KEYEVENTF_KEYUP
SendInput_( 1, KeyArray(), 40 )
*G_key\ki\wVk = special_keycode
*G_key\ki\dwFlags = #KEYEVENTF_KEYUP
SendInput_( 1, KeyArray(), 40 )
EndProcedure
Procedure SendSpecialKey2( keycode, special_keycode, special_keycode2 )
ReleaseKey()
*G_key\ki\wVk = special_keycode
*G_key\ki\dwFlags = 0
SendInput_( 1, KeyArray(), 40 )
*G_key\ki\wVk = special_keycode2
*G_key\ki\dwFlags = 0
SendInput_( 1, KeyArray(), 40 )
*G_key\ki\wVk = keycode
*G_key\ki\dwFlags = 0
SendInput_( 1, KeyArray(), 40 )
*G_key\ki\wVk = keycode
*G_key\ki\dwFlags = #KEYEVENTF_KEYUP
SendInput_( 1, KeyArray(), 40 )
*G_key\ki\wVk = special_keycode2
*G_key\ki\dwFlags = #KEYEVENTF_KEYUP
SendInput_( 1, KeyArray(), 40 )
*G_key\ki\wVk = special_keycode
*G_key\ki\dwFlags = #KEYEVENTF_KEYUP
SendInput_( 1, KeyArray(), 40 )
EndProcedure
Procedure _Re(mode)
Protected Old_bufer$, Selected_Text$, Letter$, i, New_Text$, n, Layout
Old_bufer$ = GetClipboardText()
SetClipboardText("")
SendSpecialKey(#VK_INSERT, #VK_CONTROL)
Selected_Text$ = GetClipboardText()
If Not Len(Left(Selected_Text$ ,1))
SendSpecialKey2(#VK_LEFT, #VK_CONTROL, #VK_SHIFT)
Delay(90)
SendSpecialKey(#VK_INSERT, #VK_CONTROL)
Delay(30)
Selected_Text$ = GetClipboardText()
EndIf
If Not Len(Left(Selected_Text$ ,1))
ProcedureReturn
EndIf
; ищем справа-налево последний валидный символ в тексте, по которому можно определить язык
Lang = 0
Letter$ = Mid(Selected_Text$, i, 1)
For i = Len(Selected_Text$) To 1 Step -1
If FindString(EnT$, Letter$)
Lang = 409
Break
EndIf
If FindString(RuT$, Letter$)
Lang = 419
Break
EndIf
Next
If Not Lang
ProcedureReturn
EndIf
StrToArrLetter(aSel(), Selected_Text$)
New_Text$ = ""
Select mode
Case 0
; if Russian, then change to English.
If Lang = 419
For i = 0 To ArraySize(aSel())
n = FindString(Ru$, aSel(i), 1, #PB_String_CaseSensitive)
If n = 0
New_Text$ + aSel(i)
Else
New_Text$ + Mid(En$, n, 1)
EndIf
Next
Layout = LoadKeyboardLayout_("00000409", #KLF_ACTIVATE)
SendMessage_(GetForegroundWindow_(), #WM_INPUTLANGCHANGEREQUEST, 1, Layout)
; if English, then change to Russian
ElseIf Lang = 409
For i = 0 To ArraySize(aSel())
n = FindString(En$, aSel(i), 1, #PB_String_CaseSensitive)
If n = 0
New_Text$ + aSel(i)
Else
New_Text$ + Mid(Ru$, n, 1)
EndIf
Next
Layout = LoadKeyboardLayout_("00000419", #KLF_ACTIVATE)
SendMessage_(GetForegroundWindow_(), #WM_INPUTLANGCHANGEREQUEST, 1, Layout)
EndIf
; Case 1
; SendSpecialKey(#VK_INSERT, #VK_CONTROL)
; Case 2
; SendHotKey2(#VK_SHIFT, #VK_HOME)
; SendSpecialKey(#VK_HOME, #VK_SHIFT)
; Delay(100)
; SendSpecialKey(#VK_INSERT, #VK_CONTROL)
EndSelect
If New_Text$ <> Selected_Text$
SetClipboardText(New_Text$)
Delay(10)
SendSpecialKey(#VK_INSERT, #VK_SHIFT)
Else
SendNormalKey(#VK_RIGHT)
EndIf
EndProcedure
If OpenWindow(0, 0, 0, 240, 70, "Gadget Hotkeys", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ShortcutGadget(#GadgetHK, 10, 10, 200, 25, #PB_Shortcut_Alt | #PB_Shortcut_J)
; SetGadgetState(0 , #PB_Shortcut_Control | #PB_Shortcut_B) ; can be inserted this way
ButtonGadget(#GadgetBtn, 10, 40, 100, 28, "Apply")
Repeat
Select WaitWindowEvent()
Case #WM_HOTKEY
Select EventwParam()
Case #HK_ID
_Re(0)
Debug "Intercepted hotkey 1"
Case 2
Debug "Intercepted hotkey 2"
Case 3
Debug "Intercepted hotkey 3"
EndSelect
Case #PB_Event_Gadget
Select EventGadget()
Case #GadgetBtn
HotkeyCode = GetGadgetState(#GadgetHK)
If Not HotkeyCode
Debug "Cancel the hotkey (Backspace)"
UnregisterHotKey_(WindowID(0), #HK_ID)
EndIf
Debug HotkeyCode
VirtKey = HotkeyCode & $FFFF ; LoWord
ModKey = GetModKey(HotkeyCode >> 16)
Debug GetKey(HotkeyCode)
; Debug SendMessage_(GadgetID(#GadgetHK), #HKM_GETHOTKEY, 0, 0)
; If MAKELONG(loword, hiword)
UnregisterHotKey_(WindowID(0), #HK_ID) ; reassignment works without unregisteringreassignment works without unregistering
If Not RegisterHotKey_(WindowID(0), #HK_ID, ModKey, VirtKey)
Debug "Failed to register hotkey"
EndIf
EndSelect
Case #PB_Event_CloseWindow
UnregisterHotKey_(WindowID(0), #HK_ID)
CloseWindow(0)
End
EndSelect
ForEver
EndIf