74

I'm giving training to a large group of people remotely and will be covering a number of application shortcut keys.

I've seen MousePose's on-screen display of keystrokes; is there a way to get this same effect but for key presses?

MousePose Screenshot

I do not need anything fancy, just key presses displayed on screen where they can be captured by meeting software during a screen share.

I haven't been able to figure this out myself.

2
  • 1
    If this question is off-topic on Super User, can people at least write what of the stack-exchange sites is appropriate for this question?
    – sdbbs
    Sep 28, 2020 at 7:22
  • @sdbbs Possibily softwarerecs.stackexchange.com
    – tejasvi88
    Jan 17, 2021 at 11:14

9 Answers 9

38

KeyPosé is a free alternative to MousePosé for Windows. You can see it in action in the screencast.

Here is a sample screenshot:

alt text

9
  • @richard you're more than welcome!
    – user1931
    Feb 4, 2010 at 16:46
  • 5
    I think it has some issues. You cannot change the position where you display the keys, sometimes the grey zone keeps showing even if you're not pressing a key, also the win/super key isn't displayed. Combinations which involves more than two keys pressed, like ctrl+alt+c, are displayed in a weird way, like first CTRL, then ALT (I suppose it should display CTRL+ALT) and finally CTRL+ALT+C. Is better than nothing, but I think there are better options. May 6, 2014 at 22:50
  • Doesn't register Tab keys for some reason... Oct 14, 2016 at 13:45
  • 1
    Use Carnac below. I tested both and Carnac gives you various visual options. github.com/bfritscher/carnac/releases/tag/v3-beta
    – Avatar
    Nov 19, 2017 at 7:50
  • 1
    link provided is old and to a potentially unsafe ZIP, here is the source: github.com/AxDSan/KeyPose
    – OzBob
    Dec 10, 2018 at 6:04
34

I highly recommend Carnac The Magnificent. It's nicely executed, nicely designed and open sourced on GitHub project that really solves this problem well.

A keyboard logging and presentation utility for presentations, screencasts, and to help you become a better keyboard user.

Screenshot

There is a fork with visualization of mouse input here: https://github.com/bfritscher/carnac/releases

9
  • Interesting, but not as beautiful rendering as KeyPosé.
    – Basj
    Sep 5, 2017 at 19:19
  • The project page provides only a carnac.application file, the youtube video youtube.com/watch?v=qSUDfzUkwnc shows a Carnac.exe. Just later I realized that I can launch carnac.application in Windows and it downloads and installs the program. I found the zip/exe also here: github.com/downloads/Code52/carnac/Carnac.zip
    – Avatar
    Nov 19, 2017 at 7:41
  • 2
    @Basj Carnac is much more "beautiful" than KeyPosé (which only shows the letters as plain text). With Carnac you can change the appearance of the keys shown (font size, opacity, colors).
    – Avatar
    Nov 19, 2017 at 7:48
  • @KaiNoack I mean the default style of Carnac is not as stylish / minimalist as Keyposé. The default design should be improved ;)
    – Basj
    Nov 19, 2017 at 10:27
  • 1
    @jdhao Double-click the Carnac icon in the notification area, then you can customize the location on screen. You can then save/set defaults etc.
    – rburte
    May 16, 2019 at 16:58
11

I would like to share my tool -- keycastow.

https://brookhong.github.io/2014/04/28/keycast-on-windows.html

enter image description here

8
  • 1
    Great thing! Also LICECap is great too, didn't know about one :) Jun 28, 2014 at 8:16
  • @brookhong what did you use to create the animated giff?
    – Ricardo C
    Nov 10, 2015 at 17:20
  • @RicardoC It's licecap, cockos.com/licecap
    – brook hong
    Nov 11, 2015 at 3:47
  • Microsoft Security Essentials classifies this as a threat. Oh well!
    – rath
    Nov 5, 2016 at 11:57
  • 1
    This tool is not downloadable as a binary; you have to build it yourself which for me is an issue because I don't have permission.
    – Lqueryvg
    Mar 17, 2018 at 10:48
7

I've written an AutoHotkey_L script for this purpose.

To run it, use AutoHotkey_L (direct dl), it's FOSS. Also, with AutoHotkey you can compile script to EXE (simply Ahk2Exe.exe /in DisplayPressedKeyOnScreen.ahk/outDisplayPressedKeyOnScreen.exe ).

It can display pressed keys OSD-like or standard Tool-tip near mouse cursor. Also, it displays mouse button clicks and wheel scrolling.

(note that frame & blurring is done for illustration purposes, the script itself only displays text w/o any disturbances) Screenshot

Heres's the script (copy and paste to notepad, save as DisplayPressedKeysOnScreen.ahk):

#NoEnv
#SingleInstance force
#InstallKeybdHook
#MaxHotkeysPerInterval 500

;This work by LogicDaemon is licensed under a Creative Commons Attribution 3.0 Unported License.

Global IdleDelay, LargeDisplay

IdleDelay:=3000

LargeDisplay:=1
; 0 = Tooltip near mouse pointer
; 1 = Big pane at screen bottom

;TrayTip %A_ScriptName%, Чтобы выйти`, нажмите правую клавишу Windows
TrayTip %A_ScriptName%, To Exit`, press the Right Windows logo key.

InputHook := InputHook("BCL1qMV*", "", "")
InputHook.KeyOpt("{All}", "INV")
InputHook.OnKeyDown := Func("OnKeyDown")
InputHook.OnKeyUp := Func("OnKeyUp")
InputHook.OnEnd := Func("RegisterKey")
Loop {
    InputHook.Start()
    InputHook.Wait()
}

return

RWin::
    ExitApp

~*LButton::
~*RButton::
~*MButton::
~*XButton1::
~*XButton2::
    MouseTooltip(SubStr(A_ThisHotkey, 3), 1)
    return

~*LButton Up::
~*RButton Up::
~*MButton Up::
~*XButton1 Up::
~*XButton2 Up::
    MouseTooltip(SubStr(A_ThisHotkey, 3, -3), 0)
    return

~*WheelDown::
~*WheelUp::
~*WheelLeft::
~*WheelRight::
    MouseTooltip(SubStr(A_ThisHotkey, 3), 1)
    MouseTooltip(SubStr(A_ThisHotkey, 3), 0)
    return

MouseTooltip(mbuttons, state){
    RegisterKey(mbuttons, state)
}

TooltipOff:
    If LargeDisplay
        Gui Hide
    Else
        Tooltip
    lastStatesText := {}
    return

OnKeyDown(inputHook, VK, SC) {
    RegisterKey(inputHook, 1, VK, SC)
}

OnKeyUp(inputHook, VK, SC) {
    RegisterKey(inputHook, 0, VK, SC)
}

RegisterKey(inputHook, kstate := 1, VK := 0, SC := 0) {
    local
    global IdleDelay, lastStatesText, inputString
    static keyStates := {}, prevKey, lastPressed, prevState, repeated := 0
         , KeyMappingToName := { (Chr(27)): "Escape"
                               , (Chr(32)): "Space"
                               , (Chr(10)): "Enter" }
         , SkipRepeat := { "LShift": ""
                         , "RShift": ""
                         , "LControl": ""
                         , "RControl": ""
                         , "LAlt": ""
                         , "RAlt": ""
                         , "LWin": ""
                         , "RWin": "" }
         , StringEndKeys := { "{Enter}": ""
                            , "{Escape}": ""
                            , "{Tab}": ""
                            , "{Up}": ""
                            , "{Down}": ""
                            , "{PgUp}": ""
                            , "{PgDn}": "" }
    
    If (VK || SC) {
        singleKey := GetKeyName(Format("vk{:02x}sc{:02x}", VK, SC))
    } Else If (!IsObject(inputHook)) {
        singleKey := inputHook
    }
    textKey := StrLen(singleKey) == 1 ? singleKey : "{" singleKey "}"
    keyStatesText := ""
    For key, state in keyStates
        If (state && key != singleKey)
            keyStatesText .= key "+"
    keyStates[singleKey] := kstate
    If (kstate && lastPressed == textKey && keyStatesText == lastStatesText) {
        If (!SkipRepeat.HasKey(singleKey))
            repeated++
    } Else {
        If (kstate) {
            If (repeated) {
                inputString .= (repeated > 4 || StrLen(lastPressed) > 1) ? "×" . repeated+1 : StrRepeat(lastPressed, repeated)
                , repeated := 0
            }
            If (keyStatesText != lastStatesText || StringEndKeys.HasKey(lastPressed))
                inputString := textKey, lastStatesText := keyStatesText
            Else If (StrLen(inputString) < 15)
                inputString .= textKey
            Else
                inputString := "…" SubStr(inputString, -15) textKey
            lastPressed := textKey
        }
    }
    ShowKeys((lstate ? keyStatesText : lastStatesText) . inputString . (repeated ? ("×" . repeated+1) : (kstate ? "↓" : "↑")))
    prevKey := singleKey, prevState := kstate
    
    SetTimer TooltipOff, % -IdleDelay
}

ShowKeys(text) {
    global GUIx, GUIy, GUIw, GUIh
         , blkOsdCtrlName, blkOsdCtrlName2
         , MonitorLeft, MonitorRight, MonitorBottom, MonitorTop
    
    If (LargeDisplay) {
        CoordMode Mouse, Screen
        MouseGetPos MouseX, MouseY

        InitLargeDisplay(MouseX, MouseY)
        
        If ((!GUIy) || (MouseX >= MonitorLeft && MouseX <= MonitorRight && MouseY >= GUIy && MouseY <= (GUIy+GUIh)) ) {
            If (MouseY < (MonitorTop + (MonitorBottom - MonitorTop) / 2) )
                GUIy := MonitorBottom - (MonitorBottom - MonitorTop) * 0.2
            Else
                GUIy := MonitorTop + (MonitorBottom - MonitorTop) * 0.2
        }
        
        GuiControl Text, blkOsdCtrlName, %text%
        GuiControl Text, blkOsdCtrlName2, %text%

        Gui, Show, x%GUIx% y%GUIy% NoActivate
    } Else {
        Tooltip % text
    }
}

InitLargeDisplay(MouseX, MouseY) {
    global GUIx, GUIy, GUIw, GUIh
         , blkOsdCtrlName, blkOsdCtrlName2
         , Monitor, MonitorLeft, MonitorRight, MonitorBottom, MonitorTop
    static guiInitialized := False
    ;Initializing GUI / reinitializing after changing monitor
    ;modded func originated from http://www.autohotkey.com/board/topic/8190-osd-function/

    If ( (   MouseX < MonitorLeft
          || MouseX > MonitorRight
          || MouseY < MonitorTop
          || MouseY > MonitorBottom)
        || !guiInitialized) { ; mouse is outside of last screen GUI was positioned at
        ;80 SM_CMONITORS: Number of display monitors on the desktop (not including "non-display pseudo-monitors"). 
        SysGet monCount, 80
        Loop % monCount
        {
            SysGet Monitor, Monitor, %A_Index%
            If (MouseX >= MonitorLeft && MouseX <= MonitorRight && MouseY >= MonitorTop && MouseY <= MonitorBottom) {
                found := true
                break
            }
        }

        If (!found) ; mouse cursor not found on any screen, fallback to default monitor
            SysGet Monitor, Monitor
        
        GUIx := MonitorLeft
        , GUIw := MonitorRight - MonitorLeft
        , GUIh := (MonitorBottom - MonitorTop) * GUIw * 0.00003
        If (GUIh > ((MonitorBottom - MonitorTop) * 0.3))
            GUIh := (MonitorBottom - MonitorTop) * 0.3
        
        opacity:="230"
        , fname:="Tahoma"
        , fsize:=GUIh * 0.65 ; really, pixel = 0.75 point, but with 0.75 lowercase letter with lower part (like "g") will get cut
        , fcolor:="cccccc"
        , bcolor:="222222"
        , fformat:="600"
        
        If (guiInitialized)
            Gui Destroy
        Gui +LastFound +AlwaysOnTop +ToolWindow -Caption
        Gui Margin, 0, 0 ;pixels of space to leave at the left/right and top/bottom sides of the window when auto-positioning.
        Gui Color, ffffff ;changes background color
        Gui Font, s%fsize% w%fformat%, %fname%

        ; 0x80 = SS_NOPREFIX -> Ampersand (&) is shown instead of underline one letter for Alt+letter navigation
        Gui Add, Text, c%bcolor% Center +0x80 w%GUIw% h%GUIh% BackgroundTrans VblkOsdCtrlName, tesT test test
        Gui Add, Text, c%fcolor% Center +0x80 w%GUIw% h%GUIh% BackgroundTrans VblkOsdCtrlName2 xp-3 yp-3 , tesT test test
        
        WinSet ExStyle, +0x20 ; WS_EX_TRANSPARENT -> mouse klickthrough
        WinSet TransColor, ffffff %opacity%

        guiInitialized := True
    }
}

StrRepeat(str, cnt) {
    If (cnt<1)
        return ""
    o := str
    Loop % cnt-1
        o .= str
    return o
}
12
  • I tried to start "DisplayPressedKeyOnScreen.exe" on Win7 64bit. I get the error message Windows cannot access the specified device, path, or file. You may not have the appropriate permissions to access the item. Is the exe-file a standalone? Or do I have to install AutoHotkey beforehand?
    – Avatar
    Jun 26, 2014 at 21:43
  • @EchtEinfachTV I'm sure it's standalone. Also, I just downloaded and successfully launched it on Win 8.1 32-bit. Can we compare MD5? Mine is d788516439ed743b3553eb3ae7b9082c, and file size is 332 288 bytes. Jun 27, 2014 at 9:11
  • The file that I downloaded from your link above shows me MD5: D788516439ED743B3553EB3AE7B9082C and file size 332 288. So it should be the exact same file. It is also weird that after the error message in Windows 7, the virus scanner Panda Cloud popped up, moving the 'malicious' file to quarantine.
    – Avatar
    Jun 27, 2014 at 9:25
  • @EchtEinfachTV then apparently it's antivirus denied access to file when you tried to launch it, that's why you received Windows message that you can't access it. Though I dunno why it blocks, you can check: it's standard autohotkey binary joined with plaintext (but reformatted) script source. Jun 28, 2014 at 7:38
  • 1
    @Amina ty, I guess that's accidental move of dropbox folders by me. Will fix my post. Sep 19, 2015 at 13:49
4

I have written a small Windows app called QiPress. It has controls to change the look-n-feel, display or ignore certain key-groups, even add static text (your own name or company name for example). Positioning is possible by disabling click-through and click-dragging the pop-up. There are other features which you probably may not require, but it covers mostly what you want.

4
  • 4
    currently 30 USD
    – miroxlav
    Sep 5, 2017 at 19:16
  • To clarify on the versions: Free Version: For personal, non-commercial use. Some advanced features disabled (like various language keyboards, multiple monitors, joystick display etc.). No time limitation. Paid Version: For all uses. All advanced features enabled. No time limitation.
    – fishfin
    Jan 12, 2018 at 7:18
  • Why is it password protected? Virustotal says it is a virus.
    – Xel Naga
    Jan 3, 2021 at 9:22
  • This is because exes are not allowed in my hosting account file system. Also, the common exe was both x86 and x64/amd64 compatible, and I found that because of x86 compatibility, there was some signature in the exe which caused issues with anti-virus. 2 months ago I removed x86 compatibility, and VirusTotal seems to be okay with it, you can try again now. More details on virus false-positives are also on the website.
    – fishfin
    Mar 11, 2021 at 4:49
2

You can use the on screen keyboard to show key presses that comes with windows. When you type on your physical keyboard the on screen one highlights said key.

3
  • 1
    Thanks, I tried that already, but the only modifier key that highlights is the Shift key. Feb 4, 2010 at 15:27
  • In windows 7, type "keyboard" in the start menu search box, and select "On-Screen Keyboard"
    – xhafan
    Jun 20, 2014 at 8:13
  • It doesn't for me (win 10).
    – NounVerber
    Oct 16, 2017 at 18:53
1

Presentation Pointer is a best alternative to MousePosé for Windows. It provides Pointer Effect, Mouse Clicks Effect, Keystrokes and even allows you to draw freely on the screen but not lock the screen. That's really an advantage of the program.

1
  • 2
    ...currently 30 USD.
    – miroxlav
    Sep 5, 2017 at 19:14
1

PointerFocus can display your keystrokes.

2
  • 5
    currently 12.50 USD
    – miroxlav
    Sep 5, 2017 at 19:15
  • Unfortunately, it cannot customize / ignore certain keys.
    – Basj
    Sep 5, 2017 at 19:19
0

You can use PassMark KeyboardTest (Free 30 day evaluation, then US$24.00 to purchase.)

enter image description here

FYI:

Not the answer you're looking for? Browse other questions tagged .