原贴链接:https://www.autohotkey.com/boards/viewtopic.php?f=6&t=26059
在原贴代码改了一些操作和窗口显示,基本上没怎么动。有点小bug不过不影响使用!
;@Ahk2Exe-SetMainIcon tool.ico
;@Ahk2Exe-AddResource tool.ico, 160
;@Ahk2Exe-AddResource Pause.png, 207
;@Ahk2Exe-AddResource Pause.png, 208
;@Ahk2Exe-ExeName %A_ScriptDir%\KeyHistoryTool.exe
;@Ahk2Exe-SetDescription key history tool
;@Ahk2Exe-SetFileVersion 1.0.0.0
;@Ahk2Exe-SetInternalName key history tool
;@Ahk2Exe-SetLanguage 0x0804
;@Ahk2Exe-SetName key history tool
;@Ahk2Exe-SetProductName key history tool
;@Ahk2Exe-SetProductVersion 1.0.0.0
;@Ahk2Exe-SetVersion 1.0.0.0
#NoEnv
#Persistent
#InstallKeybdHook
hHookKeybd := DllCall("SetWindowsHookEx", "int", 13 ; WH_KEYBOARD_LL = 13
, "ptr", RegisterCallback("Keyboard")
; hMod is not required on Win 7, but seems to be required on XP even
; though this type of hook is never injected into other processes:
, "ptr", DllCall("GetModuleHandle", "ptr", 0, "ptr")
, "uint", 0, "ptr") ; dwThreadId
#KeyHistory(15)
OnMessage(0x200, "WM_MOUSEMOVE")
OnMessage(0x201, "WM_LBUTTONDOWN")
OnMessage(0x0203, "WM_LBUTTONDBLCLK")
OnMessage(0x100, "WM_KEYDOWN")
Gui +LastFound
DllCall( "RegisterShellHookWindow", "UInt",A_ScriptHwnd)
OnMessage( DllCall( "RegisterWindowMessage", "Str","SHELLHOOK" ), "ShellIMEMessage")
Menu, Tray, NoStandard
Menu, Tray,Color,ffffff
Menu, Tray, Add, Show, MenuHandler
Menu, Tray, Add
Menu, Tray, Add, Pause, MenuHandler
Menu, Tray, Add
Menu, Tray, Add, reload, MenuHandler
Menu, Tray, Add
Menu, Tray, Add, exit, MenuHandler
Menu, Tray, Default, Show
Gosub GetlockhBitmap
SysGet,SM_CYHSCROLL,3
Global text:=""
; WS_EX_COMPOSITED = E0x02000000 & WS_EX_LAYERED = E0x00080000 -> Double Buffer
Gui, +LastFound +AlwaysOnTop +E0x02000000 +E0x00080000 +HwndhGui
Gui, Margin, 10, 10
Gui,Color,000000,000000
Gui, Font,ffffff, Lucida Console
Gui, Add, Text,xm+5 ym+6 vKHT +0x100 +0x200 -E0x200 +BackgroundTrans cffffff Section, % Format("{:-4}{:-5}{:-7}{:-9}{:-19}{:-1}", "VK", "SC", "Flags", "Elapsed", "Key", "Extra")
Gui, Add, Edit,xm+5 y+20 vKH cffffff ReadOnly +Multi -E0x200 -Tabstop HWNDhedit, % Format("{:-4}{:-5}{:-7}{:-9}{:-19}{:-30}", "00", "000", "ea!u", "1000.00", "Browser_Favorites", "KEY_IGNORE_ALL_EXCEPT_MODIFIER")
GuiControlGet, KHT, Pos
GuiControlGet, KH, Pos
Gui, Add,Pic,% "xm ys-5 w" KHTW+SM_CYHSCROLL " h" KHTH*2,% "HBITMAP:" Gradient(KHTW+SM_CYHSCROLL, KHTH*2,[0xe6e6e6, 0x1e1e1e])
Gui, Add,Text,% "xm+" KHTW+SM_CYHSCROLL+5 " w" (KHW-KHTW-SM_CYHSCROLL)/2 " yp+5 BackgroundTrans cffffff Center",Clear All
Gui, Add,Pic,% "xp yp-5 w" (KHW-KHTW-SM_CYHSCROLL-10)/2 " h" KHTH*2 " gclearall",% "HBITMAP:" Gradient((KHW-KHTW-SM_CYHSCROLL-10)/2, KHTH*2,[0xe6e6e6, 0x1e1e1e])
Gui, Add,Text,% "x+3 yp+5 w" (KHW-KHTW-SM_CYHSCROLL-10)/2 " BackgroundTrans cffffff Center",Copy All
Gui, Add,Pic,% "xp yp-5 w" (KHW-KHTW-SM_CYHSCROLL-10)/2 " h" KHTH*2 " gcopyall",% "HBITMAP:" Gradient((KHW-KHTW-SM_CYHSCROLL-10)/2, KHTH*2,[0xe6e6e6, 0x1e1e1e])
GuiControl,, KH ; clear dummy sizing text
GuiControlGet,KHTEXT,, KHT,text
gosub Resize
EmptyMem()
Return
#MaxThreadsBuffer, On
!WheelUp::
!WheelDown::
#MaxThreadsBuffer, Off
history_size := #KeyHistory() + ((A_ThisHotkey="!WheelUp") ? +1 : -1)
#KeyHistory(history_size>0 ? history_size : 1)
; Delay resize to improve hotkey responsiveness.
SetTimer, Resize, -10
return
Copyall:
GuiControlGet,KHVAULE,, KH,text
Clipboard:=KHVAULE
TrayTip,,copy successful!
Return
clearall:
buf_size := #KeyHistory()
#KeyHistory(0)
GuiControl,, KH,
Text:=""
#KeyHistory(buf_size)
Return
Resize:
; Resize label to fit key history.
gui_h := KHH*#KeyHistory()
GuiControl, Move, KH,% "h" gui_h " w" KHW
gui_h += KHY + 15
Gui, +LastFound
; Determine visibility.
WinGet, style, Style
gui_visible := style & 0x10000000
;Gui, Show, % "AutoSize NA " (gui_visible ? "" : "Hide")
;** Not used because we need to know the previous height,
; and its simpler to resize manually.
; Determine current position and height.
WinGetPos, gui_x, gui_y, gui_w_old, gui_h_old
; Use old height to determine if we should reposition, *only when shrinking*.
; This way we can move the GUI somewhere else, and the script won't reposition it.
;if (gui_h_old < gui_h)
; gui_h_old := gui_h
; Determine working area (primary screen size minus taskbar.)
SysGet, wa_, MonitorWorkArea
SysGet, twc_h, 51 ; SM_CYSMCAPTION
SysGet, bdr_h, 8 ; SM_CYFIXEDFRAME
if (!gui_visible)
{
gui_x = 72 ; Initially on the left side.
gui_y := wa_bottom-(gui_h+twc_h+bdr_h*2+10)
}
else
{ ; Move relative to bottom edge when closer to the bottom.
if (gui_y+gui_h//2 > (wa_bottom-wa_top)//2)
gui_y += gui_h_old-(gui_h+twc_h+bdr_h*2)
}
GuiControl,, KHT,%KHTEXT%
Gui, Show, % "x" (A_ScreenWidth-KHTW-30)/2 " y" (A_ScreenHeight-gui_h)/2 " h" gui_h+KHH-10 " w" KHW+SM_CYHSCROLL+5 " NA",% (A_IsAdmin?"[Admin]":"") "Key History"
;OnMessage(0x20, Func("WM_SETCURSOR").Bind(hGui))
return
GuiSize:
if (A_EventInfo = 1){
Gui, Hide
EmptyMem()
}
return
MenuHandler:
switch A_ThisMenuItem
{
case "Pause":
if (A_IsPaused)
{
WinSetTitle, ahk_id %hGui%, ,% (A_IsAdmin?"[Admin]":"") "Key History"
try {
Menu, Tray, UnCheck, Pause
Menu Tray, Icon, % A_IsCompiled?A_ScriptFullPath:A_AhkPath,,1
}
}
else
{
WinSetTitle, ahk_id %hGui%, ,% (A_IsAdmin?"[Admin]":"") "Key History - Freezed"
try {
Gosub GetlockhBitmap
Menu, Tray, Check, Pause
Menu Tray, Icon, HBITMAP:*%lockhBitmap%,,1
}
}
Pause Toggle
case "Show":
Gui, Show, ,% (A_IsAdmin?"[Admin]":"") "Key History - Freezed"
if (!A_IsPaused)
{
WinSetTitle, ahk_id %hGui%, ,% (A_IsAdmin?"[Admin]":"") "Key History - Freezed"
try {
Gosub GetlockhBitmap
Menu Tray, Icon, HBITMAP:*%lockhBitmap%,,1
Menu, Tray, Check, Pause
}
Pause On
}Else{
WinSetTitle, ahk_id %hGui%, ,% (A_IsAdmin?"[Admin]":"") "Key History"
try {
Gosub GetlockhBitmap
Menu, Tray, UnCheck, Pause
Menu Tray, Icon, % A_IsCompiled?A_ScriptFullPath:A_AhkPath,,1
Pause Toggle
}
}
case "reload":
Reload
case "exit":
ExitApp
}
return
Keyboard(nCode, wParam, lParam) {
global KeyBuffer
static sz := 16+A_PtrSize
Critical
if KeyHistory(1, vk, sc, flags)
&& NumGet(lParam+0, "uint") = vk
&& NumGet(lParam+4, "uint") = sc
&& NumGet(lParam+8, "uint") = flags
buf_max := 0 ; Don't Show key-repeat.
else
buf_max := #KeyHistory()
if (buf_max > 0)
{
; Push older key events to the back.
if (buf_max > 1)
DllCall("RtlMoveMemory", "ptr", &KeyBuffer+sz, "ptr", &KeyBuffer, "ptr", buf_max*sz)
; Copy current key event to the buffer.
DllCall("RtlMoveMemory", "ptr", &KeyBuffer, "ptr", lParam, "ptr", sz)
; "gosub Show" slows down the keyboard hook and causes problems, so use a timer.
SetTimer, Show, -20
}
return DllCall("CallNextHookEx", "ptr", 0, "int", nCode, "ptr", wParam, "ptr", lParam, "ptr")
}
KeyHistory(N, ByRef vk, ByRef sc, ByRef flags:=0, ByRef time:=0, ByRef elapsed:=0, ByRef info:=0)
{
global KeyBuffer
static sz := 16+A_PtrSize
if N is not integer
return false
buf_max := #KeyHistory()
if (N < 0)
N += buf_max + 1
if (N < 1 or N > buf_max)
return false
vk := NumGet(KeyBuffer, (N-1)*sz, "uint")
sc := NumGet(KeyBuffer, (N-1)*sz+4, "uint")
flags := NumGet(KeyBuffer, (N-1)*sz+8, "uint")
time := NumGet(KeyBuffer, (N-1)*sz+12, "uint")
info := NumGet(KeyBuffer, (N-1)*sz+16)
elapsed := time - ((time2 := NumGet(KeyBuffer, N*sz+12, "uint")) ? time2 : time)
switch info
{
case 0xFFC3D44F: info := "KEY_IGNORE"
case 0xFFC3D44E: info := "KEY_PHYS_IGNORE"
case 0xFFC3D44D: info := "KEY_IGNORE_ALL_EXCEPT_MODIFIER"
}
return (vk or sc)
}
#KeyHistory(NewSize="")
{
global KeyBuffer
static sz := 16+A_PtrSize
; Get current history length.
if (NewSize="")
return (cap:=VarSetCapacity(KeyBuffer)//sz)>0 ? cap-1 : 0
if (NewSize)
{
new_cap := (NewSize+1)*sz
cap := VarSetCapacity(KeyBuffer)
if (cap > new_cap)
cap := new_cap
VarSetCapacity(old_buffer, cap)
; Back up previous history.
DllCall("RtlMoveMemory", "ptr", &old_buffer, "ptr", &KeyBuffer, "ptr", cap)
; Set new history length.
VarSetCapacity(KeyBuffer, 0) ; FORCE SHRINK
VarSetCapacity(KeyBuffer, new_cap, 0)
; Restore previous history.
DllCall("RtlMoveMemory", "ptr", &KeyBuffer, "ptr", &old_buffer, "ptr", cap)
; (Remember N+1 key events to simplify calculation of the Nth key event's elapsed time.)
; Put tick count so the initial key event has a meaningful value for "elapsed".
NumPut(A_TickCount, KeyBuffer, 12, "uint")
}
else
{ ; Clear history entirely.
VarSetCapacity(KeyBuffer, 0)
}
}
GetKeyFlagText(flags)
{
return ((flags & 0x1) ? "e" : "") ; LLKHF_EXTENDED
. ((flags & 0x10) ? "a" : "") ; LLKHF_INJECTED (artificial)
. ((flags & 0x20) ? "!" : "") ; LLKHF_ALTDOWN
. ((flags & 0x80) ? "u" : "") ; LLKHF_UP (key up)
}
; Gets readable key name, usually identical to the name in KeyHistory.
GetKeyNameText(vkCode, scanCode, isExtendedKey)
{
return GetKeyName(format("vk{1:02x}sc{3}{2:02x}", vkCode, scanCode, isExtendedKey))
/* ; For older versions of AutoHotkey:
; My Right Shift key Shows as vk161 sc54 isExtendedKey=true. For some
; reason GetKeyNameText only returns a name for it if isExtendedKey=false.
if vkCode = 161
return "Right Shift"
VarSetCapacity(buffer, 32, 0)
DllCall("GetKeyNameText"
, "UInt", (scanCode & 0xFF) << 16 | (isExtendedKey ? 1<<24 : 0) ;| 1<<25
, "Str", buffer
, "Int", 32)
return buffer
*/
}
Show:
SetFormat, FloatFast, .2
SetFormat, IntegerFast, H
text_ :=""
buf_size := #KeyHistory()
Loop, % buf_size
{
if (KeyHistory(buf_size+1-A_Index, vk, sc, flags, time, elapsed, info))
{
keytext := GetKeyNameText(vk, sc, flags & 0x1)
if (elapsed < 0)
elapsed := "#err#"
else
dt := elapsed/1000.0
; AHK-style SC
sc_a := sc
if (flags & 1)
sc_a |= 0x100, flags &= ~1
sc_a := SubStr("000" SubStr(sc_a, 3), -2)
vk_a := SubStr(vk+0, 3)
if (StrLen(vk_a)<2)
vk_a = 0%vk_a%
StringUpper, vk_a, vk_a
StringUpper, sc_a, sc_a
flags := GetKeyFlagText(flags & ~0x1)
text_:=Format("{:-4}{:-5}{:-7}{:-9}{:-19}{:-30}`n", vk_a, sc_a, flags, dt, keytext, info) (InStr(flags,"u")||(info,"KEY_IGNORE")?"··········································································`n":"")
if InStr(text,text_)
Continue
text .= text_
}
}
GuiControl,, KH, % Text ;Trim(RegExReplace(Text "`n","m)(.+\n)(([^\r\n]+\n){25}\n*$)","$2"),"`n")
SendMessage, 0xB1, -2, -1,, ahk_id %hedit%
SendMessage, 0xB7,,,, ahk_id %hedit%
Return
GuiClose:
ExitApp
Return
GetlockhBitmap:
base64Code=
(join`r`n LTrim
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
SUVORK5CYII=
)
lockhBitmap:=hBitmapFromBase64(base64Code)
Return
WM_KEYDOWN()
{
if A_Gui
return true
}
WM_MOUSEMOVE(wParam, lParam, uMsg, hWnd)
{
if (A_GuiControl="KHT")
ToolTip In Flags`ne%A_Tab%=%A_Tab%Extended`na%A_Tab%=%A_Tab%Artificial`n!%A_Tab%=%A_Tab%Alt-Down`nu%A_Tab%=%A_Tab%Key-Up`nAlt+WheelDown/WheelUp to adjust the window size
else
ToolTip
}
WM_LBUTTONDOWN(wParam, lParam, uMsg, hWnd){
Global hGui,lockhBitmap
DllCall("user32.dll\PostMessage", "ptr", hWnd, "uint", 0x00A1, "ptr", 2, "ptr", 0)
}
ShellIMEMessage( wParam,lParam ) {
Global hGui,lockhBitmap
WinGet, MinMax, MinMax , ahk_id %hGui%
if (MinMax<>0){
EmptyMem()
if !A_IsPaused
{
WinSetTitle, ahk_id %hGui%, ,% (A_IsAdmin?"[Admin]":"") "Key History - Freezed"
try {
Gosub GetlockhBitmap
Menu, Tray, Check, Pause
Menu Tray, Icon, HBITMAP:*%lockhBitmap%,,1
}
Pause Toggle
}
}
}
WM_SETCURSOR(hPic, wp) {
static hCursor, flags := (LR_DEFAULTSIZE := 0x40) | (LR_SHARED := 0x8000)
, params := [ "Ptr", 0, "UInt", OCR_HAND := 32649
, "UInt", IMAGE_CURSOR := 2
, "Int", 0, "Int", 0, "UInt", flags, "Ptr" ]
(!hCursor && hCursor := DllCall("LoadImage", params*))
if (wp = hPic)
Return DllCall("SetCursor", "Ptr", hCursor)
}
hBitmapFromBase64(ByRef base64) {
hBitmap := 0
VarSetCapacity(B64, StrLen(base64) << !!A_IsUnicode)
B64 := base64
If !DllCall("Crypt32.dll\CryptStringToBinary", "Ptr", &B64, "UInt", 0, "UInt", 0x01, "Ptr", 0, "UIntP", DecLen, "Ptr", 0, "Ptr", 0)
Return False
VarSetCapacity(Dec, DecLen, 0)
If !DllCall("Crypt32.dll\CryptStringToBinary", "Ptr", &B64, "UInt", 0, "UInt", 0x01, "Ptr", &Dec, "UIntP", DecLen, "Ptr", 0, "Ptr", 0)
Return False
; Bitmap creation adopted from "How to convert Image data (JPEG/PNG/GIF) to hBITMAP?" by SKAN
; -> http://www.autohotkey.com/board/topic/21213-how-to-convert-image-data-jpegpnggif-to-hbitmap/?p=139257
hData := DllCall("Kernel32.dll\GlobalAlloc", "UInt", 2, "UPtr", DecLen, "UPtr")
pData := DllCall("Kernel32.dll\GlobalLock", "Ptr", hData, "UPtr")
DllCall("Kernel32.dll\RtlMoveMemory", "Ptr", pData, "Ptr", &Dec, "UPtr", DecLen)
DllCall("Kernel32.dll\GlobalUnlock", "Ptr", hData)
DllCall("Ole32.dll\CreateStreamOnHGlobal", "Ptr", hData, "Int", True, "PtrP", pStream)
hGdip := DllCall("Kernel32.dll\LoadLibrary", "Str", "Gdiplus.dll", "UPtr")
VarSetCapacity(SI, 16, 0), NumPut(1, SI, 0, "UChar")
DllCall("Gdiplus.dll\GdiplusStartup", "PtrP", pToken, "Ptr", &SI, "Ptr", 0)
DllCall("Gdiplus.dll\GdipCreateBitmapFromStream", "Ptr", pStream, "PtrP", pBitmap)
DllCall("Gdiplus.dll\GdipCreateHBITMAPFromBitmap", "Ptr", pBitmap, "PtrP", hBitmap, "UInt", 0)
DllCall("Gdiplus.dll\GdipDisposeImage", "Ptr", pBitmap)
DllCall("Gdiplus.dll\GdiplusShutdown", "Ptr", pToken)
DllCall("Kernel32.dll\FreeLibrary", "Ptr", hGdip)
DllCall(NumGet(NumGet(pStream + 0, 0, "UPtr") + (A_PtrSize * 2), 0, "UPtr"), "Ptr", pStream)
Return hBitmap
}
EmptyMem(PID=""){
pid:=!PID ? DllCall("GetCurrentProcessId") : pid
h:=DllCall("OpenProcess", "UInt", 0x001F0FFF, "Int", 0, "Int", pid)
DllCall("SetProcessWorkingSetSize", "UInt", h, "Int", -1, "Int", -1)
DllCall("CloseHandle", "Int", h)
}
; https://www.autohotkey.com/boards/viewtopic.php?f=6&t=91899
CreateGradient(W, H, V, aColors) {
Local
C := aColors.Length()
xOFF := (X := V ? W : 0) ? 0 : Ceil(W / (C - 1))
yOFF := (Y := V ? 0 : H) ? 0 : Ceil(H / (C - 1))
VarSetCapacity(VERT, C * 16, 0)
VarSetCapacity(MESH, C * 8, 0)
Loop % (C, pVert := &VERT, pMesh := &MESH) {
X := V ? (X == 0 ? W : X := 0) : X
Y := !V ? (Y == 0 ? H : Y := 0) : Y
Color := Format("{:06X}", aColors[A_Index] & 0xFFFFFF)
Color := Format("0x{5:}{6:}00{3:}{4:}00{1:}{2:}00", StrSplit(Color)*)
pVert := NumPut(Color, NumPut(Y, NumPut(X, pVert+0, "Int"), "Int"), "Int64")
pMesh := NumPut(A_Index, NumPut(A_Index - 1, pMesh+0, "Int"), "Int")
V ? (Y += yOFF) : (X += xOFF)
}
hBM := DllCall("Gdi32.dll\CreateBitmap", "Int", 1, "Int", 1, "Int", 0x1, "Int", 32, "Ptr*", 0, "Ptr")
hBM := DllCall("User32.dll\CopyImage", "Ptr", hBM, "Int", 0x0, "Int", W, "Int", H, "Int", 0x8, "Ptr")
mDC := DllCall("Gdi32.dll\CreateCompatibleDC", "Ptr", 0, "Ptr")
DllCall("Gdi32.dll\SaveDC", "Ptr", mDC)
DllCall("Gdi32.dll\SelectObject", "Ptr", mDC, "Ptr", hBM)
DllCall("Msimg32.dll\GradientFill", "Ptr", mDC, "Ptr", &VERT, "Int", C, "Ptr", &MESH, "Int", C - 1, "Int", !!V)
DllCall("Gdi32.dll\RestoreDC", "Ptr", mDC, "Int", -1)
DllCall("Gdi32.dll\DeleteDC", "Ptr", mDC)
Return hBM
}
DPIScale(x) {
Return (x * A_ScreenDPI) // 96
}
Gradient(Width, Height,Color) {
Return CreateGradient(DPIScale(Width), DPIScale(Height), 1,objlength(color)?Color: [0x3FBBE3, 0x008EBC])
}
就这几个单词还不直接汉化一下
菜单和提示我故意用英文的,中文搞不好就乱码,这几个字面意思应该难不到朝圣者