Skip to content

Instantly share code, notes, and snippets.

@aqzlpm11
Created June 4, 2020 11:01
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save aqzlpm11/9ecd3465d7706b1b35f89719d837d1c9 to your computer and use it in GitHub Desktop.
Save aqzlpm11/9ecd3465d7706b1b35f89719d837d1c9 to your computer and use it in GitHub Desktop.
Recording script for AHK
;-----------------------------------
; Macro Recorder v2.1 By FeiYue
;
; Description: This script records the mouse
; and keyboard actions and then plays back.
;
; F1 --> Record(Screen) (CoordMode, Mouse, Screen)
; F2 --> Record(Window) (CoordMode, Mouse, Window)
; F3 --> Stop Record/Play
; F4 --> Play LogFile
; F5 --> Edit LogFile
; F6 --> Pause Record/Play
;
; Note:
; 1. press the Ctrl button individually
; to record the movement of the mouse.
; 2. Shake the mouse on the Pause button,
; you can pause recording or playback.
;-----------------------------------
#NoEnv
SetBatchLines, -1
Thread, NoTimers
CoordMode, ToolTip
SetTitleMatchMode, 2
DetectHiddenWindows, On
;--------------------------
LogFile:=A_Temp . "\~Record.txt"
UsedKeys:="F1,F2,F3,F4,F5,F6"
Play_Title:=RegExReplace(LogFile,".*\\") " ahk_class AutoHotkey"
;--------------------------
Gui, +AlwaysOnTop -Caption +ToolWindow +E0x08000000 +Hwndgui_id
Gui, Margin, 0, 0
Gui, Font, s12
s:="[F1]Record(Screen),[F2]Record(Window),"
. "[F3]Stop,[F4]Play,[F5]Edit,[F6] Pause "
For i,v in StrSplit(s, ",")
{
j:=i=1 ? "":"x+0", j.=InStr(v,"Pause") ? " vPause":""
Gui, Add, Button, %j% gRun, %v%
}
Gui, Add, Button, x+0 w0 Hidden vMyText
Gui, Show, NA y0, Macro Recorder
OnMessage(0x200,"WM_MOUSEMOVE")
;--------------------------
SetTimer, OnTop, 2000
OnTop:
Gui, +AlwaysOnTop
return
Run:
if IsLabel(k:=RegExReplace(RegExReplace(A_GuiControl,".*]"),"\W"))
Goto, %k%
return
WM_MOUSEMOVE() {
static OK_Time
ListLines, Off
if (A_Gui=1) and (A_GuiControl="Pause")
and (t:=A_TickCount)>OK_Time
{
OK_Time:=t+500
Gosub, Pause
}
}
ShowTip(s:="", pos:="y35", color:="Red|00FFFF") {
static bak, idx
if (bak=color "," pos "," s)
return
bak:=color "," pos "," s
SetTimer, ShowTip_ChangeColor, Off
Gui, ShowTip: Destroy
if (s="")
return
; WS_EX_NOACTIVATE:=0x08000000, WS_EX_TRANSPARENT:=0x20
Gui, ShowTip: +LastFound +AlwaysOnTop +ToolWindow -Caption +E0x08000020
Gui, ShowTip: Color, FFFFF0
WinSet, TransColor, FFFFF0 150
Gui, ShowTip: Margin, 10, 5
Gui, ShowTip: Font, Q3 s20 bold
Gui, ShowTip: Add, Text,, %s%
Gui, ShowTip: Show, NA %pos%, ShowTip
SetTimer, ShowTip_ChangeColor, 1000
ShowTip_ChangeColor:
Gui, ShowTip: +AlwaysOnTop
r:=StrSplit(SubStr(bak,1,InStr(bak,",")-1),"|")
Gui, ShowTip: Font, % "Q3 c" r[idx:=Mod(Round(idx),r.length())+1]
GuiControl, ShowTip: Font, Static1
return
}
;============ Hotkey =============
F1::
Suspend, Permit
Goto, RecordScreen
F2::
Suspend, Permit
Goto, RecordWindow
RecordScreen:
RecordWindow:
if (Recording or Playing)
return
Coord:=InStr(A_ThisLabel,"Win") ? "Window":"Screen"
LogArr:=[], oldid:="", Log(), Recording:=1, SetHotkey(1)
ShowTip("Recording")
return
F3::
Stop:
Suspend, Permit
if Recording
{
if (LogArr.MaxIndex()>0)
{
s:="`nLoop, 1`n{`n`nSetTitleMatchMode, 2"
. "`nCoordMode, Mouse, " Coord "`n"
For k,v in LogArr
s.="`n" v "`n"
s.="`nSleep, 1000`n`n}`n"
s:=RegExReplace(s,"\R","`n")
FileDelete, %LogFile%
FileAppend, %s%, %LogFile%
s:=""
}
SetHotkey(0), Recording:=0, LogArr:=""
}
else if Playing
{
WinGet, list, List, %Play_Title%
Loop, % list
if WinExist("ahk_id " list%A_Index%)!=A_ScriptHwnd
{
WinGet, pid, PID
WinClose,,, 3
IfWinExist
Process, Close, %pid%
}
SetTimer, CheckPlay, Off
Playing:=0
}
ShowTip()
Suspend, Off
Pause, Off
GuiControl,, Pause, % "[F6] Pause "
isPaused:=0
return
F4::
Play:
Suspend, Permit
if (Recording or Playing)
Gosub, Stop
ahk:=A_IsCompiled ? A_ScriptDir "\AutoHotkey.exe" : A_AhkPath
IfNotExist, %ahk%
{
MsgBox, 4096, Error, Can't Find %ahk% !
Exit
}
Run, %ahk% /r "%LogFile%"
SetTimer, CheckPlay, 500
Gosub, CheckPlay
return
CheckPlay:
Check_OK:=0
WinGet, list, List, %Play_Title%
Loop, % list
if (list%A_Index%!=A_ScriptHwnd)
Check_OK:=1
if Check_OK
Playing:=1, ShowTip("Playing")
else if Playing
{
SetTimer, CheckPlay, Off
Playing:=0, ShowTip()
}
return
F5::
Edit:
Suspend, Permit
Gosub, Stop
Run, notepad.exe "%LogFile%"
return
F6::
Pause:
Suspend, Permit
if Recording
{
Suspend
Pause, % A_IsSuspended ? "On":"Off", 1
isPaused:=A_IsSuspended, Log()
}
else if Playing
{
isPaused:=!isPaused
WinGet, list, List, %Play_Title%
Loop, %list%
if WinExist("ahk_id " list%A_Index%)!=A_ScriptHwnd
PostMessage, 0x111, 65306
}
else return
if isPaused
GuiControl,, Pause, [F6]<Pause>
else
GuiControl,, Pause, % "[F6] Pause "
return
;============ Functions =============
SetHotkey(f:=0) {
; These keys are already used as hotkeys
global UsedKeys
f:=f ? "On":"Off"
Loop, 254
{
k:=GetKeyName(vk:=Format("vk{:X}", A_Index))
if k not in ,Control,Alt,Shift,%UsedKeys%
Hotkey, ~*%vk%, LogKey, %f% UseErrorLevel
}
For i,k in StrSplit("NumpadEnter|Home|End|PgUp"
. "|PgDn|Left|Right|Up|Down|Delete|Insert", "|")
{
sc:=Format("sc{:03X}", GetKeySC(k))
if k not in ,Control,Alt,Shift,%UsedKeys%
Hotkey, ~*%sc%, LogKey, %f% UseErrorLevel
}
SetTimer, LogWindow, %f%
if (f="On")
Gosub, LogWindow
}
LogKey:
LogKey()
return
LogWindow:
LogWindow()
return
LogKey() {
Critical
k:=GetKeyName(vksc:=SubStr(A_ThisHotkey,3))
k:=StrReplace(k,"Control","Ctrl"), r:=SubStr(k,2)
if r in Alt,Ctrl,Shift,Win
LogKey_Control(k)
else if k in LButton,RButton,MButton
LogKey_Mouse(k)
else
{
if (k="NumpadLeft" or k="NumpadRight") and !GetKeyState(k,"P")
return
k:=StrLen(k)>1 ? "{" k "}" : k~="\w" ? k : "{" vksc "}"
Log(k,1)
}
}
LogKey_Control(key) {
global LogArr, Coord
k:=InStr(key,"Win") ? key : SubStr(key,2)
if (k="Ctrl")
{
CoordMode, Mouse, %Coord%
MouseGetPos, X, Y
}
Log("{" k " Down}",1)
Critical, Off
KeyWait, %key%
Critical
Log("{" k " Up}",1)
if (k="Ctrl")
{
i:=LogArr.MaxIndex(), r:=LogArr[i]
if InStr(r,"{Blind}{Ctrl Down}{Ctrl Up}")
LogArr[i]:="MouseMove, " X ", " Y
}
}
LogKey_Mouse(key) {
global gui_id, LogArr, Coord
k:=SubStr(key,1,1)
CoordMode, Mouse, %Coord%
MouseGetPos, X, Y, id
if (id=gui_id)
return
Log("MouseClick, " k ", " X ", " Y ",,, D")
CoordMode, Mouse, Screen
MouseGetPos, X1, Y1
t1:=A_TickCount
Critical, Off
KeyWait, %key%
Critical
t2:=A_TickCount
if (t2-t1<=200)
X2:=X1, Y2:=Y1
else
MouseGetPos, X2, Y2
i:=LogArr.MaxIndex(), r:=LogArr[i]
if InStr(r, ",,, D") and Abs(X2-X1)+Abs(Y2-Y1)<5
LogArr[i]:=SubStr(r,1,-5), Log()
else
Log("MouseClick, " k ", " (X+X2-X1) ", " (Y+Y2-Y1) ",,, U")
}
LogWindow() {
global oldid, LogArr
static oldtitle
id:=WinExist("A")
WinGetTitle, title
WinGetClass, class
if (title="" and class="")
return
if (id=oldid and title=oldtitle)
return
oldid:=id, oldtitle:=title
title:=SubStr(title,1,50)
if (!A_IsUnicode)
{
GuiControl,, MyText, %title%
GuiControlGet, s,, MyText
if (s!=title)
title:=SubStr(title,1,-1)
}
title.=class ? " ahk_class " class : ""
title:=RegExReplace(Trim(title), "[``%;]", "``$0")
s:="tt = " title "`nWinWait, %tt%"
. "`nIfWinNotActive, %tt%,, WinActivate, %tt%"
i:=LogArr.MaxIndex(), r:=LogArr[i]
if InStr(r,"tt = ")=1
LogArr[i]:=s, Log()
else
Log(s)
}
Log(str:="", Keyboard:=0) {
global LogArr
static LastTime
t:=A_TickCount, Delay:=(LastTime ? t-LastTime:0), LastTime:=t
IfEqual, str,, return
i:=LogArr.MaxIndex(), r:=LogArr[i]
if (Keyboard and InStr(r,"Send,") and Delay<1000)
{
LogArr[i]:=r . str
return
}
if (Delay>200)
LogArr.Push("Sleep, " (Delay//2))
LogArr.Push(Keyboard ? "Send, {Blind}" str : str)
}
;============ The End ============
;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment