; 一款比较好用的鼠标坐标和按键历史记录工具 ; 来源:https://autohotkey.com/boards/viewtopic.php?f=6&t=26059 ; If the most recent event is a mouse-move and the mouse moves again, ; enable this to update it instead of adding another mouse-move event. MERGE_MOVE := true #NoEnv #Persistent #MouseHistory(10) Gui, +LastFound -DPIScale WinSet, Transparent, 200 Gui, +ToolWindow +AlwaysOnTop Gui, Margin, 10, 10 Gui, Font,, Lucida Console Gui, Add, Text, vMH, . . GuiControlGet, MH, Pos GuiControl,, MH ; clear dummy sizing text gosub Resize OnMessage(0x201, "WM_LBUTTONDOWN") return #MaxThreadsBuffer, On !WheelUp:: !WheelDown:: #MaxThreadsBuffer, Off history_size := #MouseHistory() + ((A_ThisHotkey="!WheelUp") ? +1 : -1) #MouseHistory(history_size>0 ? history_size : 1) ; Delay resize to improve hotkey responsiveness. SetTimer, Resize, -10 return Resize: ; Resize label to fit mouse history. gui_h := MHH*(#MouseHistory()) GuiControl, Move, MH, h%gui_h% gui_h += 20 Gui, +LastFound ; Determine visibility. WinGet, style, Style gui_visible := style & 0x10000000 ; Determine current position and height. WinGetPos, gui_x, gui_y, , 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 = 10 ; 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) } Gui, Show, x%gui_x% y%gui_y% h%gui_h% NA, Mouse History return Show: SetFormat, FloatFast, .2 text = buf_size := #MouseHistory() Loop, % buf_size { SetFormat, IntegerFast, D if MouseHistory(A_Index, msg, x, y, mouseData, flags, time, elapsed) { SetFormat, IntegerFast, H msg := (msg + 0) "" SetFormat, IntegerFast, D ; WM_LBUTTONDOWN/UP/DBLCLK, WM_NC.. if msg in 0x201,0x202,0x203,0xA1,0xA2,0xA3 btn = Left ; WM_RBUTTONDOWN/UP/DBLCLK, WM_NC.. else if msg in 0x204,0x205,0x206,0xA4,0xA5,0xA6 btn = Right ; WM_MBUTTONDOWN/UP/DBLCLK, WM_NC.. else if msg in 0x207,0x208,0x209,0xA7,0xA8,0xA9 btn = Middle ; WM_XBUTTONDOWN/UP/DBLCLK, WM_NC.. else if msg in 0x20B,0x20C,0x20D,0xAB,0xAC,0xAD btn := (mouseData & 0x10000) ? "X1" : "X2" ; WM_MOUSEWHEEL else if msg = 0x20A { mouseData := mouseData << 32 >> 48 btn := (mouseData < 0) ? "WD" : "WU" } ; WM_MOUSEHWHEEL else if msg = 0x20E { mouseData := mouseData << 32 >> 48 btn := (mouseData < 0) ? "WL" : "WR" } ; WM_MOUSEMOVE else if msg = 0x200 btn = ; ??? else btn := msg clickCount = ; WM_LBUTTONDBLCLK, WM_NC.., ..R/M/XBUTTONDBLCLK.. if msg in 0x203,0xA3,0x206,0xA6,0x209,0xA9,0x20D,0xAD { clickCount := 2 } ; WM_MOUSEWHEEL, WM_MOUSEHWHEEL else if msg in 0x20A,0x20E { clickCount := Abs(mouseData) if !clickCount clickCount = } ; WM_L/R/M/XBUTTONDOWN, WM_NC.. else if msg in 0x201,0x204,0x207,0x20B,0xA1,0xA4,0xA7,0xAB { clickCount = Down } ; WM_L/R/M/XBUTTONUP, WM_NC.. else if msg in 0x202,0x205,0x208,0x20C,0xA2,0xA5,0xA8,0xAC { clickCount = Up } text .= ((flags & 1) ? "* " : " ") ;. SubStr(msg " ", 1, 6) . SubStr(btn " ", 1, 8) . SubStr(" " x, -4) " " SubStr(" " y, -4) . SubStr(" " clickCount, -5) . SubStr(" " elapsed/1000.0, -6) "`n" } else break } GuiControl,, MH, % text Return GuiClose: ExitApp MouseHistory(N, ByRef msg, ByRef x, ByRef y, ByRef mouseData, ByRef flags, ByRef time, ByRef elapsed=-1) { global MouseBuffer if N is not integer return false buf_max := #MouseHistory() if (N < 1 or N > buf_max) return false x := NumGet(MouseBuffer, ofs:=(N-1)*24, "int") y := NumGet(MouseBuffer, ofs+4, "int") mouseData := NumGet(MouseBuffer, ofs+8, "uint") flags := NumGet(MouseBuffer, ofs+12, "uint") time := NumGet(MouseBuffer, ofs+16, "uint") msg := NumGet(MouseBuffer, ofs+20, "uint") elapsed := time - ((time2 := NumGet(MouseBuffer, N*24+16, "uint")) ? time2 : time) return !!msg } #MouseHistory(NewSize="") { global MouseBuffer static MouseHook, MouseHookProc if NewSize = ; Get current history length. return (cap:=VarSetCapacity(MouseBuffer)//24)>0 ? cap-1 : 0 if NewSize { if !MouseHook { ; Register the mouse hook. MouseHookProc := RegisterCallback("Mouse") MouseHook := DllCall("SetWindowsHookEx", "int", 14, "ptr", MouseHookProc, "uint", 0, "uint", 0, "ptr") } new_cap := (NewSize+1)*24 ; sizeof(MSLLHOOKSTRUCT)=24 cap := VarSetCapacity(MouseBuffer) if (cap > new_cap) cap := new_cap VarSetCapacity(old_buffer, cap) ; Back up previous history. DllCall("RtlMoveMemory", "ptr", &old_buffer, "ptr", &MouseBuffer, "ptr", cap) ; Set new history length. VarSetCapacity(MouseBuffer, 0) ; FORCE SHRINK VarSetCapacity(MouseBuffer, new_cap, 0) ; Restore previous history. DllCall("RtlMoveMemory", "ptr", &MouseBuffer, "ptr", &old_buffer, "ptr", cap) ; (Remember N+1 mouse events to simplify calculation of the Nth mouse event's elapsed time.) ; Put tick count so the initial mouse event has a meaningful value for "elapsed". NumPut(A_TickCount, MouseBuffer, 16, "uint") } else { if MouseHook { ; Unregister the mouse hook. DllCall("UnhookWindowsHookEx", "ptr", MouseHook) DllCall("GlobalFree", "ptr", MouseHookProc) MouseHook = } ; Clear history entirely. VarSetCapacity(MouseBuffer, 0) } } ; Mouse hook callback - records mouse events into MouseBuffer. Mouse(nCode, wParam, lParam) { global MouseBuffer, MERGE_MOVE Critical if (buf_max:=#MouseHistory()) > 0 { if MERGE_MOVE && NumGet(MouseBuffer, 20, "uint") = 0x200 ;if MERGE_MOVE && wParam = 0x200 && NumGet(MouseBuffer, 20, "uint") = 0x200 { ; Update the most recent (mouse-move) event. DllCall("RtlMoveMemory", "ptr", &MouseBuffer, "ptr", lParam, "ptr", 20) } else { ; Push older mouse events to the back. if (buf_max > 1) DllCall("RtlMoveMemory", "ptr", &MouseBuffer+24, "ptr", &MouseBuffer, "ptr", buf_max*24) ; Copy current mouse event to the buffer. DllCall("RtlMoveMemory", "ptr", &MouseBuffer, "ptr", lParam, "ptr", 20) } NumPut(wParam, MouseBuffer, 20, "uint") ; Put wParam in place of dwEventInfo. ; "gosub Show" slows down the mouse hook and causes problems, so use a timer. SetTimer, Show, -10 } return DllCall("CallNextHookEx", "uint", 0, "int", nCode, "ptr", wParam, "ptr", lParam, "ptr") } WM_LBUTTONDOWN(wParam, lParam) { global text StringReplace, Clipboard, text, `n, `r`n, All }
声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。
评论(0)