/res/ahk/macro_recorder.ahk

http://github.com/Skiouros/Macro · AutoHotKey · 439 lines · 352 code · 78 blank · 9 comment · 40 complexity · 79324fc5c4c66217d0e2c531269f9d49 MD5 · raw file

  1. Class MacroRecorder Extends CGUI
  2. {
  3. __New(mainGui, owner = "")
  4. {
  5. this.btnAdd := this.AddControl("Button", "btnAdd", "x20 y380 w90 h23", "New")
  6. this.btnCancel := this.AddControl("Button", "btnCancel", "x462 y400 w90 h23", "Cancel")
  7. this.btnDelete := this.AddControl("Button", "btnDelete", "x110 y380 w90 h23", "Delete")
  8. this.btnOK := this.AddControl("Button", "btnOK", "x362 y400 w90 h23", "OK")
  9. this.btnHelp := this.AddControl("Button", "btnHelp", "x562 y400 w90 h23", "Help")
  10. this.btnStartRecord := this.AddControl("Button", "btnStartRecord", "x525 y50 w90 h23", "Start Recording")
  11. this.btnStopRecord := this.AddControl("Button", "btnStopRecord", "x525 y25 w90 h23", "Stop Recording")
  12. this.chkDelay := this.AddControl("Checkbox", "chkDelay", "x485 y80 w165 h30", "Record delays between events")
  13. this.AddControl("Groupbox", "groupbox1", "x485 y110 w155 h80", "")
  14. this.chkMouse := this.AddControl("Checkbox", "chkMouse", "x510 y107 w120 h20", "Include mouse clicks")
  15. this.chkCoords := this.AddControl("Checkbox", "chkCoords", "x490 y130 w100 h20", "Record location")
  16. this.AddControl("GroupBox", "e", "x222 y10 w430 h380", "Details")
  17. this.macroList := this.AddControl("ListView", "macroList", "x12 y10 w190 h360 NoSortHdr -Multi -ReadOnly", "Macro")
  18. this.currentMacro := this.AddControl("ListView", "currentMacro", "x232 y40 w250 h330 NoSortHdr -Multi count100", "Keys")
  19. this.btnStopRecord.Disable()
  20. this.btnStartRecord.Disable()
  21. Menu, MacroName, Add, Edit, EditName
  22. Menu, MacroName, Add, Delete, DeleteName
  23. Menu, LButton, Add, Down, MouseEvent
  24. Menu, LButton, Add, Up, MouseEvent
  25. Menu, LButton, Add, Click, MouseEvent
  26. Menu, RButton, Add, Down, MouseEvent
  27. Menu, RButton, Add, Up, MouseEvent
  28. Menu, RButton, Add, Click, MouseEvent
  29. Menu, MButton, Add, Down, MouseEvent
  30. Menu, MButton, Add, Up, MouseEvent
  31. Menu, MButton, Add, Click, MouseEvent
  32. Menu, Wheel, Add, Backward, MouseEvent
  33. Menu, Wheel, Add, Forward, MouseEvent
  34. Menu, MouseEvents, Add, Left Button, :LButton
  35. Menu, MouseEvents, Add, Right Button, :RButton
  36. Menu, MouseEvents, Add, Middle Button, :MButton
  37. Menu, MouseEvents, Add, Wheel, :Wheel
  38. Menu, Macro, Add, Insert Mouse Event, :MouseEvents, P100
  39. Menu, Macro, Add, Edit, Edit
  40. Menu, Macro, Add, Insert Delay, InsertDelay
  41. Menu, Macro, Add, Delete, Delete ; Menu for adding delays and mouse events
  42. this.gui := mainGui
  43. this.Owner := owner, this.OwnerAutoClose := 1, this.MinimizeBox := 0
  44. this.Toolwindow := 1
  45. this.Title := "Macro Recorder"
  46. }
  47. chkMouse_CheckedChanged()
  48. {
  49. enabled := this.chkMouse.Checked
  50. this.chkCoords.Enabled := enabled
  51. }
  52. btnOK_Click()
  53. {
  54. debug ? debug("Saving macros")
  55. this.UpdateMacro()
  56. xml.Save(A_ScriptDir . "\res\Profiles\" . xml.Get("name") . ".xml") ; Save xml file.
  57. this.ClearCurrentMacro()
  58. ; Update current hotkey with new macro name.
  59. if (this.selectedRow)
  60. if (macroName := this.MacroName(this.selectedRow))
  61. this.gui.UpdateKey(MacroName)
  62. this.oldMacroName := "", this.selectedRow := 0
  63. this.gui.Enabled := true
  64. this.Hide()
  65. this.gui.UpdateMacros()
  66. }
  67. btnHelp_Click()
  68. {
  69. MsgBox,
  70. ( LTrim
  71. Right click "Keys" listview for context menu.
  72. Any thing selected from context menu will be added to bottom of seleced item.
  73. )
  74. }
  75. btnStartRecord_Click()
  76. {
  77. global PID
  78. this.StopRecording := 0
  79. this.ClearCurrentMacro()
  80. debug ? debug("Start recording macro")
  81. ; Disable controls while recording keys.
  82. this.SetControls(0)
  83. this.btnStopRecord.Enabled := 1
  84. this.btnStartRecord.Enabled := 0
  85. Delay := this.chkDelay.Checked
  86. Click := this.chkMouse.Checked
  87. location := this.chkCoords.Checked
  88. ; load the script to monitor key strokes.
  89. AhkRecorder.ahkDll(A_ScriptDir . "\res\ahk\recorder.ahk")
  90. AhkRecorder.ahkAssign("delay", (Delay ? "1" : "0"))
  91. AhkRecorder.ahkAssign("mouseClicks", (Click ? "1" : "0"))
  92. AhkRecorder.ahkAssign("location", (location ? "1" : "0"))
  93. AhkRecorder.ahkAssign("PID", PID)
  94. While (!AhkRecorder.ahkReady()) ;wait for the script to be ready
  95. Sleep 10
  96. }
  97. btnStopRecord_Click()
  98. {
  99. AhkRecorder.ahkTerminate()
  100. initial := 0
  101. debug ? debug("Stop recording macro")
  102. this.StopRecording := 1
  103. ; Enable controls
  104. this.SetControls(1)
  105. this.btnStopRecord.Enabled := 0
  106. this.btnStartRecord.Enabled := 1
  107. this.UpdateMacro()
  108. }
  109. SetControls(Enabled)
  110. {
  111. this.currentMacro.Enabled := Enabled
  112. this.macroList.Enabled := Enabled
  113. this.btnOK.Enabled := Enabled
  114. this.btnAdd.Enabled := Enabled
  115. this.btnDelete.Enabled := Enabled
  116. this.chkDelay.Enabled := Enabled
  117. this.chkMouse.Enabled := Enabled
  118. this.chkCoords.Enabled := Enabled
  119. }
  120. btnCancel_Click()
  121. {
  122. debug ? debug("Canceled macro manager")
  123. this.PreClose()
  124. this.Hide()
  125. }
  126. btnAdd_Click(saveRow = 0)
  127. {
  128. debug ? debug("Added macro")
  129. Loop ; Create a macro with a unique name.
  130. {
  131. macroName := "Macro" . A_Index
  132. if (!xml.Exist("macro", macroName))
  133. break
  134. }
  135. this.macroList.Items.Add("Select", macroName)
  136. this.macroList.Items.Modify(this.macroList.Items.Count, "vis")
  137. xml.AddMacro(macroName, "")
  138. ; Make the name editable right away.
  139. ControlFocus, SysListView321, A
  140. ControlSend, SysListView321, {End}, A
  141. ControlSend, SysListView321, {F2}, A
  142. ; Save current macro for possible use.
  143. if (saveRow)
  144. this.selectedRow := this.macroList.FocusedIndex
  145. }
  146. btnDelete_Click()
  147. {
  148. selectedRow := this.macroList.FocusedIndex
  149. if (!text := this.macroList.Items[selectedRow][1])
  150. return
  151. MsgBox, 52, , % "Are you sure you want to delete:`n" . text
  152. IfMsgBox, No
  153. return
  154. debug ? debug("Deleted macro: " . text)
  155. this.macroList.Items.Delete(selectedRow)
  156. this.ClearCurrentMacro()
  157. xml.Delete("macros", text)
  158. }
  159. currentMacro_ContextMenu()
  160. {
  161. if (this.macroList.FocusedIndex && this.currentMacro.Enabled) ;Also works if other controls like the button were focused before.
  162. {
  163. selectedRow := this.currentMacro.FocusedIndex
  164. ControlGet, pressedKeys, List, , % this.currentMacro.ClassNN, A ; Get all the keys from the listbox
  165. StringSplit, text,pressedKeys, `n
  166. if (InStr(text%selectedRow%, "Sleep"))
  167. {
  168. Menu, Macro, Enable, Edit
  169. GuiControl, -ReadOnly, % this.currentMacro.ClassNN
  170. }
  171. else
  172. Menu, Macro, Disable, Edit
  173. Menu, Macro, Show
  174. }
  175. }
  176. macroList_ContextMenu()
  177. {
  178. if (this.macroList.FocusedIndex && this.macroList.Enabled)
  179. Menu, MacroName, Show
  180. }
  181. MacroName(Index)
  182. {
  183. ControlGet, macros, List, , % this.macroList.ClassNN, A ; Get all the keys from the listbox
  184. StringSplit, macroName, macros, `n
  185. return macroName%Index%
  186. }
  187. macroList_ItemFocused(RowIndex)
  188. {
  189. macroName := this.MacroName(RowIndex)
  190. if (macroName = this.oldMacroName)
  191. return
  192. else if macroName is number
  193. return
  194. this.oldMacroName := macroName
  195. this.LoadMacro(macroName) ; Update ListView to show keys in macro
  196. debug ? debug("Loaded macro: " . macroName)
  197. }
  198. macroList_EditingStart(RowIndex)
  199. {
  200. this.savedText := this.macroList.Items[RowIndex][1]
  201. }
  202. macroList_EditingEnd(RowIndex)
  203. {
  204. text := this.macroList.Items[RowIndex][1]
  205. firstChar := SubStr(text, 1, 1)
  206. ; Make sure name is fine
  207. if text is not alnum
  208. {
  209. MsgBox, 48, , Only letters and numbers allowed.
  210. this.macroList.Items[RowIndex][1] := this.savedText
  211. }
  212. else if (!text) ; Make sure text isn't blank
  213. this.macroList.Items[RowIndex][1] := this.savedText
  214. else if firstChar is not Alpha
  215. {
  216. MsgBox, 48, , Macro names must start with a letter.
  217. this.macroList.Items[RowIndex][1] := this.savedText
  218. }
  219. else if (text = this.savedText)
  220. return
  221. else if (xml.Exist("macro", text)) ; Check to make sure we don't have duplicate macros.
  222. {
  223. MsgBox, 48, ,Duplicate names are not allowed.
  224. this.macroList.Items[RowIndex][1] := this.savedText
  225. }
  226. else
  227. {
  228. xml.Rename("macro", this.savedText, text)
  229. debug ? debug("Renamed macro: " . this.savedText . " to " . text)
  230. ; xml.Save(A_ScriptDir, xml.Get("name")) ; Save xml file.
  231. }
  232. }
  233. currentMacro_EditingStart(RowIndex)
  234. {
  235. selectedRow := this.currentMacro.FocusedIndex
  236. ControlGet, pressedKeys, List, , % this.currentMacro.ClassNN, A ; Get all the keys from the listbox
  237. StringSplit, text,pressedKeys, `n
  238. text := text%selectedRow%
  239. if (!InStr(text, "Sleep"))
  240. {
  241. GuiControl, +ReadOnly, % this.currentMacro.ClassNN
  242. return
  243. }
  244. this.savedDelay := text
  245. Send % Trim(RegExReplace(text, "Sleep??,[\s]*?")) . "^+{Left}"
  246. }
  247. currentMacro_EditingEnd(RowIndex)
  248. {
  249. ControlGet, pressedKeys, List, , % this.currentMacro.ClassNN, A ; Get all the keys from the listbox
  250. StringSplit, text, pressedKeys, `n
  251. text := text%RowIndex%
  252. if (!text)
  253. this.currentMacro.Items.Modify(RowIndex, "", this.savedDelay)
  254. else if text is not number
  255. this.currentMacro.Items.Modify(RowIndex, "", this.savedDelay)
  256. else
  257. this.currentMacro.Items.Modify(RowIndex, "", "Sleep, " . text)
  258. }
  259. ClearCurrentMacro()
  260. {
  261. Loop % this.currentMacro.Items.Count
  262. this.currentMacro.Items.Delete(1)
  263. }
  264. LoadMacro(macroName)
  265. {
  266. if (!macroName)
  267. return
  268. debug ? debug("Loading " . macroName . " in macro manager")
  269. this.ClearCurrentMacro()
  270. value := xml.Get("macro", macroName, "value")
  271. StringReplace, value, value, ``n, `n, all
  272. Loop, Parse, value, `n
  273. this.currentMacro.Items.Add("", A_LoopField) ; add contents of macro to listview.
  274. this.btnStartRecord.Enable()
  275. }
  276. Load(name = "", new = 0)
  277. {
  278. Loop % this.macroList.Items.Count
  279. this.macroList.Items.Delete(1)
  280. debug ? debug("Loading macro manager")
  281. macros := xml.List("macros", "|")
  282. Loop, Parse, macros, |
  283. if (Trim(A_LoopField, "`n`r "))
  284. this.macroList.Items.Add("", A_LoopField) ; Add each macro to the listview.
  285. this.Show()
  286. if (name)
  287. {
  288. ControlGet, macros, List, , % this.macroList.ClassNN, A ; Get all the keys from the listbox
  289. StringSplit, macroName, macros, `n
  290. Loop % macroName0
  291. if (name = macroName%A_Index%)
  292. index := A_Index
  293. ControlFocus, % this.macroList.ClassNN, A
  294. this.macroList.Items.Modify(index, "Focus")
  295. this.macroList.Items.Modify(index, "Select")
  296. }
  297. if (new)
  298. this.btnAdd_Click(1)
  299. }
  300. UpdateMacro()
  301. {
  302. if (!this.macroList.FocusedIndex)
  303. return
  304. ControlGet, pressedKeys, List, , SysListView322, A ; Get all the keys from the listbox
  305. StringReplace, pressedKeys, pressedKeys, `n, ``n, All ; Changes newlines to `n so it can be stored in xml
  306. selectedRow := this.macroList.FocusedIndex
  307. macroName := this.macroList.Items[selectedRow][1]
  308. debug ? debug("Updated macro: " . macroName)
  309. xml.AddMacro(macroName, pressedKeys) ; Add the macro to xml.
  310. }
  311. ;Called when the window was destroyed (e.g. closed here)
  312. PreClose()
  313. {
  314. this.btnStopRecord_Click()
  315. this.ClearCurrentMacro()
  316. xml := new Xml(currentXml)
  317. this.oldMacroName := "", this.selectedRow := 0
  318. this.gui.Enabled := true
  319. }
  320. }
  321. EditName:
  322. Send, {F2}
  323. return
  324. DeleteName:
  325. gui.Macro.btnDelete_Click()
  326. return
  327. Edit:
  328. Send, {F2}
  329. return
  330. Delete:
  331. selectedRow := gui.Macro.currentMacro.FocusedIndex
  332. gui.Macro.currentMacro.Items.Delete(selectedRow)
  333. return
  334. InsertDelay:
  335. selectedRow := gui.Macro.currentMacro.FocusedIndex + 1
  336. if (!selectedRow)
  337. selectedRow := 1
  338. gui.Macro.currentMacro.Items.Insert(selectedRow, "", "Sleep, 100")
  339. return
  340. MouseEvent:
  341. selectedRow := gui.Macro.currentMacro.FocusedIndex + 1
  342. if (A_ThisMenu = "Wheel")
  343. {
  344. if (A_ThisMenuItem = "Forward")
  345. event := "{" . A_ThisMenu . "Up}"
  346. else if (A_ThisMenuItem = "backwards")
  347. event := "{" . A_ThisMenu . "Down}"
  348. }
  349. else if (A_ThisMenuItem = "click")
  350. {
  351. event := "{" . A_ThisMenu . " Down}"
  352. gui.Macro.currentMacro.Items.Insert(selectedRow, "", event)
  353. event := "{" . A_ThisMenu . " Up}"
  354. gui.Macro.currentMacro.Items.Insert(selectedRow + 1, "", event)
  355. return
  356. }
  357. else
  358. event := "{" . A_ThisMenu . " " . A_ThisMenuItem . "}"
  359. gui.Macro.currentMacro.Items.Insert(selectedRow, "", event)
  360. gui.UpdateMacro()
  361. return