75

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.

music2myear
  • 49,799

9 Answers9

39

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

Russ
  • 394
  • 4
  • 7
35

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

rburte
  • 1,331
11

I would like to share my tool -- keycastow.

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

enter image description here

Journeyman Geek
  • 133,878
8

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 }

LogicDaemon
  • 2,063
3

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.

fishfin
  • 139
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.

Unfundednut
  • 7,190
1

PointerFocus can display your keystrokes.

Indrek
  • 24,874
Dan
  • 11
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.

Garvey
  • 11
1

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

enter image description here

FYI:

Franck Dernoncourt
  • 24,246
  • 64
  • 231
  • 400