LAttilaD Posted July 31, 2010 Share Posted July 31, 2010 I'm working on a keyboard remapper and met a strange problem. All letter keys, both shifted and unshifted, are mapped to a function that begins with the following: $ch = @HotKeyPressed $shift = False If StringLeft($ch, 1) = "+" Then $ch = StringRight($ch, 1) $shift = True While(_IsPressed("10")) WEnd EndIf Here we determine if a shifted key is pressed, and if yes, we wait until it's up again. Without the While loop, Shift had a habit to stay pressed after a shifted letter. Executing send("{shiftdown}{shiftup}") didn't help. So I added the While loop as shown above. Now typing Hello results in Hello (and not HELLO), but typing USA gives ASU… My fingers are programmed to type all-caps words like USA by holding Shift, typing the letters and releasing Shift, but after adding the While loop it turns all-caps words backwards. Let me tell you what happens later in the function, to give a good overview on the story. We determine what letter should the keypress result in. (It's a multi-layout remapper with an autocaps feature.) Then we turn all hotkeys off, send the letter out and turn the hotkeys on again. Turning off is necessary because pressing a letter key that gives the same letter causes an infinite loop. While the hotkeys are pressed, a Blockinput is given to get rid of undefined meanings of the keys to appear. I believe something is happening with the keyboard buffer, but I never met such a behavior. Can anybody help? Thank you in advance. Láng Attila D., LAttilaD.org Link to comment Share on other sites More sharing options...
BugFix Posted July 31, 2010 Share Posted July 31, 2010 You can Hook the messages: Shift Down/Up (left/right shift key) and check capslock. expandcollapse popup#include <WinAPI.au3> #include <WindowsConstants.au3> #include <StructureConstants.au3> OnAutoItExitRegister('OnAutoItExit') Opt('MustDeclareVars', 1) Global $hStub_KeyProc = DllCallbackRegister("_KeyProc", "long", "int;wparam;lparam") Global $hmod = _WinAPI_GetModuleHandle(0) Global $hHook = _WinAPI_SetWindowsHookEx($WH_KEYBOARD_LL, DllCallbackGetPtr($hStub_KeyProc), $hmod) Global $active = False, $isShift = False, $isCapsLock = False _Main() Func _Main() Local $gui = GUICreate('Test', 400, 300) GUICtrlCreateInput('', 10, 30, 380) GUISetState() Do If BitAND(WinGetState($gui), 8) Then ; so the Hook takes only effect on this GUI $active = True Else $active = False EndIf If $isShift Then ConsoleWrite('SHIFT' & @CRLF) If $isCapsLock Then ConsoleWrite('CAPSLOCK' & @CRLF) If $isShift And $isCapsLock Then ConsoleWrite('SHIFT + CAPSLOCK = like NO SHIFT' & @CRLF) Until GUIGetMsg() = -3 EndFunc Func _Exit() Exit EndFunc ;=========================================================== ; callback function ;=========================================================== Func _KeyProc($nCode, $wParam, $lParam) Local $tKEYHOOKS, $vkCode, $ret $ret = DllCall("user32.dll","long","GetKeyState","long", 0x14) If $ret[0] Then $isCapsLock = True Else $isCapsLock = False EndIf $tKEYHOOKS = DllStructCreate($tagKBDLLHOOKSTRUCT, $lParam) If $nCode < 0 Or Not $active Then Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam) $vkCode = DllStructGetData($tKEYHOOKS, "vkCode") If $wParam = $WM_KEYDOWN Then If $vkCode = 0xA0 Or $vkCode = 0xA1 Then $isShift = True ; left or right Shift-Key down EndIf Else Switch DllStructGetData($tKEYHOOKS, "flags") Case 0x80, 0x81 ; 0x80= UP for 'normal' keys and left pairs, 0x81= UP for right pairs If $vkCode = 0xA0 Or $vkCode = 0xA1 Then $isShift = False ; LShift, RShift EndSwitch EndIf Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam) EndFunc Func OnAutoItExit() _WinAPI_UnhookWindowsHookEx($hHook) DllCallbackFree($hStub_KeyProc) EndFunc Best Regards BugFix Link to comment Share on other sites More sharing options...
LAttilaD Posted July 31, 2010 Author Share Posted July 31, 2010 You can Hook the messages: Shift Down/Up (left/right shift key) and check capslock. Well, Bugfix, thank you for the help, but it seems not working yet. I've copied parts from my code into it and tried it. Here is the resulting code. Please start it, hold Shift and type a word, then release Shift. You'll get your word backwards. Should I modify my code to get along with yours? If yes, how? (Note that parts of my code are marked with "my parts" remarks. Only modifications in your code was commenting out MustDeclareVars, just to avoid the need to declare vars in my code, and adding an include for misc.au3, to make _IsPressed work.) expandcollapse popup#include <misc.au3> #include <WinAPI.au3> #include <WindowsConstants.au3> #include <StructureConstants.au3> OnAutoItExitRegister('OnAutoItExit') ;Opt('MustDeclareVars', 1) Global $hStub_KeyProc = DllCallbackRegister("_KeyProc", "long", "int;wparam;lparam") Global $hmod = _WinAPI_GetModuleHandle(0) Global $hHook = _WinAPI_SetWindowsHookEx($WH_KEYBOARD_LL, DllCallbackGetPtr($hStub_KeyProc), $hmod) Global $active = False, $isShift = False, $isCapsLock = False ;my parts Const $alphabet = "qwertyuiopasdfghjklzxcvbnm" Dim $capsmode, $caps, $keyson, $layout, $langindex, $gui, $list, $okbutton, $languages, $buffer keyson() ;end my parts _Main() Func _Main() Local $gui = GUICreate('Test', 400, 300) GUICtrlCreateInput('', 10, 30, 380) GUISetState() Do If BitAND(WinGetState($gui), 8) Then ; so the Hook takes only effect on this GUI $active = True Else $active = False EndIf If $isShift Then ConsoleWrite('SHIFT' & @CRLF) If $isCapsLock Then ConsoleWrite('CAPSLOCK' & @CRLF) If $isShift And $isCapsLock Then ConsoleWrite('SHIFT + CAPSLOCK = like NO SHIFT' & @CRLF) Until GUIGetMsg() = -3 EndFunc Func _Exit() Exit EndFunc ;=========================================================== ; callback function ;=========================================================== Func _KeyProc($nCode, $wParam, $lParam) Local $tKEYHOOKS, $vkCode, $ret $ret = DllCall("user32.dll","long","GetKeyState","long", 0x14) If $ret[0] Then $isCapsLock = True Else $isCapsLock = False EndIf $tKEYHOOKS = DllStructCreate($tagKBDLLHOOKSTRUCT, $lParam) If $nCode < 0 Or Not $active Then Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam) $vkCode = DllStructGetData($tKEYHOOKS, "vkCode") If $wParam = $WM_KEYDOWN Then If $vkCode = 0xA0 Or $vkCode = 0xA1 Then $isShift = True ; left or right Shift-Key down EndIf Else Switch DllStructGetData($tKEYHOOKS, "flags") Case 0x80, 0x81 ; 0x80= UP for 'normal' keys and left pairs, 0x81= UP for right pairs If $vkCode = 0xA0 Or $vkCode = 0xA1 Then $isShift = False ; LShift, RShift EndSwitch EndIf Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam) EndFunc Func OnAutoItExit() _WinAPI_UnhookWindowsHookEx($hHook) DllCallbackFree($hStub_KeyProc) EndFunc ;----my parts Func letter_hu() $ch = @HotKeyPressed $shift = False If StringLeft($ch, 1) = "+" Then $ch = StringRight($ch, 1) $shift = True While(_IsPressed("10")) WEnd EndIf If $shift And $ch = "`" Then $ch = "0" Else $i = StringInStr("`0-=\[];'" & $alphabet, $ch) $ch = StringMid("uöüóíoúéá" & $alphabet, $i, 1) $ch = StringMid("ûöüóíõúéá" & $alphabet, $i, 1) EndIf If ($capsmode = True And $caps = True) Or $shift = True Then $ch = StringUpper($ch) EndIf keysoff(False) Send($ch) $caps = False keyson() EndFunc ;==>letter_hu Func keyson() HotKeySet("a", "letter_hu") HotKeySet("b", "letter_hu") HotKeySet("c", "letter_hu") HotKeySet("d", "letter_hu") HotKeySet("e", "letter_hu") HotKeySet("f", "letter_hu") HotKeySet("g", "letter_hu") HotKeySet("h", "letter_hu") HotKeySet("i", "letter_hu") HotKeySet("j", "letter_hu") HotKeySet("k", "letter_hu") HotKeySet("l", "letter_hu") HotKeySet("m", "letter_hu") HotKeySet("n", "letter_hu") HotKeySet("o", "letter_hu") HotKeySet("p", "letter_hu") HotKeySet("q", "letter_hu") HotKeySet("r", "letter_hu") HotKeySet("s", "letter_hu") HotKeySet("t", "letter_hu") HotKeySet("u", "letter_hu") HotKeySet("v", "letter_hu") HotKeySet("w", "letter_hu") HotKeySet("x", "letter_hu") HotKeySet("y", "letter_hu") HotKeySet("z", "letter_hu") HotKeySet("`", "letter_hu") HotKeySet("0", "letter_hu") HotKeySet("-", "letter_hu") HotKeySet("=", "letter_hu") HotKeySet("\", "letter_hu") HotKeySet("[", "letter_hu") HotKeySet("]", "letter_hu") HotKeySet(";", "letter_hu") HotKeySet("'", "letter_hu") HotKeySet("+a", "letter_hu") HotKeySet("+b", "letter_hu") HotKeySet("+c", "letter_hu") HotKeySet("+d", "letter_hu") HotKeySet("+e", "letter_hu") HotKeySet("+f", "letter_hu") HotKeySet("+g", "letter_hu") HotKeySet("+h", "letter_hu") HotKeySet("+i", "letter_hu") HotKeySet("+j", "letter_hu") HotKeySet("+k", "letter_hu") HotKeySet("+l", "letter_hu") HotKeySet("+m", "letter_hu") HotKeySet("+n", "letter_hu") HotKeySet("+o", "letter_hu") HotKeySet("+p", "letter_hu") HotKeySet("+q", "letter_hu") HotKeySet("+r", "letter_hu") HotKeySet("+s", "letter_hu") HotKeySet("+t", "letter_hu") HotKeySet("+u", "letter_hu") HotKeySet("+v", "letter_hu") HotKeySet("+w", "letter_hu") HotKeySet("+x", "letter_hu") HotKeySet("+y", "letter_hu") HotKeySet("+z", "letter_hu") HotKeySet("+`", "letter_hu") HotKeySet("+0", "letter_hu") HotKeySet("+-", "letter_hu") HotKeySet("+=", "letter_hu") HotKeySet("+\", "letter_hu") HotKeySet("+[", "letter_hu") HotKeySet("+]", "letter_hu") HotKeySet("+;", "letter_hu") HotKeySet("+'", "letter_hu") BlockInput(0) EndFunc ;==>keyson Func keysoff($quick = True) BlockInput(1) HotKeySet("a") HotKeySet("b") HotKeySet("c") HotKeySet("d") HotKeySet("e") HotKeySet("f") HotKeySet("g") HotKeySet("h") HotKeySet("i") HotKeySet("j") HotKeySet("k") HotKeySet("l") HotKeySet("m") HotKeySet("n") HotKeySet("o") HotKeySet("p") HotKeySet("q") HotKeySet("r") HotKeySet("s") HotKeySet("t") HotKeySet("u") HotKeySet("v") HotKeySet("w") HotKeySet("x") HotKeySet("y") HotKeySet("z") HotKeySet("`") HotKeySet("0") HotKeySet("-") HotKeySet("=") HotKeySet("\") HotKeySet("[") HotKeySet("]") HotKeySet(";") HotKeySet("'") HotKeySet("+a") HotKeySet("+b") HotKeySet("+c") HotKeySet("+d") HotKeySet("+e") HotKeySet("+f") HotKeySet("+g") HotKeySet("+h") HotKeySet("+i") HotKeySet("+j") HotKeySet("+k") HotKeySet("+l") HotKeySet("+m") HotKeySet("+n") HotKeySet("+o") HotKeySet("+p") HotKeySet("+q") HotKeySet("+r") HotKeySet("+s") HotKeySet("+t") HotKeySet("+u") HotKeySet("+v") HotKeySet("+w") HotKeySet("+x") HotKeySet("+y") HotKeySet("+z") HotKeySet("+`") HotKeySet("+0") HotKeySet("+-") HotKeySet("+=") HotKeySet("+\") HotKeySet("+[") HotKeySet("+]") HotKeySet("+;") HotKeySet("+'") HotKeySet(".") HotKeySet("+1") HotKeySet("+/") HotKeySet("+`") HotKeySet("1") HotKeySet("2") HotKeySet("3") HotKeySet("4") HotKeySet("5") HotKeySet("6") HotKeySet("7") HotKeySet("8") HotKeySet("9") HotKeySet("+3") HotKeySet("+4") HotKeySet("+5") HotKeySet("+6") HotKeySet("+7") HotKeySet("+8") HotKeySet("+9") HotKeySet(",") HotKeySet("/") HotKeySet("+,") HotKeySet("+.") HotKeySet("#[") HotKeySet("#,") HotKeySet("#.") HotKeySet("#/") HotKeySet("#;") HotKeySet("#'") EndFunc ;==>keysoff Láng Attila D., LAttilaD.org Link to comment Share on other sites More sharing options...
BugFix Posted July 31, 2010 Share Posted July 31, 2010 Ah, I've missunderstand your problem. Now it's clear. In this case you don't need a hook. your solution works. But if you use _IsPressed in an loop, new chars will added at front. So you get an reverse string. I've changed that and meked it also shorter. expandcollapse popup#include <misc.au3> ;my parts Const $alphabet = "qwertyuiopasdfghjklzxcvbnm" Dim $capsmode, $caps, $keyson, $layout, $langindex, $gui, $list, $okbutton, $languages, $buffer keyson() ;end my parts _Main() Func _Main() Local $gui = GUICreate('Test', 400, 300) GUICtrlCreateInput('', 10, 30, 380) GUISetState() Do Until GUIGetMsg() = -3 EndFunc ;----my parts Func letter_hu() $ch = @HotKeyPressed $shift = False If StringLeft($ch, 1) = "+" Then $ch = StringRight($ch, 1) ;~ $shift = True ;~ While(_IsPressed("10")) <== this loop buffers the shifted string revers ;~ WEnd ;#################################### If _IsPressed("10") Then $shift = True Else $shift = False EndIf ;#################################### EndIf If $shift And $ch = "`" Then $ch = "0" Else $i = StringInStr("`0-=\[];'" & $alphabet, $ch) $ch = StringMid("uöüóíoúéá" & $alphabet, $i, 1) $ch = StringMid("ûöüóíõúéá" & $alphabet, $i, 1) EndIf If ($capsmode = True And $caps = True) Or $shift = True Then $ch = StringUpper($ch) EndIf keysoff(False) Send($ch) $caps = False keyson() EndFunc ;==>letter_hu Func keyson() For $i = 45 To 122 If $i = 58 Or $i = 60 Then ContinueLoop If $i = 62 Then $i = 91 If $i = 94 Or $i = 95 Then ContinueLoop HotKeySet(Chr($i), "letter_hu") HotKeySet('+' & Chr($i), "letter_hu") Next BlockInput(0) EndFunc ;==>keyson Func keysoff($quick = True) BlockInput(1) For $i = 45 To 122 If $i = 58 Or $i = 60 Then ContinueLoop If $i = 62 Then $i = 91 If $i = 94 Or $i = 95 Then ContinueLoop HotKeySet(Chr($i)) HotKeySet('+' & Chr($i)) Next EndFunc ;==>keysoff Best Regards BugFix Link to comment Share on other sites More sharing options...
LAttilaD Posted July 31, 2010 Author Share Posted July 31, 2010 (edited) Do I see it well the only difference is this part? ;~ While(_IsPressed("10")) <== this loop buffers the shifted string revers ;~ WEnd ;#################################### If _IsPressed("10") Then $shift = True Else $shift = False EndIf Now, I'm sorry, but the original problem is restored. All-caps strings don't reverse this way, but Shift tends to glue again. Type SaSaSaSaSaSaSa, carefully raising Shift before the a's, and sometimes you will get uppercase A's. (Edit: missed Autoit tags for first.) Edited July 31, 2010 by LAttilaD Láng Attila D., LAttilaD.org Link to comment Share on other sites More sharing options...
BugFix Posted July 31, 2010 Share Posted July 31, 2010 Can't repeat your problem. Script from my last post works fine for me. No reverse string in any case. Best Regards BugFix Link to comment Share on other sites More sharing options...
LAttilaD Posted July 31, 2010 Author Share Posted July 31, 2010 Yes, no reverse string at me, too. But Shift gets stuck in again. Láng Attila D., LAttilaD.org Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now