介绍
此脚本源自ahk社区的ahk_vl版本,时过境迁,版本更迭,我将此脚本升级到v2版本,对部分内容做简化,并增加了更多功能。
效果
- 绿色为按下键
使用
- 双击托盘图标显示或关闭悬浮键盘
- shift+LButton 移动
- shift+WhellUp\WhellDown 改变透明度
仓库
脚本较长,可使用地址,也可直接复制代码。
脚本代码如下 :
#Requires AutoHotkey v2.0
#SingleInstance Force
CoordMode "Mouse", "Screen"
; class-desc: Do all the configuration here
class Config {
; Whether keys can be sent through the mouse
; If true, gui transparency cannot be set
; But it doesn't do much right now,
; because it loses focus so that can't be sent to the right window
static EnableInput := false
; Determines the gui window size by calculating the font size
static fontSize := 14
static fontName := 'Verdana'
; Default 200
static guiCapacity := Config.EnableInput ? '' : 200
; Gui background color
; Don't use a deep color because the button can't set background color
static guiBackColor := 'cfff2e6'
; The color when the button is pressed
static guiProgressColor := 'cA1BE7B'
; Same as guiBackColor
static guiProgressBackColor := SubStr(Config.guiBackColor, 2)
static guiOption := '+AlwaysOnTop -MaximizeBox +ToolWindow -Caption +E0x20'
; The text on tray
static trayItemOn := 'Show keyboard'
static trayItemOff := 'Hide keyboard'
}
; tray setting
tray := A_TrayMenu
; set dobule-click
tray.ClickCount := 2
; delete standard item
tray.delete
tray.add Config.trayItemOff, K_Toggle
; division
tray.add
; add exit item
tray.add "Exit", (*) => ExitApp()
tray.default := Config.trayItemOff
; param:
; ret: -->
; desc: Toggle tray item name
K_Toggle(*) {
static flag := true
if flag {
tray.rename(Config.trayItemOff, Config.trayItemOn)
VK.Cancel()
} else {
tray.rename(Config.trayItemOn, Config.trayItemOff)
VK.Show()
}
flag := !flag
}
; Calculate object dimensions based on chosen font size:
k_KeyWidth := Config.fontSize * 3
k_KeyHeight := Config.fontSize * 3
; Spacing to be used between the keys.
k_KeyMargin := Config.fontSize // 6
; The total width of the keyboard in terms of the keys and their margins.
width := 15 * k_KeyWidth + 14 * k_KeyMargin
; Values for specially sized keys. The first and last keys of each row are critical for proper sizing.
k_KeyWidthHalf := k_KeyWidth / 2
k_TabW := Config.fontSize * 4
k_CapsW := k_KeyWidth + k_KeyMargin + k_KeyWidthHalf
k_ShiftW := 2 * k_KeyWidth + k_KeyMargin
k_SpacebarWidth := Config.fontSize * 17
k_LastKeyWidth := width - (k_TabW + 12 * k_KeyWidth + 13 * k_KeyMargin)
k_EnterWidth := width - (k_CapsW + 11 * k_KeyWidth + 12 * k_KeyMargin)
k_LastShiftWidth := width - (k_ShiftW + 10 * k_KeyWidth + 11 * k_KeyMargin)
k_LastCtrlWidth := width - (6 * k_TabW + k_SpacebarWidth + 7 * k_KeyMargin)
; Only a facilitator for creating GUI.
k_KeySize := ' w' k_KeyWidth ' h' k_KeyHeight
k_Position := ' x+' k_KeyMargin k_KeySize
; This table is used to relate the hotkeys pressed with their progress bars to flash them when pressed.
; **All uppercase**
k_Characters := Map(
"``", 1
, '1', 2
, '2', 3
, '3', 4
, '4', 5
, '5', 6
, '6', 7
, '7', 8
, '8', 9
, '9', 10
, '0', 11
, "-", 12
, "=", 13
, "BACKSPACE", 14
, "TAB", 15
, "Q", 16
, "W", 17
, "E", 18
, "R", 19
, "T", 20
, "Y", 21
, "U", 22
, "I", 23
, "O", 24
, "P", 25
, "[", 26
, "]", 27
, "\", 28
, "CAPSLOCK", 29
, "A", 30
, "S", 31
, "D", 32
, "F", 33
, "G", 34
, "H", 35
, "J", 36
, "K", 37
, "L", 38
, ";", 39
, "'", 40
, "ENTER", 41
, "LSHIFT", 42
, "Z", 43
, "X", 44
, "C", 45
, "V", 46
, "B", 47
, "N", 48
, "M", 49
, ",", 50
, ".", 51
, "/", 52
, "RSHIFT", 53
, "LCTRL", 54
, "LWIN", 55
, "LALT", 56
, "SPACE", 57
, "RALT", 58
, "RWN", 59
, "APPSKEY", 60
, "RCTRL", 61
, "INSERT", 62
, "HOME", 63
, "PGUP", 64
, "DELETE", 65
, "END", 66
, "PGDN", 67
, "UP", 68
, "LEFT", 69
, "DOWN", 70
, "RIGHT", 71)
; Zero-width non-breaking space
zwnbs := Chr(8204)
labels := Map(
"AppsKey", "App"
, "BackSpace", Chr(0x1F844)
, "CapsLock", "Caps"
, "Delete", "Del"
, "End", Chr(0x21F2)
, "Home", Chr(0x21F1)
, "Insert", "Ins"
, "LAlt", "Alt"
, "LCtrl", "Ctrl"
, "LShift", "Shift"
, "LWin", "Win"
, "PgDn", "PD"
, "PgUp", "PU"
, "RAlt", "Alt" zwnbs
, "RCtrl", "Ctrl" zwnbs
, "RShift", "Shift" zwnbs
, "RWin", "Win" zwnbs
, "Tab", "Tab" ;Chr(0x2B7E)
, "Left", "◀"
, "Right", "▶"
, "Down", "▼"
, "Up", "▲")
class VK extends Gui {
; store current gui instance hwnd
static insHwnd := unset
__New() {
super.__New(Config.guiOption)
this.SetFont('s' Config.fontSize, Config.fontName)
this.BackColor := Config.guiBackColor
; 1
this.AddProgress('Section xm ym Disabled vprg1 ' k_Position)
this.AddProgress('Disabled vprg2 ' k_Position)
this.AddProgress('Disabled vprg3 ' k_Position)
this.AddProgress('Disabled vprg4 ' k_Position)
this.AddProgress('Disabled vprg5 ' k_Position)
this.AddProgress('Disabled vprg6 ' k_Position)
this.AddProgress('Disabled vprg7 ' k_Position)
this.AddProgress('Disabled vprg8 ' k_Position)
this.AddProgress('Disabled vprg9 ' k_Position)
this.AddProgress('Disabled vprg10 ' k_Position)
this.AddProgress('Disabled vprg11 ' k_Position)
this.AddProgress('Disabled vprg12 ' k_Position)
this.AddProgress('Disabled vprg13 ' k_Position)
this.AddProgress('Disabled vprg14 x+' k_KeyMargin ' w' k_ShiftW ' h' k_KeyHeight)
this.AddProgress('Disabled ' k_Position)
this.AddProgress('Disabled vprg62 ' k_Position)
this.AddProgress('Disabled vprg63 ' k_Position)
this.AddProgress('Disabled vprg64 ' k_Position)
; 2
this.AddProgress('Disabled vprg15 xs y+' k_KeyMargin ' w' k_TabW ' h' k_KeyHeight)
this.AddProgress('Disabled vprg16 ' k_Position)
this.AddProgress('Disabled vprg17 ' k_Position)
this.AddProgress('Disabled vprg18 ' k_Position)
this.AddProgress('Disabled vprg19 ' k_Position)
this.AddProgress('Disabled vprg20 ' k_Position)
this.AddProgress('Disabled vprg21 ' k_Position)
this.AddProgress('Disabled vprg22 ' k_Position)
this.AddProgress('Disabled vprg23 ' k_Position)
this.AddProgress('Disabled vprg24 ' k_Position)
this.AddProgress('Disabled vprg25 ' k_Position)
this.AddProgress('Disabled vprg26 ' k_Position)
this.AddProgress('Disabled vprg27 ' k_Position)
this.AddProgress('Disabled vprg28 x+' k_KeyMargin ' w' k_LastKeyWidth ' h' k_KeyHeight)
this.AddProgress('Disabled ' k_Position)
this.AddProgress('Disabled vprg65 ' k_Position)
this.AddProgress('Disabled vprg66 ' k_Position)
this.AddProgress('Disabled vprg67 ' k_Position)
; 3
this.AddProgress('Disabled vprg29 xs y+' k_KeyMargin ' w' k_CapsW ' h' k_KeyHeight)
this.AddProgress('Disabled vprg30 ' k_Position)
this.AddProgress('Disabled vprg31 ' k_Position)
this.AddProgress('Disabled vprg32 ' k_Position)
this.AddProgress('Disabled vprg33 ' k_Position)
this.AddProgress('Disabled vprg34 ' k_Position)
this.AddProgress('Disabled vprg35 ' k_Position)
this.AddProgress('Disabled vprg36 ' k_Position)
this.AddProgress('Disabled vprg37 ' k_Position)
this.AddProgress('Disabled vprg38 ' k_Position)
this.AddProgress('Disabled vprg39 ' k_Position)
this.AddProgress('Disabled vprg40 ' k_Position)
this.AddProgress('Disabled vprg41 x+' k_KeyMargin ' w' k_EnterWidth ' h' k_KeyHeight)
this.AddProgress('Disabled ' k_Position)
this.AddProgress('Disabled ' k_Position)
this.AddProgress('Disabled ' k_Position)
this.AddProgress('Disabled ' k_Position)
; 4
this.AddProgress('Disabled vprg42 xs y+' k_KeyMargin ' w' k_ShiftW ' h' k_KeyHeight)
this.AddProgress('Disabled vprg43 ' k_Position)
this.AddProgress('Disabled vprg44 ' k_Position)
this.AddProgress('Disabled vprg45 ' k_Position)
this.AddProgress('Disabled vprg46 ' k_Position)
this.AddProgress('Disabled vprg47 ' k_Position)
this.AddProgress('Disabled vprg48 ' k_Position)
this.AddProgress('Disabled vprg49 ' k_Position)
this.AddProgress('Disabled vprg50 ' k_Position)
this.AddProgress('Disabled vprg51 ' k_Position)
this.AddProgress('Disabled vprg52 ' k_Position)
this.AddProgress('Disabled vprg53 x+' k_KeyMargin ' w' k_LastShiftWidth ' h' k_KeyHeight)
this.AddProgress('Disabled ' k_Position)
this.AddProgress('Disabled ' k_Position)
this.AddProgress('Disabled vprg68 ' k_Position)
this.AddProgress('Disabled ' k_Position)
; 5
this.AddProgress('Disabled vprg54 xs y+' k_KeyMargin ' w' k_TabW ' h' k_KeyHeight)
this.AddProgress('Disabled vprg55 x+' k_KeyMargin ' w' k_TabW ' h' k_KeyHeight)
this.AddProgress('Disabled vprg56 x+' k_KeyMargin ' w' k_TabW ' h' k_KeyHeight)
this.AddProgress('Disabled vprg57 x+' k_KeyMargin ' w' k_SpacebarWidth ' h' k_KeyHeight)
this.AddProgress('Disabled vprg58 x+' k_KeyMargin ' w' k_TabW ' h' k_KeyHeight)
this.AddProgress('Disabled vprg59 x+' k_KeyMargin ' w' k_TabW ' h' k_KeyHeight)
this.AddProgress('Disabled vprg60 x+' k_KeyMargin ' w' k_TabW ' h' k_KeyHeight)
this.AddProgress('Disabled vprg61 x+' k_KeyMargin ' w' k_LastCtrlWidth ' h' k_KeyHeight)
this.AddProgress('Disabled ' k_Position)
this.AddProgress('Disabled vprg69 ' k_Position)
this.AddProgress('Disabled vprg70 ' k_Position)
this.AddProgress('Disabled vprg71 ' k_Position)
; Overlay the progress bar with a button
this.AddButton('Section xs ym ' k_KeySize, '``')
this.AddButton(k_Position, '1')
this.AddButton(k_Position, '2')
this.AddButton(k_Position, '3')
this.AddButton(k_Position, '4')
this.AddButton(k_Position, '5')
this.AddButton(k_Position, '6')
this.AddButton(k_Position, '7')
this.AddButton(k_Position, '8')
this.AddButton(k_Position, '9')
this.AddButton(k_Position, '0')
this.AddButton(k_Position, '-')
this.AddButton(k_Position, '=')
this.AddButton(k_Position ' w' k_ShiftW ' h' k_KeyHeight, labels.Get('BackSpace'))
this.AddProgress('Disabled Background' Config.guiProgressBackColor k_Position)
this.AddButton(k_Position, 'Ins')
this.AddButton(k_Position, labels.Get('Home'))
this.AddButton(k_Position, labels.Get('PgUp'))
; 2
this.AddButton('xs y+' k_KeyMargin ' w' k_TabW ' h' k_KeyHeight, labels.Get('Tab'))
this.AddButton(k_Position, 'Q')
this.AddButton(k_Position, 'W')
this.AddButton(k_Position, 'E')
this.AddButton(k_Position, 'R')
this.AddButton(k_Position, 'T')
this.AddButton(k_Position, 'Y')
this.AddButton(k_Position, 'U')
this.AddButton(k_Position, 'I')
this.AddButton(k_Position, 'O')
this.AddButton(k_Position, 'P')
this.AddButton(k_Position, '[')
this.AddButton(k_Position, ']')
this.AddButton('x+' k_KeyMargin ' w' k_LastKeyWidth ' h' k_KeyHeight, '\')
this.AddProgress('Disabled Background' Config.guiProgressBackColor k_Position)
this.AddButton(k_Position, 'Del')
this.AddButton(k_Position, labels.Get('End'))
this.AddButton(k_Position, labels.Get('PgDn'))
; 3
this.AddButton('xs y+' k_KeyMargin ' w' k_CapsW ' h' k_KeyHeight, labels.Get('CapsLock'))
this.AddButton(k_Position, 'A')
this.AddButton(k_Position, 'S')
this.AddButton(k_Position, 'D')
this.AddButton(k_Position, 'F')
this.AddButton(k_Position, 'G')
this.AddButton(k_Position, 'H')
this.AddButton(k_Position, 'J')
this.AddButton(k_Position, 'K')
this.AddButton(k_Position, 'L')
this.AddButton(k_Position, ';')
this.AddButton(k_Position, '`'')
this.AddButton('x+' k_KeyMargin ' w' k_EnterWidth ' h' k_KeyHeight, 'Enter')
this.AddProgress('Disabled Background' Config.guiProgressBackColor k_Position)
this.AddProgress('Disabled Background' Config.guiProgressBackColor k_Position)
this.AddProgress('Disabled Background' Config.guiProgressBackColor k_Position)
this.AddProgress('Disabled Background' Config.guiProgressBackColor k_Position)
; 4
this.AddButton('xs y+' k_KeyMargin ' w' k_ShiftW ' h' k_KeyHeight, labels.Get('LShift'))
this.AddButton(k_Position, 'Z')
this.AddButton(k_Position, 'X')
this.AddButton(k_Position, 'C')
this.AddButton(k_Position, 'V')
this.AddButton(k_Position, 'B')
this.AddButton(k_Position, 'N')
this.AddButton(k_Position, 'M')
this.AddButton(k_Position, ',')
this.AddButton(k_Position, '.')
this.AddButton(k_Position, '/')
this.AddButton('x+' k_KeyMargin ' w' k_LastShiftWidth ' h' k_KeyHeight, labels.Get('RShift'))
this.AddProgress('Disabled Background' Config.guiProgressBackColor k_Position)
this.AddProgress('Disabled Background' Config.guiProgressBackColor k_Position)
this.AddButton(k_Position, labels.Get('Up'))
this.AddProgress('Disabled Background' Config.guiProgressBackColor k_Position)
; 5
this.AddButton('xs y+' k_KeyMargin ' w' k_TabW ' h' k_KeyHeight, labels.Get('LCtrl'))
this.AddButton('x+' k_KeyMargin ' w' k_TabW ' h' k_KeyHeight, labels.Get('LWin'))
this.AddButton('x+' k_KeyMargin ' w' k_TabW ' h' k_KeyHeight, labels.Get('LAlt'))
this.AddButton('x+' k_KeyMargin ' w' k_SpacebarWidth ' h' k_KeyHeight, 'Space')
this.AddButton('x+' k_KeyMargin ' w' k_TabW ' h' k_KeyHeight, labels.Get('RAlt'))
this.AddButton('x+' k_KeyMargin ' w' k_TabW ' h' k_KeyHeight, labels.Get('RWin'))
this.AddButton('x+' k_KeyMargin ' w' k_TabW ' h' k_KeyHeight, labels.Get('AppsKey'))
this.AddButton('x+' k_KeyMargin ' w' k_LastCtrlWidth ' h' k_KeyHeight, labels.Get('RCtrl'))
this.AddProgress('Disabled Background' Config.guiProgressBackColor k_Position)
this.AddButton(k_Position, labels.Get('Left'))
this.AddButton(k_Position, labels.Get('Down'))
this.AddButton(k_Position, labels.Get('Right'))
}
; param:
; ret: gui instance-->gui object
; desc: display the gui and returns the current instance
static Show() {
; singleton
for w in WinGetList('ahk_pid ' ProcessExist())
if (g := GuiFromHwnd(w)) && g.base = this.Prototype {
g.Show()
return g
}
ins := VK()
VK.insHwnd := ins.Hwnd
ins.Show('y' A_ScreenHeight * (3 / 4))
if Config.guiCapacity
WinSetTransparent(Config.guiCapacity, 'ahk_id' ins.Hwnd)
return ins
}
; param:
; ret: -->
; desc: distory
static Cancel() {
WinClose('ahk_id' VK.insHwnd)
}
}
; display keyboard
vkv := VK.Show()
; class-desc: some methods
class Utils {
; param:
; ret: -->boolean
; desc:
static IsOverGui() {
WinGetPos(&guiX, &guiY, &guiW, &guiH, 'ahk_id' VK.insHwnd)
MouseGetPos(&x, &y)
if x < guiX || x > guiX + guiW
return false
if y < guiY || y > guiY + guiH
return false
return true
}
; param:
; ret: -->
; desc: restore the position and transparent
static RestoreVK() {
WinMove(, A_ScreenHeight * (3 / 4), , , 'ahk_id' VK.insHwnd)
Config.guiCapacity := 255
WinSetTransparent(Config.guiCapacity, 'ahk_id' VK.insHwnd)
}
; static KeyWaitAny() {
; ih := InputHook()
; ih.KeyOpt("{All}", "E")
; ih.Start()
; ih.Wait()
; return ih.EndKey
; }
}
; OneKey() {
; ; This method can only trigger one button at the same time, so I abandoned it
; ; but there are some redeeming features, No need to set hotkeys repeatedly
; while true {
; k := Utils.KeyWaitAny()
; if k ~= 'i)\w*'
; k := StrUpper(k)
; try {
; keySuffix := k_Characters.Get(k)
; guiCtrl := GuiCtrlFromHwnd(vkv['prg' keySuffix].Hwnd)
; guiCtrl.Opt('+Background' Config.guiProgressColor)
; KeyWait(k)
; guiCtrl.Opt('+Background' Config.guiProgressBackColor)
; guiCtrl.Redraw()
; }
; catch as e
; MsgBox e.Message
; }
; }
; set all the keys as hotkey
; from ascii 45 to 96 but skip some keys
Loop 49 {
k_char := Chr(A_Index + 44)
if k_char ~= '[<>^``]'
continue
; binding method
Hotkey '~*' k_char, Flash
}
~*`::
~*Backspace::
~*Tab::
~*CapsLock::
~*'::
~*Enter::
~*LShift::
~*,::
~*RShift::
~*LCtrl::
~*LWin::
~*LAlt::
~*Space::
~*RAlt::
~*RWin::
~*AppsKey::
~*RCtrl::
~*Insert::
~*Home::
~*PgUp::
~*Delete::
~*End::
~*PgDn::
~*Up::
~*Left::
~*Down::
~*Right:: Flash()
; param:
; ret: -->
; desc: change color when holding button, redraw when releasing
Flash(*) {
k_ThisHotKey := StrReplace(A_ThisHotkey, '~*', '')
k_ThisHotKey := StrUpper(k_ThisHotKey)
try {
keySuffix := k_Characters.Get(K_ThisHotkey)
guiCtrl := GuiCtrlFromHwnd(vkv['prg' keySuffix].Hwnd)
guiCtrl.Opt('+Background' Config.guiProgressColor)
KeyWait(K_ThisHotkey)
guiCtrl.Opt('+Background' Config.guiProgressBackColor)
guiCtrl.Redraw()
}
catch as e
MsgBox e.Message
}
; move gui
Lshift & LButton::
{
if !Utils.IsOverGui()
return
if (A_ThisHotkey = A_PriorHotkey && A_TimeSincePriorHotkey < 300) {
Utils.RestoreVK()
return
}
; move gui window
MouseGetPos(&px, &py)
WinGetPos(&wx, &wy, , , 'ahk_id' VK.insHwnd)
dx := wx - px, dy := wy - py
SetWinDelay -1
While GetKeyState("LButton", "P")
{
MouseGetPos(&nx, &ny)
WinMove(nx + dx, ny + dy, , , 'ahk_id' VK.insHwnd)
}
}
#HotIf !Config.EnableInput
; change the transparent via mouse whell
LShift & WheelUp::
{
Config.guiCapacity += 10
If Config.guiCapacity > 255
Config.guiCapacity := 255
WinSetTransparent(Config.guiCapacity, 'ahk_id' VK.insHwnd)
}
LShift & WheelDown::
{
Config.guiCapacity -= 10
If Config.guiCapacity < 0
Config.guiCapacity := 10
WinSetTransparent(Config.guiCapacity, 'ahk_id' VK.insHwnd)
}
#HotIf
#HotIf Config.EnableInput
; Outputs the text of the focus control
; But it's useless here
~LButton::
{
if !Utils.IsOverGui()
return
KeyWait('LButton')
ActiveBtnHwnd := ControlGetFocus('ahk_id' VK.insHwnd)
MsgBox ControlGetText(ActiveBtnHwnd)
}
#HotIf
添加F行
后续,我又添加了一个F行
此脚本位于仓库ahk-scripts/scrtips/visualKeyboard.ahk
仓库:https://gitee.com/dkwd/ahk-scripts.git