[Script] KeypressOSD - Display key press on screen

Post your working scripts, libraries and tools for AHK v1.1 and older
denyerec
Posts: 4
Joined: 25 Jul 2017, 12:26

Re: [Script] KeypressOSD - Display key press on screen

26 Jul 2017, 02:36

As you may have gathered I'm rather new at this - I didn't even realise that was an option. I'll go and look up how to do that now and see if it resolves things!

EDIT:

OK so I have run the scripts separately (Generating two instances of AHK) and it's now working as I would expect, so thankyou for that! Now my challenge is to restrict the keypress detection to two applications only. As I only want to show the keypresses in Photoshop & Lightroom (The two applications I produce tutorials for).

EDIT 2:

I am trying to restrict the key display to a couple of applications, I have created the following group:

Code: Select all

GroupAdd, TutorialApps, ahk_class #32770
GroupAdd, TutorialApps, ahk_class Photoshop
GroupAdd, TutorialApps, Adobe Photoshop Lightroom - Library
GroupAdd, TutorialApps, Adobe Photoshop Lightroom - Develop
GroupAdd, TutorialApps, ahk_exe Photo Mechanic.exe
But so far have not managed to isolate the display code with a #IfWinActive, ahk_group TutorialApps block. If anyone can help, that'd be awesome!

Edit 3:

Got it :)

Code: Select all

ShowHotkey(HotkeyStr) {

  if WinActive("ahk_group TutorialApps") {

	WinGetPos, ActWin_X, ActWin_Y, ActWin_W, ActWin_H, A
	if !ActWin_W
		throw

	text_w := (ActWin_W > A_ScreenWidth) ? A_ScreenWidth : ActWin_W
	GuiControl,     , HotkeyText, %HotkeyStr%
	GuiControl, Move, HotkeyText, w%text_w% Center

	if (GuiPosition = "Top")
		gui_y := ActWin_Y
	else
		gui_y := (ActWin_Y+ActWin_H) - 115 - 0

	Gui, Show, NoActivate x%ActWin_X% y%gui_y% h%GuiHeight% w%text_w%
  } else {
	return
  }

}
tmplinshi
Posts: 1604
Joined: 01 Oct 2013, 14:57

Re: [Script] KeypressOSD - Display key press on screen

26 Jul 2017, 09:18

@denyerec Or you can simply add Hotkey, IfWinActive, ahk_group TutorialApps before CreateHotkey():

Code: Select all

Hotkey, IfWinActive, ahk_group TutorialApps
CreateHotkey()
j_fayez
Posts: 2
Joined: 05 Aug 2017, 11:59

Re: [Script] KeypressOSD - Display key press on screen

05 Aug 2017, 12:05

How to display pressed keys through this virtual Keyboard?

https://autohotkey.com/board/topic/9470 ... -keyboard/
j_fayez
Posts: 2
Joined: 05 Aug 2017, 11:59

Re: [Script] KeypressOSD - Display key press on screen

05 Aug 2017, 12:05

How to display pressed keys through this virtual Keyboard?

https://autohotkey.com/board/topic/9470 ... -keyboard/
robodesign

Re: [Script] KeypressOSD - Display key press on screen

19 Sep 2017, 10:51

When I run this script, using the International English layout, the dead keys do not work anymore.... any idea why?

Dead keys are ` and ' , these help with adding accents in combination with other letters.

Any fix possible for this?

Very nice script. Thank you very much. It should count any repeated letter or button, not just key combinations.
robodesign

Re: [Script] KeypressOSD - Display key press on screen

21 Sep 2017, 13:32

I made various improvements to the code, together with Saiapatsu on IRC (thank you very much). It is highly usable now. I use it most of the times.

todo:
; - make key combinations with space and backspace work again, e.g. Ctrl-bksp
; - make it work again with sticky keys; if i press once Ctrl and after another key, no combo detected
; - make dead keys work; now they show up only in the OSD
; - when user enables CapsLock or NumLock or ScrollLock, capitalize the key, when they turn off, lower case
; - make it count Otherkeys, not just key combinations, e.g. how many times I pressed PgUp or Enter.

Script here:
http://p.ahkscript.org/?p=34fce847

If anyone here is willing to help, I would be glad. I use it because it helps me with my visual impariments.

Thank you very much.
robodesign

Re: [Script] KeypressOSD - Display key press on screen

23 Sep 2017, 10:25

Hello!

I made fixes and improvements to the new version.

Change log (highlights):
; by Marius Sucan (robodesign.ro)
; v2.58 (2017-09-23) - Numpad keys have friendly naming, based on the numlock state. Combinations with space and backspace work again.
; v2.56 (2017-09-22) - more fixes for space usage and key combinations; now it capitalizes ScrollLock, NumLock and Capslock when turned on.

; by Saiapatsu from irc.freenode.net #ahk
; v2.54 (2017-09-21) - Scrolls through n recently typed characters instead of just the latest word

; by Marius Sucan (robodesign.ro)
; v2.50 (2017-09-20) - Changed the OSD positioning and sizing. Now it is always fixed in a specific place. Added Capslock beeper.

To do (sorted by priority):
; - add keyboard shortcut to disable/activate loop 95, if dead keys issue persists
; - make dead keys always work; with the current work around the special keys show up only in the OSD and rarely in the text field you type
; - when numlock is on, all numpad keys should initiate typing mode
; - if OSD is not visible or if previous key combinations were pressed, when user presses shift + letters or other keys covered by Loop 95, display it as a combination
; - when user types single letters, display shift + (sign or number) keys as signs, respecting the influence of the shift key, eg. Shift + 0, should be displayed as )
; - make it count mouse clicks, Otherkeys, not just key combinations, e.g. how many times I pressed PgUp or Enter
; - friendly names for mouse clicks
; - make it work reliably with sticky keys; if user presses once Ctrl and another key afterwards, it rarely detects the combination
; - always make beeps for volume keys
; - add option for making a beep at every key press or when capslock is on
; - on mouse hover, hide the OSD
; - automatic resizing of the GUI, the OSD

Any help is welcomed. I am no programmer and implementing the functions I need is very difficult for me.

Script at: http://p.ahkscript.org/?p=fd7a9b26

Thank you very much.
User avatar
Drugwash
Posts: 853
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: [Script] KeypressOSD - Display key press on screen

23 Sep 2017, 13:20

Have you ever tried this thing with a RO layout? It doesn't work at all for the diacritics (ăîşţâŞĂÎŞŢÂ), neither do combinations using Shift or AltGr. It desperately needs a different approach altogether. Same as all those virtual keyboard-wannabe scripts.
Part of my AHK work can be found here.
robodesign

Re: [Script] KeypressOSD - Display key press on screen

26 Sep 2017, 10:51

Hello, again!

Thank you very much for your reply. I did not test it with the Romanian keyboard, even if I am a Romanian :) .... I have my own keyboard layout, with dead keys based on ENG US keyboard layout.

I will test the romanian layout. I hope to be able to fix the problems. In general, yes, I agree, the code needs a refactoring, but I am not that skillful.

Anyways... I managed to make considerable improvements by myself to the script these past few days.

; CHANGELOG:
v2.60 (2017-09-26) - Fixed many issues with counting keys;
* reimplemented the feature to see the previous key combination, if quickly a new one is pressed;
* added options/settings to toggle previous keys, counting keys and delay;
* added shortcuts to toggle ShowSingleKey option and to reinitialize the OSD;
*added option for automatic resizing of the OSD; it can be turned off in the settings section; it is a fishy implementation, but if one adjusts it, can make it to suit personal needs;
* added option to beep when key is released or when writing with capslock

v2.58 (2017-09-23)
* Numpad keys have friendly naming, based on the numlock state.
* Combinations with space and backspace work again.

v2.56 (2017-09-22)
* fixes for space usage and key combinations;
* now it indicates when ScrollLock, NumLock and Capslock are activated.

Script available here:
http://p.ahkscript.org/?p=0b2dbf32

; to-do list (sorted by priority):
; - make dead keys always work; with the current work-around, the special keys show up in the OSD and sometimes in the text field the user types in
; - when numlock is on, all numpad keys should initiate typing mode
; - if user presses capslock when writing, the text should not be removed
; - when user types single letters, display Shift + (sign or number) keys as signs, respecting the influence of the shift key, eg. Shift + 0, should be displayed as )
; - if OSD is not visible or if previous key combinations were pressed, when user presses Shift + letters or other keys covered by Loop 95, display it as a combination; please see CreateHotkey()
;
; less important
; - on mouse hover, hide the OSD
; - make it work reliably with sticky keys; if user presses once Ctrl and another key afterwards, it rarely detects the combination
; - make it count mouse clicks as well
; - friendly names for mouse clicks
; - always make beeps for volume keys
; - insert mode; detect

Best regards, Marius
User avatar
Drugwash
Posts: 853
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: [Script] KeypressOSD - Display key press on screen

26 Sep 2017, 13:35

Please do, thank you. For more info check https://drugwash.wordpress.com/tutorial ... -romanesc/
Part of my AHK work can be found here.
robodesign

Re: [Script] KeypressOSD - Display key press on screen

26 Sep 2017, 16:50

Drug wash, are you a coder?

As a side note, this is not a virtual keyboard. It's just an on-screen display to help visualise what keys the user presses. It helps with my visual impairment.
User avatar
joedf
Posts: 9097
Joined: 29 Sep 2013, 17:08
Location: Canada
Contact:

Re: [Script] KeypressOSD - Display key press on screen

26 Sep 2017, 19:53

Drugwash is a very talented and knowledgeable programmer! :+1:
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x16GB Kingston FURY Beast - DDR4 3200 MHz | [About Me] | [About the AHK Foundation] | [Courses on AutoHotkey]
[ASPDM - StdLib Distribution] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library]
User avatar
Drugwash
Posts: 853
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: [Script] KeypressOSD - Display key press on screen

27 Sep 2017, 08:14

Thanks, Joe, but that's an overstatement. I'm just a simple guy playing with ones and zeroes sometimes. :)

Marius, the OSD and the virtual keyboards share the same principle: they have to understand, read and display the actual keys on the current layout. I offered the link to the OSK page just to show the RO layout which may help in testing this script. It is not only about RO but any other layout out there that is not EN. All the OSD and virtual keyboard scripts 've tested so far failed to retreive and display the correct characters because authors used a wrong approach. Even AHK_L itself fails in GetKeyName(Key) when fed with the scancodes (same as with MapVirtualKeyEx() for that matter), it requires the vk codes or the entire lParam fom related WM_* messages in GetKeyNameText() plus a few other tricks to get the right keys and combinations.

I wish I could help more but my 98SE machine is off pending a thorough hardware checkup and fix, and I never code anything until it first works in 9x.
Oh and please do not misspell my nickname, Drugwash stands for Dragoş, my real name. Thank you.
Part of my AHK work can be found here.
robodesign

Re: [Script] KeypressOSD - Display key press on screen

28 Sep 2017, 11:15

Hello, again!

I am back with a new and improved version.

; CHANGELOG:

by phaleth from irc.freenode.net #ahk
v2.67 (2017-09-28)
; - dead keys improvements

by Marius Sucan (robodesign.ro)
v2.66 (2017-09-28)
; - key combinations with Shift work better.

v2.65 (2017-09-27)
; - Fixed a bug with counting modifier keys;
; - improved the dead keys work-around
; - friendly names for mouse clicks
; - when pressed, volume keys always generate beeps
; - added option to differentiate between left and right modifiers
; - now it detects AltGr key
; - the key beeper now also makes a beep for modifiers.
; - capslock no longer erases text you are typing displayed by the OSD
; - now you can toggle between two different OSD positions with Ctrl + Alt + Shift + F9

; to-do list (sorted by priority):
; - if numlock is on, all numpad keys should initiate typing mode
; - when user types single letters, display Shift + (sign or numeric keys) as signs/symbols, eg. Shift + 0, should be displayed as )
; - after pressing Shift + [letter] if the following key is a single letter, remember the first Shift + [letter]
; - show Shift as a modifier, as Ctrl and Alt; Shift does not behave as the other two
; - make dead keys 100% work, always; with the current implementation, the special keys show up seemingly random in the OSD and sometimes in the text field the user types in
;
; less important
; - on mouse hover or click, hide the OSD
; - always count mouse clicks; it sometimes does, other times it does not count them; no idea why
; - counting of key fires is not initiated after OSD is hidden for awhile when the user presses the first key
; - make it work reliably with sticky keys; if user presses once Ctrl and another key afterwards, it rarely detects the combination on Winndows 7;
; - test Romanian kbd layout as suggested by drugwash

Script at: http://p.ahkscript.org/?p=eb51d9d2 .

If someone can help me with the to-do list, I would be really happy. The first ones are the most important - the first section of the to-do list. Thank you.

Best regards, Marius
robodesign

Re: [Script] KeypressOSD - Display key press on screen

29 Sep 2017, 11:12

Hello!

A new version is here:

; CHANGELOG:
; by Marius Sucan (robodesign.ro)
; v2.68 (2017-09-29) - numpad keys now work in typing mode as expected; they appear as symbols or numbers
;
; by phaleth from irc.freenode.net #ahk
; v2.67 (2017-09-28) - dead keys improvements

; TO-DO:::::::::::::::::::::::::::::::::::
; Features to implement:
; - when user types single letters, display Shift + (sign or numeric keys) as signs/symbols, eg. Shift + 0, should be displayed as )
; - on mouse hover or click, hide the OSD
;
; Glitches to fix:
; - after pressing Shift + [letter] if the following key is a single letter, remember the first Shift + [letter]
; - after a Numpad key is pressed, typing mode should begin if the second one is another numpad key
; - show Shift as a modifier, as Ctrl and Alt; Shift should behave as the other two; it is never displayed alone and countable
; - show a generic symbol for ignored dead keys; helps to clarify one was pressed
; - always count mouse clicks; it sometimes does, other times it does not; no idea why
; - once a key is pressed, counting of key fires is not initiated after the OSD was hidden for a little awhile
; - make dead keys 100% work, always; with the current implementation, the special keys show up seemingly random in the OSD and sometimes in the text field the user types in
; - make it work reliably with sticky keys; if user presses once Ctrl and another key afterwards, it rarely detects the combination on Winndows 7;
; - test Romanian kbd layout as suggested by drugwash

Best regards, Marius
robodesign
Posts: 941
Joined: 30 Sep 2017, 03:59
Location: Romania
Contact:

Re: [Script] KeypressOSD - Display key press on screen

30 Sep 2017, 04:09

I forgot to paste the code, sorry:
Link at: http://p.ahkscript.org/?p=158825d3

Code: Select all

; KeypressOSD.ahk
; AVAILABLE SHORTCUTS:
; Ctrl+Alt+Shift+F8  - toggles "Show single key" option. Useful when you must reliably use dead keys.
; Ctrl+Alt+Shift+F9  - toggles between two OSD offsets: GuiYa and GuiYb
; Ctrl+Alt+Shift+F12 - Reinitialize OSD. Useful when it no longer appears on top. To have it appear on top of elevated apps, run it in administrator mode.

#SingleInstance force
#NoEnv
SetBatchLines, -1
ListLines, Off

; Settings.
    global TransN                := 210   ; range from 0 to 255
    global ShowSingleKey         := true  ; makes it show only key combinations
    global ShowMouseButton       := true
    global ShowSingleModifierKey := true  ; make it display Ctrl, Alt, Shift when pressed alone
    global DifferModifiers       := 0     ; differentiate between left and right modifiers
    global DisplayTime           := 3000  ; in milliseconds
    global GuiWidth              := 360
    global GuiHeight             := 50
    global GuiX                  := 50
    global GuiYa                 := 250  ; toggle between GuiYa and GuiYb with Ctrl + Alt + Shift + F9
    global GuiYb                 := 800
    global FontSize              := 19
    global OSDautosize           := 1    ; make adjustments in ShowHotkey() to your font size, to make it suit your needs
    global ShowPrevKey           := 1
    global ShowPrevKeyDelay      := 300
    global ShowKeyCount          := 1    ; count how many times a key is pressed
    global ShowKeyCountFired     := 1    ; Show only key presses (0) or catch key fires as well (1)
    global NumLetters            := 24   ; amount of recently typed letters to display
    global NumLettersAutosize    := 65   ; the amount when OSD resizes automatically
    global CapslockBeeper        := 1    ; beeps only when the key is released
    global KeyBeeper             := 0    ; beeps only when the key is released

; Initialization variables. Altering these may lead to undesired results.
    global typed := ""
    global visible := 0
    global GuiY := GuiYa
    global prefixed := 0 ; hack used to determine if last keypress had a modifier
    global zcSCROL := "SCROLL LOCK"
    global tickcount_start := 0   ; timer to count repeated key presses
    global keyCount := 0
    global ShowKeyCountDelay := (ShowKeyCountFired = 0) ? 700 : 6000
    #MaxHotkeysPerInterval 500
    NumLetters := (OSDautosize=1) ? NumLettersAutosize : NumLetters
    global text_width := 60

    CreateGUI()
    CreateHotkey()
    return

; The script

GetSpecialKeysStates() {
    GetKeyState, ScrollState, ScrollLock, T   
    If ScrollState = D
    {
       global zcSCROL := "SCROLL LOCK ON"
    }
    else {
       global zcSCROL := "Scroll lock off"
    }
}

TypedLetter(key) {
    return typed := SubStr(typed key, -NumLetters)
}

OnKeyPressed() {
    try {
        key := GetKeyStr()
        typed := "" ; concerning TypedLetter(" ") - it resets the content of the OSD
        ShowHotkey(key)
        SetTimer, HideGUI, % -DisplayTime
    }
}

OnLetterPressed() {
    try {
        if typed 
        {
            sleep, 25    ; this delay helps with dead keys,  but it generates errors; the following actions: stringleft,1 and stringlower help correct these
        } else
        {
        }

        key := GetKeyStr(1)     ; consider it a letter

        if prefixed
        {
            ShowHotkey(key)
        } else
        {
            StringLeft, key, key, 1
            Stringlower, key, key

            GetKeyState, CapsState, CapsLock, T
            If CapsState != D
            {
                 if GetKeyState("Shift", "P")
                {
                  StringUpper, key, key
                }
            } else
                StringUpper, key, key

            TypedLetter(key)
            ShowHotkey(typed)
        }
        SetTimer, HideGUI, % -DisplayTime
    }
}

OnSpacePressed() {
    try {
        if typed {
            if (visible)
            {
                TypedLetter("_")
                ShowHotkey(typed)
            } else
            {
                TypedLetter("_")
                ShowHotkey(typed)
                SetTimer, HideGUI, % -DisplayTime
            }
        } else if (!typed)
        {
          key := GetKeyStr()
          ShowHotkey(key)
          SetTimer, HideGUI, % -DisplayTime
        }
    }
}

OnBspPressed() {
    If (KeyBeeper = 1)
       {
         soundbeep, 1900, 45
       }
    try
    {
        if typed
        {
            typed := SubStr(typed, 1, StrLen(typed) - 1)
            ShowHotkey(typed)
        } else if (!typed)
        {
            key := GetKeyStr()
            ShowHotkey(key)
            SetTimer, HideGUI, % -DisplayTime
        }
    }
}

OnCapsPressed() {
    try
    {
        if typed
        {
            ShowHotkey(typed)
        } else if (!typed)
        {
            key := GetKeyStr()
            GetKeyState, CapsState, CapsLock, T
            if CapsState = D
            {
                key := prefixed ? key : "CAPSLOCK ON"
            } else
                key := prefixed ? key : "CapsLock off"
            ShowHotkey(key)
            SetTimer, HideGUI, % -DisplayTime
        }
    }

    If (CapslockBeeper = 1)
       {
        soundbeep, 450, 200
       }
}

OnNumpadPressed()
{
    GetKeyState, NumState, NumLock, T
    try {
        if NumState != D
        {
            key := GetKeyStr()
            ShowHotkey(key)
            SetTimer, HideGUI, % -DisplayTime
        } else if !typed
        {
            key := GetKeyStr()
            ShowHotkey(key)
        } else if NumState = D
        {
            key := GetKeyStr(1) ; consider it a letter
            StringLeft, key, key, 3
            StringRight, key, key, 1
            TypedLetter(key)
            ShowHotkey(typed)
        }
        SetTimer, HideGUI, % -DisplayTime
    }
}

OnKeyUp()
{
       If (KeyBeeper = 1)
       {
         soundbeep, 150, 45
       }
}

_OnKeyUp() {
    global tickcount_start := A_TickCount

    if typed && (CapslockBeeper = 1)
    {
        GetKeyState, CapsState, CapsLock, T
        If CapsState = D
           {
             soundbeep, 450, 25
           }
           else if (KeyBeeper = 1)
           {
             soundbeep, 1900, 45
           }
    }

    If (CapslockBeeper = 0) && (KeyBeeper = 1)
       {
         soundbeep, 1900, 45
       }
       else if (CapslockBeeper = 1) && (KeyBeeper = 0)
       {
       }
       else if !typed && (CapslockBeeper = 1)
       {
         soundbeep, 1900, 45
       }

}

; ===================================================================================

CreateGUI() {
    global

    Gui, +AlwaysOnTop -Caption +Owner +LastFound +ToolWindow +E0x20
    Gui, Margin, 10, 10
    Gui, Color, 222222
    Gui, Font, cWhite s%FontSize% bold, Arial, -wrap
    Gui, Add, Text, vHotkeyText left x10 y10 -wrap

    WinSet, Transparent, %TransN%
}

CreateHotkey() {

    Loop, 95
    {
        k := Chr(A_Index + 31)

        for each, char2skip in StrSplit("``,^,',"",~", ",")  ; dead keys to ignore
        {
            if (k = char2skip)
            {
                continue, 2
            }
        }

        if (k = " ")
        {
            Hotkey, % "~*Space", OnSpacePressed
            Hotkey, % "~*Space Up", _OnKeyUp
        }
        else
        {
            Hotkey, % "~*" k, OnLetterPressed
            Hotkey, % "~*" k " Up", _OnKeyUp
        }
    }

    Hotkey, % "~*Backspace", OnBspPressed
    Hotkey, % "~*CapsLock", OnCapsPressed

    Loop, 24 ; F1-F24
    {
        Hotkey, % "~*F" A_Index, OnKeyPressed
        Hotkey, % "~*F" A_Index " Up", _OnKeyUp
    }

    Loop, 10 ; Numpad0 - Numpad9
    {
        Hotkey, % "~*Numpad" A_Index - 1, OnNumpadPressed
        Hotkey, % "~*Numpad" A_Index - 1 " Up", _OnKeyUp
    }

    NumpadKeysList := "NumpadDot|NumpadDiv|NumpadMult|NumpadAdd|NumpadSub|sc04E|sc04A|sc052|sc04F|sc050|sc051|sc04B|sc04C|sc04D|sc047|sc048|sc049|sc053|sc037|sc135"

    Loop, parse, NumpadKeysList, |
    {
       Hotkey, % "~*" A_LoopField, OnNumpadPressed
       Hotkey, % "~*" A_LoopField " Up", _OnKeyUp
    }

    Otherkeys := "WheelDown|WheelUp|WheelLeft|WheelRight|XButton1|XButton2|Browser_Forward|Browser_Back|Browser_Refresh|Browser_Stop|Browser_Search|Browser_Favorites|Browser_Home|Volume_Mute|Volume_Down|Volume_Up|Media_Next|Media_Prev|Media_Stop|Media_Play_Pause|Launch_Mail|Launch_Media|Launch_App1|Launch_App2|Help|Sleep|PrintScreen|CtrlBreak|Break|AppsKey|Tab|Enter|Esc"
               . "|Insert|Home|End|Up|Down|Left|Right|ScrollLock|NumLock|Pause|sc145|sc146|sc046|sc123|sc11C|sc149|sc151|sc122|sc153|sc152"
    Loop, parse, Otherkeys, |
    {
        Hotkey, % "~*" A_LoopField, OnKeyPressed
        Hotkey, % "~*" A_LoopField " Up", _OnKeyUp
    }

    If ShowMouseButton {
        Loop, Parse, % "LButton|MButton|RButton", |
        Hotkey, % "~*" A_LoopField, OnKeyPressed
    }

    for i, mod in ["LCtrl", "RCtrl", "LAlt", "RAlt"] {
        Hotkey, % "~*" mod, OnKeyPressed
        Hotkey, % "~*" mod " Up", OnKeyUp
    }

    for i, mod in ["LWin", "RWin"]
        Hotkey, % "~*" mod, OnKeyPressed
        Hotkey, % "~*" mod " Up", OnKeyUp

    If typed {
    for i, mod in ["LShift", "RShift"]
        Hotkey, % "~*" mod, OnKeyPressed
        Hotkey, % "~*" mod " Up", OnKeyUp
    }
}

ShowHotkey(HotkeyStr) {
    if GetKeyState("Shift", "P") && (HotkeyStr ~= "\^")
    {
        SendRaw, ^
        return
    }

    if (OSDautosize=1)
    {
        text_width := (StrLen(HotkeyStr)/1.3)*FontSize
        text_width := (text_width<70) ? 70 : text_width+15
    } else if (OSDautosize=0)
    {
        text_width := GuiWidth
    }

    if !typed
    {
        StringUpper, HotkeyStr, HotkeyStr, T
    }

    GuiControl,     , HotkeyText, %HotkeyStr%
    GuiControl, Move, HotkeyText, w%text_width% left
    Gui, Show, NoActivate x%GuiX% y%GuiY% AutoSize
    visible := 1
}

GetKeyStr(letter := 0) {
    static modifiers := ["LCtrl", "RCtrl", "LAlt", "RAlt", "LShift", "RShift", "LWin", "RWin"]
    static repeatCount := 1

    ; If any mod but shift, go ; If shift, check if not letter

    for i, mod in modifiers {
    if (mod = "LShift" && typed || mod = "RShift" && typed ? (!letter && GetKeyState(mod)) : GetKeyState(mod))
       prefix .= mod " + "
    }

    if (!prefix && !ShowSingleKey)
        throw

    key := SubStr(A_ThisHotkey, 3)

    if (key ~= "i)^(LCtrl|RCtrl|LShift|RShift|LAlt|RAlt|LWin|RWin)$") {
        if !ShowSingleModifierKey
        {
            throw
        } else
        {
            key := ""
            prefix := RTrim(prefix, "+ ")
        }

        prefix := CompactModifiers(prefix)

        if (ShowKeyCount=1) {
            if !InStr(prefix, "+") && IsDoubleClickEx() {
                if (A_ThisHotKey != A_PriorHotKey) || (ShowKeyCount=1) && (A_TickCount-tickcount_start < ShowKeyCountDelay+repeatCount*100) {
                    if (++repeatCount > 1) {
                        prefix .= " [" repeatCount "]"
                    }
                } else {
                    repeatCount := 0
                }
            } else {
                repeatCount := 1
            }
        }
    } else {
        if ( StrLen(key) = 1 ) {
            key := GetKeyChar(key, "A")
        } else if ( SubStr(key, 1, 2) = "sc" ) {
            key := SpecialSC(key)
        } else if (key = "Volume_Up") || (key = "Volume_Down") {
            soundbeep, 150, 40
        } else if (key = "MButton") {
            key := "Middle Click"
        } else if (key = "RButton") {
            key := "Right Click"
        } else if (key = "LButton") && IsDoubleClick() {
            key := "Double-Click"
        } else if (key = "LButton") {
            throw
            ; key := "Left Click"
        }
        {
            _key := (key = "Doub1le-Click") ? "Left Click" : key
        }

        prefix := CompactModifiers(prefix)

        static pre_prefix, pre_key, keyCount := 1
        keyCount := (key=pre_key) && (prefix = pre_prefix) ? keyCount : 1
        global ShowKeyCountDelay := (ShowKeyCountFired = 0) ? 700 : 6000
        ShowKeyCountDelay := (ShowKeyCountFired=1) ? (ShowKeyCountDelay+keyCount*100) : ShowKeyCountDelay

        if (InStr(prefix, "+")) && (A_TickCount-tickcount_start < ShowKeyCountDelay) || (!letter) && (A_TickCount-tickcount_start < ShowKeyCountDelay)
        {
            if (ShowPrevKey=1) && (A_TickCount-tickcount_start < ShowPrevKeyDelay) && !typed
            {
                ShowPrevKeyValid := 1
            } else
            {
                ShowPrevKeyValid := 0
            }
            if (prefix != pre_prefix) {
                result := (ShowPrevKeyValid=1) ? prefix key " {" pre_prefix pre_key "}" : prefix key
            } else if (ShowPrevKeyValid=1) && (key != pre_key) || (ShowKeyCount=1) && (ShowPrevKeyValid=1)
            {
                keyCount := (key=pre_key) && (ShowKeyCount=1) ? (keyCount+1) : 1
                key := (keyCount>1) && (ShowKeyCount=1) ? (key " {" keyCount "}") : (key ", " pre_key)
            } else if (ShowPrevKeyValid=0)
            {
                keyCount := (key=pre_key) && (ShowKeyCount=1) ? (keyCount+1) : 1
                key := (keyCount>1) ? (key " {" keyCount "}") : (key)
            }
        } else {
            keyCount := 1
        }

        pre_prefix := prefix
        pre_key := _key

        repeatCount := 1
    }

    prefixed := prefix ? 1 : 0
    return result ? result : prefix . key
}

CompactModifiers(stringy)
{
    if DifferModifiers = 1
    {
        StringReplace, stringy, stringy, LCtrl + RAlt, AltGr, All
        StringReplace, stringy, stringy, LCtrl + RCtrl + RAlt, RCtrl + AltGr, All
        StringReplace, stringy, stringy, RAlt, AltGr, All
        StringReplace, stringy, stringy, LAlt, Alt, All
    } else if (DifferModifiers = 0)
    {
        StringReplace, stringy, stringy, LCtrl + RAlt, AltGr, All
        ; StringReplace, stringy, stringy, LCtrl + RCtrl + RAlt, RCtrl + AltGr, All
        StringReplace, stringy, stringy, LCtrl, Ctrl, All
        StringReplace, stringy, stringy, RCtrl, Ctrl, All
        StringReplace, stringy, stringy, LShift, Shift, All
        StringReplace, stringy, stringy, RShift, Shift, All
        StringReplace, stringy, stringy, LAlt, Alt, All
        StringReplace, stringy, stringy, LWin, WinKey, All
        StringReplace, stringy, stringy, RWin, WinKey, All
        StringReplace, stringy, stringy, Ctrl + Ctrl, Ctrl, All
        StringReplace, stringy, stringy, Shift + Shift, Shift, All
        StringReplace, stringy, stringy, WinKey + WinKey, WinKey, All
        StringReplace, stringy, stringy, RAlt, AltGr, All
    }
    return stringy
}

SpecialSC(sc) {
    GetSpecialKeysStates()

    GetKeyState, NumState, NumLock, T
    If NumState = D
    {
       k := {sc046: zcSCROL, sc145: "NUM LOCK ON", sc146: "Pause", sc123: "Genius LuxeMate Scroll", sc04E: "[ + ]", sc04A: "[ - ]", sc052: "[ 0 ]", sc04F: "[ 1 ]", sc050: "[ 2 ]", sc051: "[ 3 ]", sc04B: "[ 4 ]", sc04C: "[ 5 ]", sc04D: "[ 6 ]", sc047: "[ 7 ]", sc048: "[ 8 ]", sc049: "[ 9 ]", sc053: "[ . ]", sc037: "[ * ]", sc135: "[ / ]", sc11C: "[Enter]", sc149: "Page Up", sc151: "Page Down", sc153: "Delete", sc122: "Media_Play/Pause"}
    }
    else {
       k := {sc046: zcSCROL, sc145: "Num lock off", sc146: "Pause", sc123: "Genius LuxeMate Scroll", sc04E: "[ + ]", sc04A: "[ - ]", sc052: "[Insert]", sc04F: "[End]", sc050: "[Down]", sc051: "[Page Down]", sc04B: "[Left]", sc04C: "", sc04D: "[Right]", sc047: "[Home]", sc048: "[Up]", sc049: "[Page Up]", sc053: "[Delete]", sc037: "[ * ]", sc135: "[ / ]", sc11C: "[Enter]", sc149: "Page Up", sc151: "Page Down", sc153: "Delete", sc122: "Media_Play/Pause"}
    }
    return k[sc]
}

; by Lexikos -- https://autohotkey.com/board/topic/110808-getkeyname-for-other-languages/#entry682236
GetKeyChar(Key, WinTitle:=0) {
    thread := WinTitle=0 ? 0
        : DllCall("GetWindowThreadProcessId", "ptr", WinExist(WinTitle), "ptr", 0)
    hkl := DllCall("GetKeyboardLayout", "uint", thread, "ptr")
    vk := GetKeyVK(Key), sc := GetKeySC(Key)
    VarSetCapacity(state, 256, 0)
    VarSetCapacity(char, 4, 0)
    n := DllCall("ToUnicodeEx", "uint", vk, "uint", sc
        , "ptr", &state, "ptr", &char, "int", 2, "uint", 0, "ptr", hkl)
    return StrGet(&char, n, "utf-16")
}

IsDoubleClick(MSec = 300) {
    Return (A_ThisHotKey = A_PriorHotKey) && (A_TimeSincePriorHotkey < MSec)
}

IsDoubleClickEx(MSec = 300) {
    preHotkey := RegExReplace(A_PriorHotkey, "i) Up$")
    Return (A_ThisHotKey = preHotkey) && (A_TimeSincePriorHotkey < MSec)
}

HideGUI() {
    visible := 0
    Gui, Hide
}

!+^F8::
    ShowSingleKey := (!ShowSingleKey) ? true : false
    ShowHotkey("Show single keys = " ShowSingleKey)
    SetTimer, HideGUI, % -DisplayTime
return

!+^F9::
    GuiY := (GuiY = GuiYb) ? GuiYa : GuiYb
    ShowHotkey("OSD position changed")
    SetTimer, HideGUI, % -DisplayTime
return

!+^F12::
    Gui, Destroy
    sleep, 100
    CreateGUI()
    sleep, 100
    ShowHotkey("OSD reinitialized")
    SetTimer, HideGUI, % -DisplayTime
return
-------------------------
KeyPress OSD v4: GitHub or forum. (presentation video)
Quick Picto Viewer: GitHub or forum.
AHK GDI+ expanded / compilation library (on GitHub)
My home page.
robodesign
Posts: 941
Joined: 30 Sep 2017, 03:59
Location: Romania
Contact:

Re: [Script] KeypressOSD - Display key press on screen

30 Sep 2017, 16:17

A newer version here:

http://p.ahkscript.org/?p=db5cfc58


; CHANGELOG:
; by Marius Sucan (robodesign.ro)
; v2.69 (2017-09-30) - OSD / GUI hides when mouse is over it. Many thanks to phaleth!
; v2.68 (2017-09-29) - numpad keys now work in typing mode as expected; they appear as symbols or numbers

; TO-DO:::::::::::::::::::::::::::::::::::
; features to implement:
; - when user types single letters, display Shift + (sign or numeric keys) as signs/symbols, eg. Shift + 0, should be displayed as ) done
;
; and numerous glitches to fix....

Best regards, Marius
Last edited by robodesign on 29 Oct 2017, 06:31, edited 1 time in total.
-------------------------
KeyPress OSD v4: GitHub or forum. (presentation video)
Quick Picto Viewer: GitHub or forum.
AHK GDI+ expanded / compilation library (on GitHub)
My home page.
robodesign
Posts: 941
Joined: 30 Sep 2017, 03:59
Location: Romania
Contact:

Re: [Script] KeypressOSD - Display key press on screen

03 Oct 2017, 14:18

Hello!

New version available.

Script at: http://p.ahkscript.org/?p=585f9e18

; CHANGELOG:
; by Marius Sucan (robodesign.ro)
; v2.70 (2017-10-03)
- added option to toggle dead keys support / work-around.
- added option to hide annoying keys that usually get in the way: Left Click and Print Screen.
- redraw improvements, reduced flickering
- disabled OSD transparency to reduce flickering

; TO-DO:::::::::::::::::::::::::::::::::::
; features to implement:
; - when user types single letters, display Shift + (sign or numeric keys) as signs/symbols, eg. Shift + 0, should be displayed as ); done
; - after pressing Shift + [letter] if the following key is a single letter, remember the first Shift + [letter]; done
; - show a generic symbol for ignored dead keys; helps to clarify one was pressed;
; - after a Numpad key is pressed, typing mode should begin if the second one is another numpad key; done
;
; glitches to fix [by priority]:
; - show Shift as a modifier, as Ctrl and Alt; Shift should behave as the other two; it is never displayed alone and countable; done
; - always count mouse clicks; it sometimes does, other times it does not; no idea why; done
; - once a key is pressed, counting of key fires is not initiated after the OSD was hidden for a little awhile;
; - if dead keys support / work-around enabled, once you typed a caret [^], sometimes user gets randomly inserted carets when typing; done
; - automatic resizing of the OSD/GUI is just a silly hack based on the default font size and the number of typed chars; it often fails to resize properly;
; - redraw issues; it still flickers too much;
; - make dead keys 100% work, always; with the current implementation, the special keys show up seemingly random in the OSD and sometimes in the text field the user types in; done
; - make it work reliably with sticky keys; if user presses once Ctrl and another key afterwards, it rarely detects the combination on Winndows 7;
; - test Romanian kbd layout as suggested by drugwash; done

Code: Select all


; KeypressOSD.ahk
;--------------------------------------------------------------------------------------------------------------------------
;
; AVAILABLE SHORTCUTS:
; Ctrl+Alt+Shift+F8  - toggles "Show single key" option. Useful when you must reliably use dead keys.
; Ctrl+Alt+Shift+F9  - toggles between two OSD offsets: GuiYa and GuiYb
; Ctrl+Alt+Shift+F12 - Reinitialize OSD. Useful when it no longer appears on top. To have it appear on top of elevated apps, run it in administrator mode.
;
; CHANGELOG:
; by Marius Sucan (robodesign.ro)
;             v2.70 (2017-10-03) - added option to toggle dead keys support / work-around.
;                                - added option to hide annoying keys that usually get in the way: Left Click and Print Screen.
;                                - redraw improvements, reduced flickering
;                                - disabled OSD transparency to reduce flickering
;             v2.69 (2017-09-30) - OSD / GUI hides when mouse is over it. Many thanks to phaleth!
;             v2.68 (2017-09-29) - numpad keys now work in typing mode as expected; they appear as symbols or numbers
;
; by phaleth from irc.freenode.net #ahk
;             v2.67 (2017-09-28) - dead keys improvements
;
; by Marius Sucan (robodesign.ro)
;             v2.66 (2017-09-28) - key combinations with Shift work better.
;             v2.65 (2017-09-27) - Fixed a bug with counting modifier keys;
;                                - improved the dead keys work-around
;                                - friendly names for mouse clicks
;                                - when pressed, volume keys  always generate beeps
;                                - added option to differentiate between left and right modifiers
;                                - now it detects AltGr key
;                                - the key beeper now also makes a beep for modifiers.
;                                - capslock no longer erases text you are typing displayed by the OSD
;                                - now you can toggle between two different OSD positions with Ctrl + Alt + Shift + F9
;             v2.60 (2017-09-26) - Fixed many bugs with counting keys;
;                                - reimplemented the feature to see the previous key combination, if quickly a new one is pressed;
;                                - added options/settings to toggle previous keys, counting keys and delay;
;                                - added shortcuts to toggle ShowSingleKey option and to reinitialize the OSD;
;                                - added option for automatic resizing of the OSD; it can be turned off in the settings section; it is a fishy implementation, but if one adjusts it, can make it to suit personal needs;
;                                - added option to beep when key is released or when writing with capslock
;             v2.58 (2017-09-23) - Numpad keys have friendly naming, based on the numlock state.
;                                - Combinations with space and backspace work again.
;             v2.56 (2017-09-22) - more fixes for space usage and key combinations;
;                                - now it indicates when ScrollLock, NumLock and Capslock are activated.
;             v2.55 (2017-09-21) - minor fixes for space usage and key combinations.
;
; by Saiapatsu from irc.freenode.net #ahk
;             v2.54 (2017-09-21) - Scrolls through n recently typed characters instead of just the latest word
;             v2.53 (2017-09-21) - Case change effect limited to the 95 letters only.
;             v2.52 (2017-09-21) - Now supports backspace. Commented out CapsLock beeper.
;             v2.51 (2017-09-21) - Changed labels to functions, added ToolWindow style to window, changed DisplayTime
;                                  calculation, made it show last word typed, hid spacebar presses
;             todo: make Shift look less ugly
;
; by Marius Sucan (robodesign.ro)
;             v2.50 (2017-09-20) - Changed the OSD positioning and sizing. It was based on the current window. Now it is always fixed in a specific place. Added a Capslock beeper.
;
; by tmplinshi from https://autohotkey.com/boards/viewtopic.php?f=6&t=225
;             v2.22 (2017-02-25) - Now pressing same combination keys continuously more than 2 times,
;                                  for example press Ctrl+V 3 times, will displayed as "Ctrl + v (3)"
;             v2.21 (2017-02-24) - Fixed LWin/RWin not poping up start menu
;             v2.20 (2017-02-24) - Added displaying continuous-pressed combination keys.
;                                  e.g.: With CTRL key held down, pressing K and U continuously will shown as "Ctrl + k, u"
;             v2.10 (2017-01-22) - Added ShowStickyModKeyCount option
;             v2.09 (2017-01-22) - Added ShowModifierKeyCount option
;             v2.08 (2017-01-19) - Fixed a bug
;             v2.07 (2017-01-19) - Added ShowSingleModifierKey option (default is True)
;             v2.06 (2016-11-23) - Added more keys. Thanks to SashaChernykh.
;             v2.05 (2016-10-01) - Fixed not detecting "Ctrl + ScrollLock/NumLock/Pause". Thanks to lexikos.
;             v2.04 (2016-10-01) - Added NumpadDot and AppsKey
;             v2.03 (2016-09-17) - Added displaying "Double-Click" of the left mouse button.
;             v2.02 (2016-09-16) - Added displaying mouse button, and 3 settings (ShowMouseButton, FontSize, GuiHeight)
;             v2.01 (2016-09-11) - Display non english keyboard layout characters when combine with modifer keys.
;             v2.00 (2016-09-01) - Removed the "Fade out" effect because of its buggy.
;                                - Added support for non english keyboard layout.
;                                - Added GuiPosition setting.
;             v1.00 (2013-10-11) - First release by tmplinshi based on RaptorX. Function keys, numpad keys and mouse clicks support. Popups at mouse position.
;             v0.50 (2010-03-18) - Released by RaptorX.
;--------------------------------------------------------------------------------------------------------------------------
;
; TO-DO:::::::::::::::::::::::::::::::::::
; features to implement:
; - when user types single letters, display Shift + (sign or numeric keys) as signs/symbols, eg. Shift + 0, should be displayed as );
; - after pressing Shift + [letter] if the following key is a single letter, remember the first Shift + [letter];
; - show a generic symbol for ignored dead keys; helps to clarify one was pressed;
; - after a Numpad key is pressed, typing mode should begin if the second one is another numpad key;
;
; glitches to fix [by priority]:
; - show Shift as a modifier, as Ctrl and Alt; Shift should behave as the other two; it is never displayed alone and countable;
; - always count mouse clicks; it sometimes does, other times it does not; no idea why;
; - once a key is pressed, counting of key fires is not initiated after the OSD was hidden for a little awhile;
; - if dead keys support / work-around enabled, once you typed a caret [^], sometimes user gets randomly inserted carets when typing;
; - automatic resizing of the OSD/GUI is just a silly hack based on the default font size and the number of typed chars; it often fails to resize properly;
; - redraw issues; it still flickers too much;
; - make dead keys 100% work, always; with the current implementation, the special keys show up seemingly random in the OSD and sometimes in the text field the user types in;
; - make it work reliably with sticky keys; if user presses once Ctrl and another key afterwards, it rarely detects the combination on Winndows 7;
; - test Romanian kbd layout as suggested by drugwash;
;----------------------------------------------------------------------------

#SingleInstance force
#NoEnv
SetBatchLines, -1
ListLines, Off

; Settings.
    global DeadKeys              := 1     ; a toggle for a partial dead keys support. Zero [0] means no dead keys. See CreateHotkey() and char2skip to define the dead keys.
    global ShowSingleKey         := 1     ; show only key combinations
    global ShowMouseButton       := 1
    global HideAnnoyingKeys      := 1     ; Left click and PrintScreen.
    global ShowSingleModifierKey := 1     ; make it display Ctrl, Alt, Shift when pressed alone
    global DifferModifiers       := 0     ; differentiate between left and right modifiers
    global ShowPrevKey           := 1     ; show previously pressed key, if pressed quickly in succession
    global ShowPrevKeyDelay      := 300
    global ShowKeyCount          := 1     ; count how many times a key is pressed
    global ShowKeyCountFired     := 1     ; show only key presses (0) or catch key fires as well (1)
    global DisplayTime           := 3000  ; in milliseconds
;    global TransparencyLevel     := 220   ; OSD transparency; range from 0 to 255. feature disabled, to reduce flickering.
    global GuiWidth              := 360
    global GuiHeight             := 50
    global GuiX                  := 50
    global GuiYa                 := 250   ; toggle between GuiYa and GuiYb with Ctrl + Alt + Shift + F9
    global GuiYb                 := 800
    global FontSize              := 19
    global OSDautosize           := 1     ; make adjustments in ShowHotkey() to match your font size
    global NumLetters            := 25    ; amount of recently typed letters to display
    global NumLettersAutosize    := 60    ; ...when OSD resizes automatically
    global CapslockBeeper        := 1     ; beeps only when the key is released
    global KeyBeeper             := 0     ; beeps only when the key is released

; Initialization variables. Altering these may lead to undesired results.
    global typed := ""
    global visible := 0
    global GuiY := GuiYa
    global prefixed := 0 ; hack used to determine if last keypress had a modifier
    global zcSCROL := "SCROLL LOCK"
    global tickcount_start := 0   ; timer to count repeated key presses
    global keyCount := 0
    global ShowKeyCountDelay := (ShowKeyCountFired = 0) ? 700 : 6000
    #MaxHotkeysPerInterval 500
    NumLetters := (OSDautosize=1) ? NumLettersAutosize : NumLetters
    global text_width := 60

    CreateGUI()
    CreateHotkey()
    return

; The script

GetSpecialKeysStates() {
    GetKeyState, ScrollState, ScrollLock, T   
    If ScrollState = D
    {
       global zcSCROL := "SCROLL LOCK ON"
    }
    else {
       global zcSCROL := "Scroll lock off"
    }
}

TypedLetter(key) {
    return typed := SubStr(typed key, -NumLetters)
}

OnKeyPressed() {
    try {
        key := GetKeyStr()
        typed := "" ; concerning TypedLetter(" ") - it resets the content of the OSD
        ShowHotkey(key)
        SetTimer, HideGUI, % -DisplayTime
    }
}

OnLetterPressed() {
    try {
        if typed 
        {
            sleep, 25    ; this delay helps with dead keys,  but it generates errors; the following actions: stringleft,1 and stringlower help correct these
        } else
        {
        }

        key := GetKeyStr(1)     ; consider it a letter

        if prefixed
        {
            ShowHotkey(key)
        } else
        {
            StringLeft, key, key, 1
            Stringlower, key, key

            GetKeyState, CapsState, CapsLock, T
            If CapsState != D
            {
                 if GetKeyState("Shift", "P")
                {
                  StringUpper, key, key
                }
            } else
                StringUpper, key, key

            TypedLetter(key)
            ShowHotkey(typed)
        }
        SetTimer, HideGUI, % -DisplayTime
    }
}

OnSpacePressed() {
    try {
        if typed {
            if (visible)
            {
                TypedLetter("_")
                ShowHotkey(typed)
            } else
            {
                TypedLetter("_")
                ShowHotkey(typed)
                SetTimer, HideGUI, % -DisplayTime
            }
        } else if (!typed)
        {
          key := GetKeyStr()
          ShowHotkey(key)
          SetTimer, HideGUI, % -DisplayTime
        }
    }
}

OnBspPressed() {
    If (KeyBeeper = 1)
       {
         soundbeep, 1900, 45
       }
    try
    {
        if typed
        {
            typed := SubStr(typed, 1, StrLen(typed) - 1)
            ShowHotkey(typed)
        } else if (!typed)
        {
            key := GetKeyStr()
            ShowHotkey(key)
            SetTimer, HideGUI, % -DisplayTime
        }
    }
}

OnCapsPressed() {
    try
    {
        if typed
        {
            ShowHotkey(typed)
        } else if (!typed)
        {
            key := GetKeyStr()
            GetKeyState, CapsState, CapsLock, T
            if CapsState = D
            {
                key := prefixed ? key : "CAPSLOCK ON"
            } else
                key := prefixed ? key : "CapsLock off"
            ShowHotkey(key)
            SetTimer, HideGUI, % -DisplayTime
        }
    }

    If (CapslockBeeper = 1)
       {
        soundbeep, 450, 200
       }
}

OnNumpadPressed()
{
    GetKeyState, NumState, NumLock, T
    try {
        if NumState != D
        {
            key := GetKeyStr()
            ShowHotkey(key)
            SetTimer, HideGUI, % -DisplayTime
        } else if !typed
        {
            key := GetKeyStr()
            ShowHotkey(key)
        } else if NumState = D
        {
            key := GetKeyStr(1) ; consider it a letter
            StringLeft, key, key, 3
            StringRight, key, key, 1
            TypedLetter(key)
            ShowHotkey(typed)
        }
        SetTimer, HideGUI, % -DisplayTime
    }
}

OnKeyUp()
{
       If (KeyBeeper = 1)
       {
         soundbeep, 150, 45
       }
}

_OnKeyUp() {
    global tickcount_start := A_TickCount

    if typed && (CapslockBeeper = 1)
    {
        GetKeyState, CapsState, CapsLock, T
        If CapsState = D
           {
             soundbeep, 450, 25
           }
           else if (KeyBeeper = 1)
           {
             soundbeep, 1900, 45
           }
    }

    If (CapslockBeeper = 0) && (KeyBeeper = 1)
       {
         soundbeep, 1900, 45
       }
       else if (CapslockBeeper = 1) && (KeyBeeper = 0)
       {
       }
       else if !typed && (CapslockBeeper = 1)
       {
         soundbeep, 1900, 45
       }

}

; ===================================================================================

CreateGUI() {
    global

    Gui, +AlwaysOnTop -Caption +Owner +LastFound +ToolWindow +E0x20
    Gui, Margin, 10, 10
    Gui, Color, 111111
    Gui, Font, cWhite s%FontSize% bold, Arial, -wrap
    Gui, Add, Text, vHotkeyText left x10 y10 -wrap

;    if TransparencyLevel between 10 and 245
;       WinSet, Transparent, %TransparencyLevel%

}

CreateHotkey() {

    Loop, 95
    {
        k := Chr(A_Index + 31)

        if DeadKeys=1
        {
            for each, char2skip in StrSplit("``,^,',"",~", ",")  ; dead keys to ignore
            {
                if (k = char2skip && DeadKeys=1)
                {
                    continue, 2
                }
            }
        }

        if (k = " ")
        {
            Hotkey, % "~*Space", OnSpacePressed
            Hotkey, % "~*Space Up", _OnKeyUp
        }
        else
        {
            Hotkey, % "~*" k, OnLetterPressed
            Hotkey, % "~*" k " Up", _OnKeyUp
        }
    }

    Hotkey, % "~*Backspace", OnBspPressed
    Hotkey, % "~*CapsLock", OnCapsPressed

    Loop, 24 ; F1-F24
    {
        Hotkey, % "~*F" A_Index, OnKeyPressed
        Hotkey, % "~*F" A_Index " Up", _OnKeyUp
    }

    Loop, 10 ; Numpad0 - Numpad9
    {
        Hotkey, % "~*Numpad" A_Index - 1, OnNumpadPressed
        Hotkey, % "~*Numpad" A_Index - 1 " Up", _OnKeyUp
    }

    NumpadKeysList := "NumpadDot|NumpadDiv|NumpadMult|NumpadAdd|NumpadSub|sc04E|sc04A|sc052|sc04F|sc050|sc051|sc04B|sc04C|sc04D|sc047|sc048|sc049|sc053|sc037|sc135"

    Loop, parse, NumpadKeysList, |
    {
       Hotkey, % "~*" A_LoopField, OnNumpadPressed
       Hotkey, % "~*" A_LoopField " Up", _OnKeyUp
    }

    Otherkeys := "WheelDown|WheelUp|WheelLeft|WheelRight|XButton1|XButton2|Browser_Forward|Browser_Back|Browser_Refresh|Browser_Stop|Browser_Search|Browser_Favorites|Browser_Home|Volume_Mute|Volume_Down|Volume_Up|Media_Next|Media_Prev|Media_Stop|Media_Play_Pause|Launch_Mail|Launch_Media|Launch_App1|Launch_App2|Help|Sleep|PrintScreen|CtrlBreak|Break|AppsKey|Tab|Enter|Esc"
               . "|Insert|Home|End|Up|Down|Left|Right|ScrollLock|NumLock|Pause|sc145|sc146|sc046|sc123|sc11C|sc149|sc151|sc122|sc153|sc152"
    Loop, parse, Otherkeys, |
    {
        Hotkey, % "~*" A_LoopField, OnKeyPressed
        Hotkey, % "~*" A_LoopField " Up", _OnKeyUp
    }

    If ShowMouseButton {
        Loop, Parse, % "LButton|MButton|RButton", |
        Hotkey, % "~*" A_LoopField, OnKeyPressed
    }

    for i, mod in ["LCtrl", "RCtrl", "LAlt", "RAlt"] {
        Hotkey, % "~*" mod, OnKeyPressed
        Hotkey, % "~*" mod " Up", OnKeyUp
    }

    for i, mod in ["LWin", "RWin"]
        Hotkey, % "~*" mod, OnKeyPressed
        Hotkey, % "~*" mod " Up", OnKeyUp

    If typed {
    for i, mod in ["LShift", "RShift"]
        Hotkey, % "~*" mod, OnKeyPressed
        Hotkey, % "~*" mod " Up", OnKeyUp
    }
}

ShowHotkey(HotkeyStr) {

    if GetKeyState("Shift", "P") && (HotkeyStr ~= "\^") && typed && !prefixed && DeadKeys
    {
        SendRaw, ^
        return
    }

    if (OSDautosize=1) && (A_TickCount-tickcount_start > 70)
    {
        text_width := (StrLen(HotkeyStr)/1.3)*FontSize
        text_width := (text_width<70) ? 70 : text_width+15
    } else if OSDautosize=0
    {
        text_width := GuiWidth
    }

    if !typed
    {
        StringUpper, HotkeyStr, HotkeyStr, T
    }


    GuiControl,     , HotkeyText, %HotkeyStr%
    GuiControl, Move, HotkeyText, w%text_width% left
    Gui, Show, NoActivate x%GuiX% y%GuiY% AutoSize, KeypressOSD
    visible := 1
    SetTimer, runThisRepeatedly, on, 800
}

GetKeyStr(letter := 0) {
    static modifiers := ["LCtrl", "RCtrl", "LAlt", "RAlt", "LShift", "RShift", "LWin", "RWin"]
    static repeatCount := 1

    ; If any mod but shift, go ; If shift, check if not letter

    for i, mod in modifiers
    {
        if (mod = "LShift" && typed || mod = "RShift" && typed ? (!letter && GetKeyState(mod)) : GetKeyState(mod))
            prefix .= mod " + "
    }

    if (!prefix && !ShowSingleKey)
        throw

    key := SubStr(A_ThisHotkey, 3)

    if (key ~= "i)^(LCtrl|RCtrl|LShift|RShift|LAlt|RAlt|LWin|RWin)$") {
        if !ShowSingleModifierKey || (A_TickCount-tickcount_start > 2000) && visible
        {
            throw
        } else
        {
             key := ""
             prefix := RTrim(prefix, "+ ")
        }

        prefix := CompactModifiers(prefix)

        if (ShowKeyCount=1) {
            if !InStr(prefix, "+") && IsDoubleClickEx() {
                if (A_ThisHotKey != A_PriorHotKey) || (ShowKeyCount=1) && (A_TickCount-tickcount_start < ShowKeyCountDelay+repeatCount*100) {
                    if (++repeatCount > 1) {
                        prefix .= " {" repeatCount "}"
                    }
                } else {
                    repeatCount := 0
                }
            } else {
                repeatCount := 1
            }
        }
    } else {
        if ( StrLen(key) = 1 ) {
            key := GetKeyChar(key, "A")
        } else if ( SubStr(key, 1, 2) = "sc" ) {
            key := SpecialSC(key)
        } else if (key = "Volume_Up") || (key = "Volume_Down") {
            soundbeep, 150, 40
        } else if (key = "PrintScreen") {
            if HideAnnoyingKeys
                throw
            key := "Print Screen"
        } else if (key = "MButton") {
            key := "Middle Click"
        } else if (key = "RButton") {
            key := "Right Click"
        } else if (key = "LButton") && IsDoubleClick() {
            key := "Double-Click"
        } else if (key = "LButton") {
            if HideAnnoyingKeys
                throw
            key := "Left Click"
        }
        {
            _key := (key = "Double-Click") ? "Left Click" : key
        }

        prefix := CompactModifiers(prefix)

        static pre_prefix, pre_key, keyCount := 1
        keyCount := (key=pre_key) && (prefix = pre_prefix) ? keyCount : 1
        global ShowKeyCountDelay := (ShowKeyCountFired = 0) ? 700 : 6000
        ShowKeyCountDelay := (ShowKeyCountFired=1) ? (ShowKeyCountDelay+keyCount*100) : ShowKeyCountDelay

        if (InStr(prefix, "+")) && (A_TickCount-tickcount_start < ShowKeyCountDelay) || (!letter) && (A_TickCount-tickcount_start < ShowKeyCountDelay)
        {
            if (ShowPrevKey=1) && (A_TickCount-tickcount_start < ShowPrevKeyDelay) && !typed
            {
                ShowPrevKeyValid := 1
            } else
            {
                ShowPrevKeyValid := 0
            }
            if (prefix != pre_prefix) {
                result := (ShowPrevKeyValid=1) ? prefix key " {" pre_prefix pre_key "}" : prefix key
            } else if (ShowPrevKeyValid=1) && (key != pre_key) || (ShowKeyCount=1) && (ShowPrevKeyValid=1)
            {
                keyCount := (key=pre_key) && (ShowKeyCount=1) ? (keyCount+1) : 1
                key := (keyCount>1) && (ShowKeyCount=1) ? (key " {" keyCount "}") : (key ", " pre_key)
            } else if (ShowPrevKeyValid=0)
            {
                keyCount := (key=pre_key) && (ShowKeyCount=1) ? (keyCount+1) : 1
                key := (keyCount>1) ? (key " {" keyCount "}") : (key)
            }
        } else {
            keyCount := 1
        }

        pre_prefix := prefix
        pre_key := _key

        repeatCount := 1
    }

    prefixed := prefix ? 1 : 0
    return result ? result : prefix . key
}

CompactModifiers(stringy)
{
    if DifferModifiers = 1
    {
        StringReplace, stringy, stringy, LCtrl + RAlt, AltGr, All
        StringReplace, stringy, stringy, LCtrl + RCtrl + RAlt, RCtrl + AltGr, All
        StringReplace, stringy, stringy, RAlt, AltGr, All
        StringReplace, stringy, stringy, LAlt, Alt, All
    } else if (DifferModifiers = 0)
    {
        StringReplace, stringy, stringy, LCtrl + RAlt, AltGr, All
        ; StringReplace, stringy, stringy, LCtrl + RCtrl + RAlt, RCtrl + AltGr, All
        StringReplace, stringy, stringy, LCtrl, Ctrl, All
        StringReplace, stringy, stringy, RCtrl, Ctrl, All
        StringReplace, stringy, stringy, LShift, Shift, All
        StringReplace, stringy, stringy, RShift, Shift, All
        StringReplace, stringy, stringy, LAlt, Alt, All
        StringReplace, stringy, stringy, LWin, WinKey, All
        StringReplace, stringy, stringy, RWin, WinKey, All
        StringReplace, stringy, stringy, Ctrl + Ctrl, Ctrl, All
        StringReplace, stringy, stringy, Shift + Shift, Shift, All
        StringReplace, stringy, stringy, WinKey + WinKey, WinKey, All
        StringReplace, stringy, stringy, RAlt, AltGr, All
    }
    return stringy
}

SpecialSC(sc) {
    GetSpecialKeysStates()

    GetKeyState, NumState, NumLock, T
    If NumState = D
    {
       k := {sc046: zcSCROL, sc145: "NUM LOCK ON", sc146: "Pause", sc123: "Genius LuxeMate Scroll", sc04E: "[ + ]", sc04A: "[ - ]", sc052: "[ 0 ]", sc04F: "[ 1 ]", sc050: "[ 2 ]", sc051: "[ 3 ]", sc04B: "[ 4 ]", sc04C: "[ 5 ]", sc04D: "[ 6 ]", sc047: "[ 7 ]", sc048: "[ 8 ]", sc049: "[ 9 ]", sc053: "[ . ]", sc037: "[ * ]", sc135: "[ / ]", sc11C: "[Enter]", sc149: "Page Up", sc151: "Page Down", sc153: "Delete", sc122: "Media_Play/Pause"}
    }
    else {
       k := {sc046: zcSCROL, sc145: "Num lock off", sc146: "Pause", sc123: "Genius LuxeMate Scroll", sc04E: "[ + ]", sc04A: "[ - ]", sc052: "[Insert]", sc04F: "[End]", sc050: "[Down]", sc051: "[Page Down]", sc04B: "[Left]", sc04C: "", sc04D: "[Right]", sc047: "[Home]", sc048: "[Up]", sc049: "[Page Up]", sc053: "[Delete]", sc037: "[ * ]", sc135: "[ / ]", sc11C: "[Enter]", sc149: "Page Up", sc151: "Page Down", sc153: "Delete", sc122: "Media_Play/Pause"}
    }
    return k[sc]
}

; by Lexikos -- https://autohotkey.com/board/topic/110808-getkeyname-for-other-languages/#entry682236
GetKeyChar(Key, WinTitle:=0) {
    thread := WinTitle=0 ? 0
        : DllCall("GetWindowThreadProcessId", "ptr", WinExist(WinTitle), "ptr", 0)
    hkl := DllCall("GetKeyboardLayout", "uint", thread, "ptr")
    vk := GetKeyVK(Key), sc := GetKeySC(Key)
    VarSetCapacity(state, 256, 0)
    VarSetCapacity(char, 4, 0)
    n := DllCall("ToUnicodeEx", "uint", vk, "uint", sc
        , "ptr", &state, "ptr", &char, "int", 2, "uint", 0, "ptr", hkl)
    return StrGet(&char, n, "utf-16")
}

IsDoubleClick(MSec = 300) {
    Return (A_ThisHotKey = A_PriorHotKey) && (A_TimeSincePriorHotkey < MSec)
}

IsDoubleClickEx(MSec = 300) {
    preHotkey := RegExReplace(A_PriorHotkey, "i) Up$")
    Return (A_ThisHotKey = preHotkey) && (A_TimeSincePriorHotkey < MSec)
}

HideGUI() {
    visible := 0
    Gui, Hide
    SetTimer, runThisRepeatedly, off, 300

}

!+^F8::
    ShowSingleKey := (!ShowSingleKey) ? true : false
    ShowHotkey("Show single keys = " ShowSingleKey)
    SetTimer, HideGUI, % -DisplayTime
return

!+^F9::
    GuiY := (GuiY = GuiYb) ? GuiYa : GuiYb
    ShowHotkey("OSD position changed")
    SetTimer, HideGUI, % -DisplayTime
return

!+^F12::
    Gui, Destroy
    sleep, 100
    CreateGUI()
    sleep, 100
    ShowHotkey("OSD reinitialized")
    SetTimer, HideGUI, % -DisplayTime
return

runThisRepeatedly() {
    id := mouseIsOver()
    title := getWinTitleFromID(id)
    if title = KeypressOSD
        HideGUI()
}

mouseIsOver() {
    MouseGetPos,,, id
    return id
}

getWinTitleFromID(id) {
    WinGetTitle, title, % "ahk_id " id
    return title
}
Best regards, Marius.
Last edited by robodesign on 29 Oct 2017, 06:33, edited 1 time in total.
-------------------------
KeyPress OSD v4: GitHub or forum. (presentation video)
Quick Picto Viewer: GitHub or forum.
AHK GDI+ expanded / compilation library (on GitHub)
My home page.

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: submeg and 119 guests