Hello, amigos!
Here's the so-called final version:
v3.98.5 (2018-01-13) - final
- [new] reorganized Typing mode settings window. Made it more informative and better organized and clean.
- [new] option to change typing delays required internally to allow host apps to receive dead keys properly.... by changing this multiplier, you can make dead keys work well, even if "Do not bind dead keys" is activated.
- minor bug fixes
Download AHK file from or use the Update now option:
https://github.com/marius-sucan/KeyPress-OSD
http://marius.sucan.ro/media/files/blog ... ss-osd.ahk
Please use AHK_H v1.1.27 [unicode] to execute this script.
@burque505, @rommmcek, @drugwash, @ozzii (or anyone else).... Please test this version and give me feedback. I want to finalise this project. Please test it with default settings. If dead keys do not work in the host app, increase the typing delays multiplier. Please also read the following:
Q: How does this application work?
A: KeyPress attaches [using keyboard hooks] individually to each key and modifier, on your keyboard and listens/waits for these to be pressed. When a key is pressed, it is displayied on the OSD. When typing, it uses Windows APIs to get the key names, based on the current keyboard layout. This applies as well when using Shift, AltGr or Caps lock.
The application does not use the caret specific Windows APIs to detect where the actual text cursor [caret] is in the text field of the currently active application, because most applications do not make use of these APIs - to report the caret position. It also does not detect if a text field is active or not.
about initialization:
When the script initializes, it goes through all the Virtual Key codes and tests with ToUnicodeEx() and GetKeyName() if there's something to bind to (a key name).
In the language file, I made list of VKs for dead keys, for around 70 keyboard layouts. I made it to bind distinctively to this type of keys. At initialization, the script generates a list of dead key names that later, is used to display the appropriate symbol. One cannot use ToUnicodeEx() each time such a key is pressed, to display their name/symbol, because they no longer function properly in host apps.
About the main typing mode.
The main typing mode hooks to each key using the Hotkey command from AHK, by Virtual Key (vk) and different modifiers. For the Shift and AltGr key combinations, the script binds distinctively, because it must be able to catch these keys orderly and always be able to determine what key name to display using ToUnicodeEx(). if it would bind simply with the (*) wildcard, dead keys cease to function and on slow systems, modifiers detection becomes unreliable. By binding specifically to each modifier and key, based on the prefixes from the built-in variable A_THISHOTKEY, it can always ascertain what to display.
About alternative hooks
When alternative hooks are enabled, a different thread runs with a Loop for an Input command limited to one character. This input command is able to capture dead keys combinations (accented letters). For each key pressed, I use SendMessage to the main thread of the script, that uses OnMessage for WM_COPYDATA. The function associated processes the incoming messages / keys. What this secondary thread sends is used only after a dead key was pressed. Thus, it all still relies on the Hotkey command to get all keys and ToUnicodeEx(), except for the accented letters (keys resulted from using dead keys). When the layout is supported and no dead keys are present, this secondary thread is never initiated.
...... Known issues with alternative hooks: This hook does not work with Windows 10, Metro apps, becauset the Input. command does not capture keys properly.
About the alternate the typing mode.
When alternate typing mode is invoked, I create a new window and focus it, to capture keys with two OnMessage hooked to WM_CHAR and WM_DEADCHAR. I no longer rely on the Hotkey bindings or Input command from the secondary thread. When the user hits Enter, I use SendInput {raw}. I do not use {text} mode, because I want the OSD to send what the user sees and not have him surprised by getting something else in the host app.
Known issues: This solution would work in all context, and all OSes, if I would find a way to set the same keyboard layout to my script window as that of the host app. I was unable to achieve this, despite my attempts for the past two days. I can set the keyboard layout for other apps, but not to my script window. I do not know why. For now, this solution works best in Win 10.
Thank you for reading this long message. I know it is tiring how many versions and bugs I come up with
.... but I am struggling to make something good... and for this, I need all the help I can get.
Best regards, Marius.