baconaise Posted March 10, 2023 Share Posted March 10, 2023 (edited) My goal is to use a hotkey to Send() text acquired from the GUICtrlRead() of an edit field on a GUI. So far, so easy. The challenge: Midway through the string returned by GUICtrlRead() (and sometimes more than once), will be a string like {MouseClick("left", x, y)}. When the program reaches that part of the string, I would like it to click at the coordinates specified; then, continue with SEND(). My original plan was to use StringSplit() with the clicks as delimiters. In theory, to loop through the array of strings, clicking when necessary. My plan doesn't seem like it will work because x and y will be unpredictable numbers, and I'm not sure how to overcome that impediment. I welcome any thoughts. Edit: This is my code so far. #include <GUIConstants.au3> AutoItSetOption("MustDeclareVars", 1) Opt("GUIOnEventMode", 1) Global $aGUI = GUICreate("", 300, 100) Global $Text_Field = GUICtrlCreateEdit("Hello{MouseClick('left',100,100)} world{MouseClick('left',200,200)}.", 0, 0, 300, 100, $ES_MULTILINE+$WS_VSCROLL) GUISetOnEvent($GUI_EVENT_CLOSE, "GUI_Events") GUISetOnEvent($GUI_EVENT_MINIMIZE, "GUI_Events") GUISetOnEvent($GUI_EVENT_RESTORE, "GUI_Events") GUISetState(@SW_SHOW,$aGUI) HotKeySet("{F1}", "F1_HotKey") While 1 Sleep(10) Wend Func GUI_Events() Select Case @GUI_CtrlId = $GUI_EVENT_CLOSE Exit EndSelect EndFunc Func F1_HotKey() Local $Text_To_Send = GUICtrlRead($Text_Field) Local $Array_Of_Text_To_Send = StringSplit($Text_To_Send,"") ;but somehow separate out clicks For $i = 1 to $Array_Of_Text_To_Send[0] ;and sequence them in this loop Send($Array_Of_Text_To_Send[$i]) Next EndFunc Edited March 10, 2023 by baconaise Added code to use as template Link to comment Share on other sites More sharing options...
mistersquirrle Posted March 10, 2023 Share Posted March 10, 2023 Could you post some code that shows what you've got so far? If you're parsing a whole string like "First click{MouseClick('left',100,200)}Second click{MouseClick('left',200,400)}", then I assume that you're using Send to send 1 key at a time and checking if you've reached a command instead of character? I would recommend using _StringBetween when you reach a special character, like "{" to find your command, execute it, then continue with your Send. Here's an example of how I would do something like that, though it can definitely get a bit messy: expandcollapse popup#include <String.au3> ; String of characters to send and commands to run Global $sString = "First click{MouseClick('left',100,200)}Second click{MouseClick('left',200,400)}" ConsoleWrite('$sString original: ' & $sString & @CRLF) ; Get all commands that are in the string, using {} as the boundries Global $aCommands = _StringBetween($sString, '{', '}') ; Loop through each command in the string, and replace the command (not the {}) with the index for that command For $iIndex = 0 To UBound($aCommands) -1 $sString = StringReplace($sString, $aCommands[$iIndex], $iIndex, 1) ; Make sure that Occurance is 1, so that you're only replacing the first occurance of that command Next ConsoleWrite('$sString commands removed: ' & $sString & @CRLF) ; Build the Send list of characters, note this still has {#} in it, so those will have their own indexes Global $aCharacters = StringSplit($sString, '', 3) Global $bCommand = False ; This will be used to know that we're not sending the characters, and so that we're... Global $iCommandIndex = '' ; Building this index from the $aCharacters array between { and } ; Now loop through the string to Send your keys, and when found, get the command index and execute the command For $iChar = 0 To UBound($aCharacters) - 1 ; Start of a command index If $aCharacters[$iChar] = '{' Then ConsoleWrite('Command found at char index: ' & $iChar & @CRLF) $iCommandIndex = '' ; Make sure that our index is reset $bCommand = True ; Notice that we're about to process a command ContinueLoop ; We can move to the next character EndIf ; If we're in between a command string { # }, build the $iCommandIndex string to get the correct index for $aCommands If $bCommand Then If $aCharacters[$iChar] = '}' Then ; End of the command index, so now we can execute $bCommand = False ; Go back to Send'ing characters ElseIf IsNumber(Int($aCharacters[$iChar])) Then ; Make sure that what we're building for our index is a number $iCommandIndex &= $aCharacters[$iChar] ; Build the index string Else ; Something unexpected ConsoleWrite('Possibly badly formatted command index: ' & $aCharacters[$iChar] & @CRLF) EndIf ; This means that we've processed the entire { ### } section and *should* have the complete index string If $bCommand = False Then ConsoleWrite('Executing command: ' & $iCommandIndex & ', ' & $aCommands[$iCommandIndex] & @CRLF) Execute($aCommands[$iCommandIndex]) ; Do your command EndIf ContinueLoop ; Go to next loop since we don't want to send } EndIf ; Do your normal Send Send($aCharacters[$iChar]) Next We ought not to misbehave, but we should look as though we could. Link to comment Share on other sites More sharing options...
ioa747 Posted March 10, 2023 Share Posted March 10, 2023 (edited) @mistersquirrle In my opinion, the {} as a command identifier, inside the string line, is not a good idea, because it uses from Send() for special characters e.g. {ENTER}, {UP} etc. here is my approach SendPlus('@CMD Run("Notepad.exe")|@CMD Sleep(300)|@CMD WinActivate("[CLASS:Notepad]")') SendPlus('@CMD WinSetState("[CLASS:Notepad]", "", @SW_MAXIMIZE)|send something{Enter 2}') SendPlus('Maximize window{Enter}') SendPlus('Here is more text{Enter 2}... and give some time{Enter}') SendPlus('@CMD sleep(1000)|First click...{Enter}|@CMD MouseClick("left",100,200)|@CMD sleep(500)|Second click|@CMD MouseClick("left",200,400)') ;---------------------------------------------------------------------------------------- Func SendPlus($String) Local $Spl = StringSplit($String, "|", 1) ConsoleWrite("" & @CRLF) For $i = 1 To $Spl[0] If StringLeft($Spl[$i], 5) = "@CMD " Then Local $SplString = StringTrimLeft($Spl[$i], 5) ConsoleWrite($i & ") Comand:" & $SplString & @CRLF) Execute($SplString) Else ConsoleWrite($i & ") String:" & $Spl[$i] & @CRLF) Send($Spl[$i]) EndIf Next EndFunc ;==>SendPlus Edited March 10, 2023 by ioa747 I know that I know nothing Link to comment Share on other sites More sharing options...
baconaise Posted March 10, 2023 Author Share Posted March 10, 2023 19 hours ago, mistersquirrle said: Could you post some code that shows what you've got so far? Certainly! This is my basic idea: #include <GUIConstants.au3> AutoItSetOption("MustDeclareVars", 1) Opt("GUIOnEventMode", 1) Global $aGUI = GUICreate("", 300, 100) Global $Text_Field = GUICtrlCreateEdit("Hello{MouseClick('left',100,100)} world{MouseClick('left',200,200)}.", 0, 0, 300, 100, $ES_MULTILINE+$WS_VSCROLL) GUISetOnEvent($GUI_EVENT_CLOSE, "GUI_Events") GUISetOnEvent($GUI_EVENT_MINIMIZE, "GUI_Events") GUISetOnEvent($GUI_EVENT_RESTORE, "GUI_Events") GUISetState(@SW_SHOW,$aGUI) HotKeySet("{F1}", "F1_HotKey") While 1 Sleep(10) Wend Func GUI_Events() Select Case @GUI_CtrlId = $GUI_EVENT_CLOSE Exit EndSelect EndFunc Func F1_HotKey() Local $Text_To_Send = GUICtrlRead($Text_Field) Local $Array_Of_Text_To_Send = StringSplit($Text_To_Send,"") ;but somehow separate out clicks For $i = 1 to $Array_Of_Text_To_Send[0] ;and sequence them in this loop Send($Array_Of_Text_To_Send[$i]) Next EndFunc Link to comment Share on other sites More sharing options...
Solution jchd Posted March 10, 2023 Solution Share Posted March 10, 2023 (edited) Try this version : Func F1_HotKey() Local $Text_To_Send = GUICtrlRead($Text_Field) Local $Array_Of_Text_To_Send = StringRegExp($Text_To_Send,"([^{]*)({[^}]*})*", 3) For $s In $Array_Of_Text_To_Send If StringLeft($s, 1) = "{" Then Execute(StringRegExpReplace($s, "[{}]", "")) Else Send($s) EndIf Next EndFunc Edited March 11, 2023 by jchd baconaise 1 This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe hereRegExp tutorial: enough to get startedPCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta. SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt) Link to comment Share on other sites More sharing options...
baconaise Posted March 10, 2023 Author Share Posted March 10, 2023 5 minutes ago, jchd said: Try this version : Func F1_HotKey() Local $Text_To_Send = GUICtrlRead($Text_Field) Local $Array_Of_Text_To_Send = StringRegExp($Text_To_Send,"([^{]*)({[^}]*})", 3) If StringLeft($s, 1) = "{" Then Execute(StringRegExpReplace($s, "[{}]", "")) Else Send($s) EndIf Next EndFunc Hello! I had to remove Next because there wasn't a For for it. I'm not sure where you got $s from, but I didn't get anywhere by declaring it prior to the function. I'll admit I'm reasonably mystified by StringRegExp. I've not used it before. Link to comment Share on other sites More sharing options...
jchd Posted March 10, 2023 Share Posted March 10, 2023 Sorry, this resulted from running the code. I've restored it in the post above. When run, it sends string to the point where the mouse was set in the previous loop. Unfortunately this " world" text deleted the For line in Scite! baconaise 1 This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe hereRegExp tutorial: enough to get startedPCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta. SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt) Link to comment Share on other sites More sharing options...
baconaise Posted March 11, 2023 Author Share Posted March 11, 2023 @jchd Well, that's a huge improvement. It's nearly perfect. I'm going to have to study it for a while in order to understand it. The only thing it's missing is it forgets to type the period after world. Link to comment Share on other sites More sharing options...
jchd Posted March 11, 2023 Share Posted March 11, 2023 Try the changed posted version baconaise 1 This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe hereRegExp tutorial: enough to get startedPCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta. SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt) Link to comment Share on other sites More sharing options...
jchd Posted March 11, 2023 Share Posted March 11, 2023 Expression tester with pattern breakdown is here: https://regex101.com/r/483ZUH/1 baconaise 1 This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe hereRegExp tutorial: enough to get startedPCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta. SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt) Link to comment Share on other sites More sharing options...
baconaise Posted March 11, 2023 Author Share Posted March 11, 2023 Absolutely nailed it. Thank you. Link to comment Share on other sites More sharing options...
jchd Posted March 11, 2023 Share Posted March 11, 2023 You're welcome! Now you have another silver bullet for your gun: regexes. Enjoy! This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe hereRegExp tutorial: enough to get startedPCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta. SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt) Link to comment Share on other sites More sharing options...
baconaise Posted March 11, 2023 Author Share Posted March 11, 2023 @jchd Would it be difficult to augment it in such a way that the other Send tricks still work (like {TAB})? Ideally, I'd like those to still work. Ideally ideally, I'd also like to be able to put in a command like {SLEEP 500} and have it sleep half a second when it gets to that point in the text. Link to comment Share on other sites More sharing options...
jchd Posted March 11, 2023 Share Posted March 11, 2023 (edited) The current code can accept {sleep 500} as well without change. But if you intend to use the same separator pair (curly brackets {}) for BOTH AutoIt statements AND Send special syntaxes, then you'll have to test the string content against all of the special syntaxes listed in Send() help. Very cumbersome! Better use a distinct separator for AutoIt statements and leave {} alone. Choose it so that it can't reasonably occur in texts nor in statements. You have the full Unicode BMP (around 64k codepoints) to choose from, but restricting to a number of ASCII everyone can compose easily seems a good idea, like ~ # | ^ % § < > ¤ Example with # #include <GUIConstants.au3> AutoItSetOption("MustDeclareVars", 1) Opt("GUIOnEventMode", 1) Global $aGUI = GUICreate("", 300, 100) Global $Text_Field = GUICtrlCreateEdit("#sleep 150#Hello#MouseClick('left',100,100)# world#MouseClick('left',200,200)#.#send({TAB})#", 0, 0, 300, 100, $ES_MULTILINE+$WS_VSCROLL) GUISetOnEvent($GUI_EVENT_CLOSE, "GUI_Events") GUISetOnEvent($GUI_EVENT_MINIMIZE, "GUI_Events") GUISetOnEvent($GUI_EVENT_RESTORE, "GUI_Events") GUISetState(@SW_SHOW,$aGUI) HotKeySet("{F1}", "F1_HotKey") While 1 Sleep(10) Wend Func GUI_Events() Select Case @GUI_CtrlId = $GUI_EVENT_CLOSE Exit EndSelect EndFunc Func F1_HotKey() Local $Text_To_Send = GUICtrlRead($Text_Field) Local $Array_Of_Text_To_Send = StringRegExp($Text_To_Send,"([^#]*)(#[^#]*#)*", 3) For $s In $Array_Of_Text_To_Send If StringLeft($s, 1) = "#" Then Execute(StringRegExpReplace($s, "#", "")) Else Send($s) EndIf Next EndFunc Using # (for instance) as the sole separator is even easier than dealing with a pair. Edited March 11, 2023 by jchd Fixed a typo baconaise 1 This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe hereRegExp tutorial: enough to get startedPCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta. SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt) Link to comment Share on other sites More sharing options...
baconaise Posted March 11, 2023 Author Share Posted March 11, 2023 That was fantastically helpful. How do I buy you a beer? Link to comment Share on other sites More sharing options...
baconaise Posted March 11, 2023 Author Share Posted March 11, 2023 (edited) @jchd I've been playing with this since yesterday, and I can't seem to sort out the regular expression quite properly. If I use your first recommended ([^#]*)(#[^#]*#), it lets me use multiple clicks and sleeps in a row, but forgets to type anything after the last click/sleep. If I use your amended ([^#]*)(#[^#]*#)*, it types the stuff at the end, but doesn't allow for consecutive slicks/sleeps. Is there some way to allow consecutive clicks/sleeps while still making sure to type the stuff at the end? Edit: I think I fixed it. Func F1_HotKey() Local $Text_To_Send = GUICtrlRead($Text_Field) Local $Array_Of_Text_To_Send = StringRegExp($Text_To_Send,"([^#]*)(#[^#]*#)([^#]*)", 3) For $s In $Array_Of_Text_To_Send If StringLeft($s, 1) = "#" Then Execute(StringRegExpReplace($s, "#", "")) Else Send($s) EndIf Next EndFunc Edited March 11, 2023 by baconaise Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now