get the result of shift+key

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
Holle
Posts: 187
Joined: 01 Oct 2013, 23:19

get the result of shift+key

17 Dec 2013, 06:10

When I press "Shift + ." on a german keyboard, i´ll get ":"
The same on the english keyboard is "<"

Is it possible to find out what char will send, wenn I send "Shift + SomeKey" ?

Example:
A user press "Shift + ." --> I want to get the ASCII-Number for the result. --> german keyboard = 58 (:) , english keyboard = 60 (<)

something like:

Code: Select all

char := "."
StringUpper, char, char
MsgBox % asc(char)
Is there a command oder a DLLCall, what can transfer it?

Get Keyboard layout and get CodePage is possible (thanks to jNizM), but I dont know to use it by my problem.
User avatar
Holle
Posts: 187
Joined: 01 Oct 2013, 23:19

Re: get the result of shift+key

17 Dec 2013, 08:32

I´ve found a function from Microsoft, maybe it is possible with that.
...the Problem is, I have no idea how I can use it in AHK. :oops:
Here is a example, how to use it (in C#)

How it works in ahk?
Zelio
Posts: 278
Joined: 30 Sep 2013, 00:45
Location: France

Re: get the result of shift+key

06 Jan 2014, 21:20

Hmm, I haven't time to help you but I already investigate without a good result, it seems microsoft drivers and manufacturers have the secret... maybe try some google search with "autohotkey keyboard IwantthisMSDNfunction"...

However, for example an old script who can help you to understand and test yours functions:

Code: Select all

#SingleInstance Force
#Persistent
#NoEnv
Process, Priority, , High
SetBatchLines, -1

hDriver:=DllCall("GetModuleHandle", "uint", 0) ; can be the good solution if dead key header and other...
;KbdLayerDescriptor() GetKeyboardLayoutName()
;HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layouts\%KeyboardLayoutName%
hKbdHook := DllCall("SetWindowsHookEx", "int", 0x0D, "uint", RegisterCallback("LowLevelKeyboardProc"), "uint", hDriver, "uint", 0)
OnExit, UnhookKeyboardAndExit
Return

LowLevelKeyboardProc(nCode, wParam, lParam) {

; if ( A_CaretX=0 && A_CaretY=0 ) ; I don't want a Keylogger , but a CharLogger, I want real hotstring comparaison, not multisequencedHotKey
; but disrupt menu key ( alt, F10 )


VK:=NumGet(lParam+0), SC:=NumGet(lParam+4), flag:=NumGet(lParam+8)
log := "code " nCode " | event " wParam
log .= "`nVK " VK " | SC " SC
log .= "`nflag " flag " " flag & 0x80 ? " Up" : " Down"
log .= flag & 0x1 ? " Ext" : ""
log .= flag & 0x10 ? " Inj" : ""
log .= flag & 0x20 ? " Alt" : ""

if !(flag & 0x10) ; only physical input
{
TID := DllCall("GetWindowThreadProcessId", "Int", WinExist("A"), "Int", 0)
TID0 := DllCall("GetCurrentThreadId", "UInt", 0)
DllCall("AttachThreadInput", "UInt", TID0, "UInt", TID, "Int", 1)
HKL := DllCall("GetKeyboardLayout", "Int", TID) ; not useless to call very often ( alt+shift change langauge deteection)
VarSetCapacity(KeyState, 256)
DllCall( "GetKeyboardState", "uint", &KeyState )
    ;DllCall("AttachThreadInput", "UInt", TID0, "UInt", TID, "Int", 0)

VarSetCapacity(Character, 32)
DK := DllCall("ToUnicodeEx", "UInt", VK, "UInt", SC, "UInt", &KeyState, "Str", Character, "UInt", 64, "UInt", 1, "UInt", HKL)
if ( (DK!=-1) && !(flag & 0x80) && (DllCall("MapVirtualKey", "uint", VK, "uint", 2)>0) )
  {
  log .= "`nChar [" Character "]"
  tooltip % log
  }

; need to intercept translate (Wm_KEYDOWN TO WM_CHAR) because ToUnicodeEx create a translation dead key are double ^ -> ^^
; and (DllCall("MapVirtualKey", "uint", VK, "uint", 2)>0) prevent it with deadkey detection but creat an other problem ê -> e
; but stored Character are good and depend where MapVirtualKey are in the code... or use sendU with {BS} ><

}

return DllCall("CallNextHookEx", "uint", hKbdHook, "int", nCode, "uint", wParam, "uint", lParam)
}

esc::
UnhookKeyboardAndExit:
DllCall("UnhookWindowsHookEx", "uint", hKbdHook)
ExitApp
Therefore there is many ways because you can catch and predict what you will write with the keyboard layout and the key combo, I guess that modern application only have and use a big data table of what every langage and keyboard can produce and they don't call a function or an API or a drivers to know this. (for example multi langage keyboard overlay, or charlogger, also you can add and map an exotic keyboard manually)
User avatar
Holle
Posts: 187
Joined: 01 Oct 2013, 23:19

Re: get the result of shift+key

07 Jan 2014, 01:16

Many thanks. It is not what I am searching for, but it will make my script more compactly.
Key combinations like RCtrl+A will not detected, but I will find a other way.

Thank you very much.
Zelio
Posts: 278
Joined: 30 Sep 2013, 00:45
Location: France

Re: get the result of shift+key

07 Jan 2014, 10:24

About RCtrl+A or other combo, maybe delete or replace this line if ( (DK!=-1) && !(flag & 0x80) && (DllCall("MapVirtualKey", "uint", VK, "uint", 2)>0) ) and this line too if !(flag & 0x10) ; only physical input (because some driver can generate extra key with ctrl and alt, left or right side, ex: try AltGr and check AHK keylist log with different keyboard), however that will produce a non printable character or nothing (tested long time ago with a french and a english keyboard)

About your second post and the API function "ToAscii", it is very similar of what I used with DK := DllCall("ToUnicodeEx", "UInt", VK, "UInt", SC, "UInt", &KeyState, "Str", Character, "UInt", 64, "UInt", 1, "UInt", HKL), in other word the script can produce all arguments needed for "ToAscii" with what you press on your keyboard, it is global with the whole system message.

There is not a miracle solve, in your case "shift+.", SC is unknow, and VK table haven't all characters possibilities (only US default, and exotic switch keys). And add a new problem with non printable character... Good luck !

For example, a game will detect your keyboard layout, if you are "french azerty" then arrow keys will be "zqsd" else if you are "english qwerty" that will select "wasd", they don't call an API they just know all keys that will change for each different keyboard.
User avatar
Holle
Posts: 187
Joined: 01 Oct 2013, 23:19

Re: get the result of shift+key

08 Jan 2014, 01:08

Thank you again.
Your script returns all "normal" keys, also
shift+. = : (in german layout).

This is perfect.
The ASCII-Number is not needed in this case, because the char is returned correctly.

The Hotkeys can identified be checking with GetKeyState.
At this moment I try to resolve the problem with the deadkeys (^ = ^^).

I need all this for a function to get the "Last Keypress" (incl. Hotkeys). Example : "LastKey = RCtrl+LShift+F10".

You script returns the correct Char, that was my biggest problem.
Thank you for your help.
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: get the result of shift+key

08 Jan 2014, 02:13

Well, a bit late, but this is using ToAscii() and is seeming to work (although not for dead-keys as yet):

Code: Select all

#NoEnv
Str := "."
MsgBox, 0, Character, % ToAscii("ß", ["Alt", "Ctrl"])
ExitApp

ToAscii(Key, Modifiers := "") {
   VK_MOD := {Shift: 0x10, Ctrl: 0x11, Alt: 0x12}
   VK := GetKeyVK(Key)
   SC := GetKeySC(Key)
   VarSetCapacity(ModStates, 256, 0)
   For Each, Modifier In Modifiers
      If VK_MOD.HasKey(Modifier)
         NumPut(0x80, ModStates, VK_MOD[Modifier], "UChar")
   Result := DllCall("USer32.dll\ToAscii", "UInt", VK, "UInt", SC, "Ptr", &ModStates, "UIntP", Ascii, "UInt", 0, "Int")
   Return Chr(Ascii)
}
User avatar
Holle
Posts: 187
Joined: 01 Oct 2013, 23:19

Re: get the result of shift+key

08 Jan 2014, 02:17

I´ve found a way, to resolve the problem with the DeadKey, but I need a Way to transfer "^e" to "ê" , "^a" to "â" and so on.
Do you know a way to transform it?


Edit:
Thank you just me, but it does´nt work on my PC.
When I try this:

Code: Select all

MsgBox, 0, Character, % ToAscii("ß", "Alt", "Ctrl")
it become the follow error message:
>"D:\AHK\AutoHotkey.exe" /ErrorStdOut "D:\Dropbox\Programmieren\AHK\MEN\test6.ahk"
D:\Dropbox\Programmieren\AHK\MEN\test6.ahk (4) : ==> Too many parameters passed to function.
Specifically: ToAscii("ÿ", "Alt", "Ctrl")
>Exit code: 2 Time: 0.103
Instead "ÿ" (this is by copy and paste) is there a "xC3?"

When I try:

Code: Select all

MsgBox, 0, Character, % ToAscii("ß", "Shift")
it works without an error message, but the result is "ß" instead "?".

Another Edit:
The script from Zelio works fine. The only problem are the Deadkey, but if there is a way to transform "^e" to "ê" (and so on) I can resolve the problem.
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: get the result of shift+key

08 Jan 2014, 05:26

Hallo Holle,

the second parameter has to be an array: ToAscii("ß", ["Alt", "Ctrl"]).

Also, you have to save the script as Unicode with BOM, if you use characters like German Umlauts or "ß".
User avatar
Holle
Posts: 187
Joined: 01 Oct 2013, 23:19

Re: get the result of shift+key

08 Jan 2014, 06:20

Omg :oops:
Now, it works perfect :)

I thought the [] was a sign for "optional" :roll:

Thank you very much.
Zelio
Posts: 278
Joined: 30 Sep 2013, 00:45
Location: France

Re: get the result of shift+key

08 Jan 2014, 09:18

I guess to use "just me" script is very better, and it will depends how you watch and listen your keyboard (with my script that can be unstable or with something like Poly regex hotstring that use AHK hotkey label for example, or other input), maybe post your script when you have finish this can be interesting...

About dead key, a quick solve (not elegant), if you have problem only with diacritic then create a simple table with letter(aeiou...) as X coordinate, and accent(^`¨~...) as Y coordinate, for more complicated table go to http://www.autohotkey.com/board/topic/7 ... n-concept/ for inspiration and idea...

GetKeyName(Key), GetKeyVK(Key), GetKeySC(Key), I don't remember of thoses toys, but I really want an handle and more features for to control hotkeys/hotstrings and use the keylist history inside Autohotkey.
User avatar
Holle
Posts: 187
Joined: 01 Oct 2013, 23:19

Re: get the result of shift+key

08 Jan 2014, 10:14

Thanks.

I will post my script as soon as is finish in a new Topic, and here will I post a link to the new Topic.
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: get the result of shift+key

08 Jan 2014, 10:28

Hallo Holle,

it seems I could find a solution for the dead-key characters here.

Code: Select all

#NoEnv
MsgBox, 0, Character, % ToAscii("a", ["Shift"], "^", False)
ExitApp

ToAscii(Key, Modifiers := "", DeadKey := "", ShiftDeadKey := False) {
   ; Key          -  Unshifted Key
   ; Modifiers    -  Array of modifier keys. Valid values: "Alt", "Ctrl", and/or "Shift".
   ; DeadKey      -  Unshifted dead-key character to be composed with Key
   ; ShiftDeadKey -  The dead-key character has to be shifted. Valid values: True/False
   Static VK_Mod := {Shift: 0x10, Ctrl: 0x11, Alt: 0x12}
   Key := SubStr(Key, 1, 1)
   VK_Key := GetKeyVK(Key)
   SC_Key := GetKeySC(Key)
   VarSetCapacity(ModStates, 256, 0)
   If (DeadKey) {
      DeadKey := SubStr(DeadKey, 1, 1)
      VK_Dead := GetKeyVK(DeadKey)
      SC_Dead := GetKeySC(DeadKey)
      If (ShiftDeadKey)
         NumPut(0x80, ModStates, VK_Mod.Shift, "UChar")
      Char :=  DllCall("User32.dll\ToAscii", "UInt", VK_Dead, "UInt", SC_Dead, "Ptr", &ModStates, "UShortP", Ascii
                     , "UInt", 0, "Int")
      If (Char <> -1) ; the specified dead-key character isn't a dead-key
         Return ""
   }
   VarSetCapacity(ModStates, 256, 0)
   For Each, Modifier In Modifiers
      If VK_Mod.HasKey(Modifier)
         NumPut(0x80, ModStates, VK_Mod[Modifier], "UChar")
   Chars := DllCall("User32.dll\ToAscii", "UInt", VK_Key, "UInt", SC_Key, "Ptr", &ModStates, "UShortP", Ascii
                  , "UInt", 0, "Int")
   If (Chars = 0) ; the specified character has no translation for the current state of the keyboard.
      Return ""
   If (Chars = -1) || (Chars = 1) ; one character was copied to the buffer.
      Return Chr(Ascii)
   ; The dead-key character cannot be composed with the specified character to form a single character.
   Return Chr(Ascii & 0xFF) . Chr((Ascii & 0xFF00) >> 8) ; or Return ""
}
User avatar
Holle
Posts: 187
Joined: 01 Oct 2013, 23:19

Re: get the result of shift+key

09 Jan 2014, 02:01

Thank you just me. It works very good, but I have a problem with the detection of dead keys.
I´ve tried many ways, but the script was unstable.

When I use Zelios method to detect pressed keys, it crashed bei pressing AltGr.
When I use hotkeys, I must add very much keys and I get a error message when the key is not in the actualy keyboard layout.

I keep trying.
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: get the result of shift+key

09 Jan 2014, 02:11

Maybe?

Code: Select all

#NoEnv
MsgBox, % IsDeadKey("^")
ExitApp

IsDeadKey(Key, Shift := False) {
   Static VK_Shift := 0x10
   VK := GetKeyVK(Key)
   SC := GetKeySC(Key)
   VarSetCapacity(ModStates, 256, 0)
   If (Shift)
      NumPut(0x80, ModStates, VK_Shift, "UChar")
   Result := DllCall("USer32.dll\ToAscii", "UInt", VK, "UInt", SC, "Ptr", &ModStates, "UIntP", Ascii, "UInt", 0, "Int")
   Return (Result = -1 ? True : False)
}
User avatar
Holle
Posts: 187
Joined: 01 Oct 2013, 23:19

Re: get the result of shift+key

09 Jan 2014, 02:32

WOW :shock:
Thanks, it works perfect.
Zelio
Posts: 278
Joined: 30 Sep 2013, 00:45
Location: France

Re: get the result of shift+key

09 Jan 2014, 09:29

And it is not over, mouhahahaha, if you plan to manage euro character (altgr+E = €) or others frenchs dead key (altgr+é = ~ dead key, altgr+è = ` dead key, etc), then you have to add that "ctrl+alt = altgr" and to modify your "ModStates" of the letter and also the dead key for add other key mod. In other word, shift true or false, or separated shift ctrl alt, are not enough...
User avatar
Holle
Posts: 187
Joined: 01 Oct 2013, 23:19

Re: get the result of shift+key

09 Jan 2014, 09:54

At this moment I work with the dead keys.
Many problems, but I resolve it slowly step by step.
Enough for today. I will continue tomorrow.
User avatar
Holle
Posts: 187
Joined: 01 Oct 2013, 23:19

Re: get the result of shift+key

28 Jan 2014, 05:32

OK, it´s done:
Look here

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Auntiejack56, Google [Bot], ntepa, Xtra and 140 guests