Mouse And Keyboard Macro Recorder

Post your working scripts, libraries and tools for AHK v1.1 and older
kostiantyndvornik
Posts: 3
Joined: 25 Jun 2023, 05:01

Re: Mouse And Keyboard Macro Recorder

25 Oct 2023, 03:39

Updated with neural netwoks. Now it stabilize image based on recognized sky or ground
https://www.youtube.com/watch?v=ASy-2zOMj_Y
umiz
Posts: 1
Joined: 08 Dec 2023, 05:40

Re: Mouse And Keyboard Macro Recorder

10 Dec 2023, 12:36

DarkSnoops wrote:
03 Apr 2023, 21:51
Hi !
Has anyone converted his script to AHK V 2.0 ? :D
I also wonder this. It would be very nice!
spidell
Posts: 4
Joined: 10 Jan 2024, 16:29

Re: Mouse And Keyboard Macro Recorder

16 Jan 2024, 16:02

Wow, this is amazing. Great work.

I am having trouble with one task; I have several PDFs open in Adobe Acrobat Reader and need to print onto different sized-paper in a specific pattern, for example:

1st page (print 1 copy letter size), 2nd page (print 2 copies letter), 3rd page (print 2 copies letter),
Return to 1st page (print 3 copies tabloid size), 2nd page (print 1 copy tabloid), 3rd page (print 1 copy tabloid)


I want to be able to print in this pattern regardless of what PDFs I have open. Since this recorder will record the PDF names during the Macro, I had to create another AHK tool to remove any PDF names from the script:

Code: Select all

#Persistent
#SingleInstance
Gui, Add, Text, , Select a text file to edit:
Gui, Add, Edit, vSelectedFile -ReadOnly
Gui, Add, Button, Default, Browse
Gui, Add, Button, Default, Edit
Gui, Show, Center, PDF Text Editor

Return

ButtonBrowse:
Gui, Submit, NoHide
FileSelectFile, SelectedFile, 3, , Select a text file to edit, Text files (*.txt)
GuiControl,, SelectedFile, %SelectedFile%
Return

ButtonEdit:
    Gui, Submit, NoHide
    IfNotExist, %SelectedFile%
    {
        MsgBox, 16, Error, Please select a valid text file.
        Return
    }

    FileRead, OriginalContent, %SelectedFile%

    ; Specify the text pattern to be removed in a case-insensitive manner
    PatternToRemove := "(?i)\b\d+-[^\s]+\.pdf\s*-\s*"

    ; Remove the specified pattern from each line
    EditedContent := RegExReplace(OriginalContent, PatternToRemove, "")

    ; Write the edited content to a temporary file
    TempFile := A_Temp "\TempEditedFile.txt"
    FileDelete, %TempFile%
    FileAppend, %EditedContent%, %TempFile%

    ; Overwrite the existing file with the edited content
    FileDelete, %SelectedFile%
    FileMove, %TempFile%, %SelectedFile%, 1 ; Overwrite the existing file

    GuiControl,, SelectedFile, %SelectedFile%
    MsgBox PDFs removed from text document. File overwritten.
    Return

GuiClose:
ExitApp
which works great.

The only issue now is, at times the print Progress window will block a click from reaching the Adobe window to click the next drawing in order. As an AHK newbie, should I be incorporating WinWaitActivate or another modification?
spidell
Posts: 4
Joined: 10 Jan 2024, 16:29

Re: Mouse And Keyboard Macro Recorder

16 Jan 2024, 16:28

Is it possible to develop a scrubber/progress bar for playback? To be able to choose where to unpause a macro... what a dream.
Kades91
Posts: 1
Joined: 13 Apr 2024, 11:59

Re: Mouse And Keyboard Macro Recorder

13 Apr 2024, 12:03

Hi all.

How do I get it to stop overwriting already saved files?

Example

I create 1 AHK file, get it working perfectly, delete the 1 in F5 Edit to make it loop indefinitely...

I create another AHK file, get it working perfectly, delete the 1 in F5 to make it loop indefinitely but then it overwrites the 1st AHK file and makes them both the exact same file?
spidell
Posts: 4
Joined: 10 Jan 2024, 16:29

Re: Mouse And Keyboard Macro Recorder

16 Apr 2024, 12:57

Try using Speedmaster's version below, this will allow you to export a Macro once you create it, and import others that have already been created.

Code: Select all

;-----------------------------------
;  Macro Recorder v2.1+  By FeiYue  (modified by Speedmaster)
;
;  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
;  F9  -->  More Options
;  F10  --> Hide/Show Panel Buttons
;
;  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.
;-----------------------------------

#SingleInstance force
#NoEnv
SetBatchLines, -1
Thread, NoTimers
CoordMode, ToolTip
SetTitleMatchMode, 2
DetectHiddenWindows, On

;--------------------------
logkeys:=""
playspeed:=2                           ; Set default playing speed here
EditorPath:="Notepad.exe"              ; set default editor path here
;~ EditorPath:=StrReplace(a_ahkpath, "autohotkey.exe") . "SciTE\SciTE.exe"     ; actvate if you have installed SciTE
LogFile:=A_Temp . "\~Record.ahk"
UsedKeys:="F1,F2,F3,F4,F5,F6,F9"
Play_Title:=RegExReplace(LogFile,".*\\") " ahk_class AutoHotkey"
global tlogmouse,tlogkey, playspeed
;--------------------------
Gui 1: +AlwaysOnTop -Caption +ToolWindow +E0x08000000 +Hwndgui_id
Gui 1: Margin, 0, 0
Gui 1: Font, s11
s:="[F1]Rec (Scr),[F2]Rec (Win),"
  . "[F3]Stop,[F4]Play,[F5]Edit,[F6]Pause,[F9]Options "
For i,v in StrSplit(s, ",")
{
  j:=i=1 ? "":"x+0", j.=InStr(v,"Pause") ? " vPause":""
  Gui, Add, Button, %j% gRun, %v%
}
Gui 1: Add, Button, x+0 w0 Hidden vMyText
Gui 1: Show, NA y0, Macro Recorder

gui 2: add, groupbox, r3,Record
Gui 2: Add, Checkbox, y25 xp+10 Checked1 ghcheck vTLogkey, Log keys
Gui 2: Add, Checkbox, Checked1 ghcheck vTLogmouse, Log mouse
Gui 2: Add, Checkbox, Checked1 ghcheck vTLogWindow, Log window


Gui 2:add, button, vTbuttons ghidebuttons y+20 w130, Hide Panel Buttons F10
Gui 2:add, button, gopen wp, Import Macro
Gui 2:add, button, gFileSaveAs wp, Export Macro
Gui 2:add, button, gexit wp, Exit Macro Recorder
gui 2: submit

if !InStr(FileExist("Macros"), "D")
   FileCreateDir, Macros

OnMessage(0x200,"WM_MOUSEMOVE")
;--------------------------
SetTimer, OnTop, 2000
OnTop:
Gui, +AlwaysOnTop
return

hcheck:
gui 2: submit, nohide
return

F10::
hidebuttons:
hidebuttons:=!hidebuttons
if hidebuttons {
	guicontrol,, tbuttons, Show Panel Buttons F10
	Gui 1:Hide
}
else {
	guicontrol,, tbuttons, Hide Panel Buttons F10
	Gui 1:show
}
return


Run:
aguictrl:=A_GuiControl
instr(aguictrl, "scr")&&aguictrl:="[F1]Record(Screen)"
instr(aguictrl, "win")&&aguictrl:="[F2]Record(Window)"
if IsLabel(k:=RegExReplace(RegExReplace(aguictrl,".*]"),"\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

;~ F7::
F3::
Stop:
Suspend, Permit
if Recording
{
  if (LogArr.MaxIndex()>0)
  {
    s:="`nPlayspeed:=" playspeed " `n`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.="`n  Sleep, 1000  //PlaySpeed `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


;~ F8::
F5::
Edit:
Suspend, Permit
Gosub, Stop
Run, %EditorPath% "%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


Open:
OutputVar:=""
FileSelectFile, OutputVar,, macros, Import File, AHK Macro File (*.ahk; *.txt)
if (OutputVar)
FileCopy, % OutputVar, % LogFile , 1
return

;-------------------------
FileSaveAs:
Gui +OwnDialogs  ; Force the user to dismiss the FileSelectFile dialog before returning to the main window.
FileSelectFile, SelectedFileName, S16, Macros, Save File, AHK File (*.ahk)
if SelectedFileName =  ; No file selected.
    return
CurrentFileName = %SelectedFileName%

IfExist %CurrentFileName%
{
    FileDelete %CurrentFileName%
    if ErrorLevel
    {
        MsgBox The attempt to overwrite "%CurrentFileName%" failed.
        return
    }
}

SplitPath, CurrentFileName,,, OutExtension

if (OutExtension)
  FileCopy, % LogFile, % CurrentFileName , 1
else
  FileCopy, % LogFile, % CurrentFileName ".ahk" , 1
return

F9::
Options:
Gui 2: +AlwaysOntop
Gui 2: Show, y100, Macro Recorder
gui 2: submit, nohide
return

;~ F12::
exit:
SplashTextOn,100,70,Macro recorder, `nGoodbye
sleep, 1000
exitapp
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:
(tLogWindow)&&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
    (tlogkey)&&LogKey_Control(k)
  else if k in LButton,RButton,MButton
    (TlogMouse)&&LogKey_Mouse(k)
  else
  {
    if (!tlogkey)
      return
    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%"  
  s:="      tt = " title "`n      WinWait, %tt%"
    . "`n      IfWinNotActive, %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("  Sleep, `% " (Delay) " //playspeed")
  LogArr.Push(Keyboard ? "Send, {Blind}" str : str)
}

;============ The End ============

[Mod edit: Added [code][/code] tags. Please use them yourself when posting code, especially when this long.]
kashmirLZ
Posts: 48
Joined: 06 Oct 2022, 23:27

Re: Mouse And Keyboard Macro Recorder

21 Apr 2024, 23:14

I like this part at the end too lol

Code: Select all

;============ The End ============
Like I just finished reading a novel.

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: gwarble, xavierarmand and 127 guests