#Persistent
; KeypressOSD.ahk
; https://www.autohotkey.com/boards/viewtopic.php?t=225
#SingleInstance force
#NoEnv
SetBatchLines, -1
ListLines, Off
ahklog.is_out_file := true ;输出到文件
ahklog.is_out_console := true ;输出到console
; Settings
global ShowSingleKey := True
global ShowMouseButton := True
global ShowSingleModifierKey := True
global ShowModifierKeyCount := true
global ShowStickyModKeyCount := false
global DisplayTime := 2000 ; In milliseconds
CreateHotkey()
return
OnKeyPressed:
try {
key := GetKeyStr()
ahklog.info(key)
}
return
OnKeyUp:
return
_OnKeyUp:
tickcount_start := A_TickCount
return
; ===================================================================================
CreateHotkey() {
Loop, 95
{
k := Chr(A_Index + 31)
k := (k = " ") ? "Space" : k
Hotkey, % "~*" k, OnKeyPressed
Hotkey, % "~*" k " Up", _OnKeyUp
}
Loop, 24 ; F1-F24
{
Hotkey, % "~*F" A_Index, OnKeyPressed
Hotkey, % "~*F" A_Index " Up", _OnKeyUp
}
Loop, 10 ; Numpad0 - Numpad9
{
Hotkey, % "~*Numpad" A_Index - 1, OnKeyPressed
Hotkey, % "~*Numpad" A_Index - 1 " 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|NumpadDot|NumpadDiv|NumpadMult|NumpadAdd|NumpadSub|NumpadEnter|Tab|Enter|Esc|BackSpace"
. "|Del|Insert|Home|End|PgUp|PgDn|Up|Down|Left|Right|ScrollLock|CapsLock|NumLock|Pause|sc145|sc146|sc046|sc123"
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 ["Ctrl", "Shift", "Alt"] {
Hotkey, % "~*" mod, OnKeyPressed
Hotkey, % "~*" mod " Up", OnKeyUp
}
for i, mod in ["LWin", "RWin"]
Hotkey, % "~*" mod, OnKeyPressed
}
GetKeyStr() {
static modifiers := ["Ctrl", "Shift", "Alt", "LWin", "RWin"]
static repeatCount := 1
for i, mod in modifiers {
if GetKeyState(mod)
prefix .= mod " + "
}
if (!prefix && !ShowSingleKey)
throw
key := SubStr(A_ThisHotkey, 3)
if (key ~= "i)^(Ctrl|Shift|Alt|LWin|RWin)$") {
if !ShowSingleModifierKey {
throw
}
key := ""
prefix := RTrim(prefix, "+ ")
if ShowModifierKeyCount {
if !InStr(prefix, "+") && IsDoubleClickEx() {
if (A_ThisHotKey != A_PriorHotKey) || ShowStickyModKeyCount {
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 = "LButton") && IsDoubleClick() {
key := "Double-Click"
}
_key := (key = "Double-Click") ? "LButton" : key
static pre_prefix, pre_key, keyCount := 1
global tickcount_start
if (prefix && pre_prefix) && (A_TickCount-tickcount_start < 300) {
if (prefix != pre_prefix) {
result := pre_prefix pre_key ", " prefix key
} else {
keyCount := (key=pre_key) ? (keyCount+1) : 1
key := (keyCount>2) ? (key " (" keyCount ")") : (pre_key ", " key)
}
} else {
keyCount := 1
}
pre_prefix := prefix
pre_key := _key
repeatCount := 1
}
return result ? result : prefix . key
}
SpecialSC(sc) {
static k := {sc046: "ScrollLock", sc145: "NumLock", sc146: "Pause", sc123: "Genius LuxeMate Scroll"}
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)
}
;-------------------log相关函数---------------------------------
class ahklog
{
static line := true
static file := true
static func := true
static log_mode := "info"
static log_strim := ""
static is_log_open := true
static is_out_console := true
static is_out_file := false
static console_create_flag := false
__New()
{
DllCall("AllocConsole")
}
__Delete()
{
DllCall("FreeConsole")
}
to_str(str)
{
local
rtn := ""
if(IsObject(str))
{
rtn := obj2json4log(str)
;删除换行空格
rtn := StrReplace(rtn, "`r`n")
rtn := StrReplace(rtn, " ")
}
else
{
rtn := str
}
return rtn
}
log(ByRef str)
{
if(this.is_out_console)
{
DllCall("AllocConsole")
FileAppend,% "[" A_Now "." A_MSec "]" str "`r`n", *
}
if(this.is_out_file)
{
FileAppend,% "[" A_Now "." A_MSec "]" str "`r`n", key_history
}
}
log_out(para*)
{
local
global G_MY_DLL_USE_MAP, G_MY_DLL_BUFFER_SIZE
if(this.is_log_open == False || (this.is_out_console == false && this.is_out_file == false))
{
return
}
if(this.is_out_console == true && this.console_create_flag == false)
{
dllcall("AllocConsole")
this.console_create_flag := true
}
if(A_IsCompiled)
{
this.line := false
}
err_obj := Exception("", -2)
err_obj_up := Exception("", -3)
SplitPath,% err_obj.file, file_info
line_info := err_obj.line
func_info := err_obj_up.what
if(RegExMatch(func_info, "^-3"))
{
func_info := "Auto-execute"
}
file_info := this.file ? "[FILE:" file_info "]" : ""
line_info := this.line ? "[LINE:" line_info "]" : ""
func_info := this.func ? "[FUNC:" func_info "]" : ""
mode_info := "[" this.log_mode "]"
log_str := ""
for k,v in para
{
log_str .= this.to_str(v)
}
log_str := mode_info file_info line_info func_info this.log_strim ":" log_str
this.log(log_str)
}
info(para*)
{
this.log_strim := ""
this.log_mode := "info"
this.log_out(para*)
}
warn(para*)
{
this.log_strim := ""
this.log_mode := "warn"
this.log_out(para*)
}
err(para*)
{
this.log_strim := ""
this.log_mode := "err"
this.log_out(para*)
}
critical(para *)
{
this.log_strim := ""
this.log_mode := "critical"
this.log_out(para*)
}
get_trim_position()
{
this.log_mode := "info"
stack_position := 0
index_position := 0
while(1)
{
stack_position++
func_stack := Exception("", index_position--)
if(RegExMatch(func_stack.what, "^-"))
{
break
}
if(stack_position > 20)
{
break
}
}
return stack_position
}
in(para *)
{
stack_position := this.get_trim_position()
strim := ""
loop,% stack_position - 3
{
strim .= ">"
}
this.log_strim := strim
this.log_out(para*)
}
out(para *)
{
stack_position := this.get_trim_position()
strim := ""
loop,% stack_position - 3
{
strim .= "<"
}
this.log_strim := strim
this.log_out(para*)
}
}
/*
;------------------------------------
; json转码纯AHK实现 v2.0 By FeiYue
;------------------------------------
*/
obj2json4log(obj, space:="") ; AHK对象转Json字符串
{
local
; 默认不替换 "/-->\/" 与 "Unicode字符-->\uXXXX"
static rep:=[ ["\\","\"], ["\""",""""] ; , ["\/","/"]
, ["\r","`r"], ["\n","`n"], ["\t","`t"]
, ["\b","`b"], ["\f","`f"] ]
if !IsObject(obj)
{
if obj is Number
return obj
if (obj=="true" or obj=="false" or obj=="null")
return obj
For k,v in rep
obj:=StrReplace(obj, v.2, v.1)
; While RegExMatch(obj, "[^\x20-\x7e]", k)
; obj:=StrReplace(obj, k, Format("\u{:04x}",Ord(k)))
return """" obj """"
}
is_arr:=1 ; 是简单数组
For k,v in obj
if (k!=A_Index) and !(is_arr:=0)
Break
s:="", space2:=space . " "
For k,v in obj
s.= "`r`n" space2 . (is_arr ? ""
: """" Trim(%A_ThisFunc%(Trim(k)),"""") """: ")
. %A_ThisFunc%(v,space2) . ","
return (is_arr?"[":"{") . Trim(s,",")
. "`r`n" space . (is_arr?"]":"}")
}
唉 ahk太强大了,强大到感觉可以替代许多工具类软件