Build an array in AHK from mouse clicks - autohotkey

I am looking to build an array of mouse click coordinates. I'm struggling to understand how you build out a two-dimensional array. Or if I'm going about this wrong and should build two arrays. One with X-coordinates and one with Y-coordinates.
I can easily build out an array with just X coordinates or just Y-coordinates. Can I somehow build out X and Y into the same 2-D array?
ArrayX := []
ArrayY := []
counter:=1
^Lbutton::
MouseGetPos CurX, CurY
ArrayX[counter] := CurX
ArrayY[counter] := CurY
counter++
return
^q::
loop % ArrayX.MaxIndex()
items.= ArrayX[A_Index] ","
StringLeft, items, items, Strlen(items)-1
Clipboard := items
msgbox % items
items:=""
loop % ArrayY.MaxIndex()
items.= ArrayY[A_Index] ","
StringLeft, items, items, Strlen(items)-1
Clipboard := items
msgbox % items
exitapp

You'd create a multidimensional or a jagged array in AHK by just assigning the element at the desired index an array.
Array[3] := [481, 529]
And you'd access it by just accessing the elements in order, e.g:
Array[3][2] would result in 529.
Other things to improve on your script:
You might want to use the .Push() method to append values to your array.
A for loop might be a desirable alternative to normal looping and worrying about the index:
for each, element in Array
StringLeft is a deprecated legacy command and shouldn't be used anyone. SubStr() replaces it.
However, for what you were doing with it, RTrim() would be better/easier:
RTrim(items, ",")
Revised script:
Array := []
^LButton::
MouseGetPos, CurX, CurY
Array.Push([CurX, CurY])
return
^q::
For each, element in Array
items .= element[1] ", " element[2] "`n"
MsgBox, % RTrim(items, "`n")
ExitApp
return

Related

What happens when I try to copy an object with `thecopy := object` instead of object.Clone()?

thearray := [6,77,4,3,66,11]
thecopy := thearray
MsgBox % thecopy.Length() ; 6
thearray := function(thearray)
MsgBox % thecopy.Length() ; 0
MsgBox % thearray.Length() ; 6
Why is thecopy "ruined" when thearray is changed by a function? My guess: The function changes the thearray. Therefor thecopy, which I guess is some kind of reference (?) to the same array as 'thearray' was, is invalid or something. Is this the right way to think about this? I'm all new to this reference thing or whatever it is.
And by the way, if .Clone() is added in the end of the second row thecopy remains intact.

Series of Variables by name

In AHK script:
Code for finding a value between great numbers of variables above, for one variable:
If (Variable1 = "sin (90°)")
MsgBox Value is reached
How searching by this method between series of variables with different value of number in their names? From Variable5 to Variable15, Variable51 to Variable105, etc.
How modify this code if number from 5 to 15, 51 to 105, or 74 to 117 etc?
number = 5
If (Variable%number% = "sin (90°)")
.............
Is %Variable%number%% acceptable and will works surely?
And here may also be useful Associative Arrays. What is it by simple examples?
Best practice here would probably be to use an array in the first place.
myArray := []
myArray[1] := "bla"
myArray.Push("bla2") ;by using this you don't need to worry about the index number
myArray[3] := "sin (90°)"
myArray[4] := 63456
Loop % myArray.MaxIndex()
{
If (myArray[A_Index] = "sin (90°)")
{
MsgBox Value is reached
}
}
... another example
anotherArray := []
Loop, read, C:\Files\prog.txt
{
If (A_LoopReadLine = "FileRead, OutputVar, C:\Files\prog1.txt")
{
anotherArray.Push(A_LoopReadLine)
MsgBox, An interesting code line was found. And was added to the array.
}
Else If (A_LoopReadLine = "blablabla")
{
anotherArray.Push(A_LoopReadLine)
MsgBox, An interesting code line was found. And was added to the array.
}
Else If (A_LoopReadLine = "some other text line")
{
anotherArray.Push(A_LoopReadLine)
MsgBox, An interesting code line was found. And was added to the array.
}
;Else
;{
; MsgBox, Nothing important was found.
;}
}
Loop % anotherArray.MaxIndex()
{
currentArrayEntry := anotherArray[A_Index]
MsgBox, %currentArrayEntry%
}
In an expression you can use variable expansion to modify the name of the variable to use:
number = 5
If (Variable%number% = "sin (90°)")
.............
But consider using arrays instead.
Is %Variable%number%% acceptable and will works surely?
Not. More right way
% Variable%number%
but it may have a problem.
Possible way is use Var := expression
Variable:= number
may be.

How do i parse a variable in a function to being able to define which variable to send?

This is my code
IniRead, custommessage1, whisperconfig.ini, messages, Message1
IniRead, custommessage2, whisperconfig.ini, messages, Message2
^NumPad1::whispermessage(1)
whispermessage(var){
finalwhisper := "custommessage" + var ;this equals custommessage1
Msgbox, %finalwhisper%
BlockInput On
SendInput ^{Enter}%finalwhisper%{Enter} ;<-- problem
BlockInput Off
return
}
So in the first line i am importing the value of custommessage1 (it could be "hi im henrik"). This is what i wish to end up getting as a output.
Inside the function i want the var (which is 1 in this case) to be merged with a variable called custommessage ending with a result of custommessage1
i want the endresult to do a SendInput %custommessage1%.
this way i can have one function for up to 9 triggers including var numbers.
Can anyone help? i am sure this is fairly simple however i am new to this coding thing so bear with me.
Your function only knows about its own variables, the ones you pass in as parameters, and global variables.
You're trying to access custommessage1, which is outside the function and isn't global. You either need to make all your variables global, or pass them in to the function.
I suggest the latter, using an array. Here's an example, make sure you're running the latest version of AHK for this to work properly.
IniRead, custommessage1, whisperconfig.ini, messages, Message1
IniRead, custommessage2, whisperconfig.ini, messages, Message2
; Store all messages in an array
messageArray := [custommessage1, custommessage2]
; Pass the array and message you want to print
^NumPad1::whispermessage(messageArray, 1)
whispermessage(array, index){
; Store the message at the given index in 'finalwhisper'
finalwhisper := array[index]
Msgbox, %finalwhisper% ; Test msgbox
; Print the message
BlockInput On
SendInput ^{Enter}%finalwhisper%{Enter}
BlockInput Off
}
Alternatively, and this is outside the scope of your question, you could load the keys from the .ini file dynamically, meaning you wouldn't have to create new variables each time you added a key/value pair.
Here's how you could do that:
; Read all the key/value pairs for this section
IniRead, keys, whisperconfig.ini, messages
Sort, keys ; Sort the keys so that they are in order
messageArray := [] ; Init array
; Loop over the key/value pairs and store all the values
Loop, Parse, keys, `n
{
; Trim of the key part, and only store the value
messageArray.insert(RegExReplace(A_LoopField, "^.+="))
}
; Pass the array and message you want to print
^NumPad1::whispermessage(messageArray, 1)
whispermessage(array, index){
; Store the message at the given index in 'finalwhisper'
finalwhisper := array[index]
Msgbox, %finalwhisper% ; Test msgbox
; Print the message
BlockInput On
SendInput ^{Enter}%finalwhisper%{Enter}
BlockInput Off
}

autohotkey how to cycle through array

I'm mainly a javascript developer and I'm starting to play with authotkey. I'm guessing if there is a better way to loop through an array than the way I'm using. Basically is like this:
cycle(value,maxValue){
value += 1
if value not between 1 and %maxValue%
value :=1
return value
}
Then I use it like this:
variable := cycle(variable,array.MaxIndex())
Seems a bit rudimentary. Is any other way?
EDIT:
I saw that my description was not clear. What I want is to get variables from the array in a circular way: when you ask for the next value and you are already at the last one, start again from the beginning.
Sounds like what you need is a for-loop
Example:
colors := Object("red", 0xFF0000, "blue", 0x0000FF, "green", 0x00FF00)
for key, value in colors
s .= key "=" value "`n"
MsgBox % s
Edit:
As per your comment, this may be more towards your need
index := 0
maxValue := 10
f3::
tooltip % index := cycle(index, maxValue)
return
cycle(index, maxValue)
{
return index := mod(index + 1, maxvalue)
}
Hope it helps
Since what blackholyman did is correct, it is not aimed on arrays.
Here is an approach that now I know it works:
i:=0,somearr:= ["bla","morebla","bla bla"]
;-- do whatever stuff here
somearr[i:=i>1?--i:somearr.MaxIndex()]

how to compare values of an array with a single value in matlab

Can anyone tell me how to compare this for loop array value pp1 with the single value of pp. If the value of pp is present in pp1 then it must show 1 or must show 0. I'm getting 1 only the last value of pp1. The code is:
[pp,pf1]=pitchauto(x,fs);
for ix=1:2
V='.wav';
ie=num2str(ix);
Stc=strcat(ie,V);
[x1,fs1]=wavread(Stc);
figure,plot(x1);
title('Test Audio');
[pp1,pf1]=pitchauto(x1,fs1);
end
if (pp==pp1)
msgbox('Matching');
else
msgbox('Not Matching');
end
Kindly do reply with the correct answers.
You calculate a value for pp1 each time, do nothing with it, then let the next loop iteration overwrite it. To make use of it, either put the test inside the loop:
for ix=1:2
V='.wav';
ie=num2str(ix);
Stc=strcat(ie,V);
[x1,fs1]=wavread(Stc);
figure,plot(x1);
title('Test Audio');
[pp1,pf1]=pitchauto(x1,fs1);
if (pp==pp1)
msgbox('Matching', num2str(ix)); % show the index number as msgbox title
else
msgbox('Not Matching', num2str(ix));
end
end
or collect the values of pp1 in an array to test afterwards:
for ix=1:2
V='.wav';
ie=num2str(ix);
Stc=strcat(ie,V);
[x1,fs1]=wavread(Stc);
figure,plot(x1);
title('Test Audio');
[pp1(ix),pf1]=pitchauto(x1,fs1); % assuming pitchauto returns a scalar
end
matchidx = (pp == pp1);
if any(matchidx)
msgbox(strcat('Matching indices: ', num2str(find(matchidx))));
else
msgbox('Not Matching');
end
If the values aren't scalar, then this approach is a bit more difficult - you could still use a matrix to collect equal-sized vectors, or a cell array to collect anything - but it's probably easier to stick with the first approach in that case.