How to concatenate string and variable in autohotkey v2? - autohotkey

Here's a piece of code that works in v1:
Var1 := "Example"
%Var1%Variable := "Concatenated Variable"
MsgBox % ExampleVariable
This syntax however seems to be removed from v2. Is there any way I can do this in v2?

Related

Folding the variable name

I want to folding tha variable name
code
numberOfInstNext := Array("","","","","","","","","","","")
numberOfInstNext[1] := 777
i := 1
I tried
msgbox %numberOfInstNext[i]%
error:
The following variable name contains an illegal character 'numberOfInstNext[i]'
Expressions says
An expression can be used in a parameter that does not directly
support it by preceding the expression with a percent sign and a space or tab.
This technique is often used to access arrays.
msgbox % numberOfInstNext[i]
I find the easiest and most scalable solution is to just assign a tmp variable each time you want to access an indexed array.
tmp := numberOfInstNext[i]
msgbox the value is %tmp%!

Autohotkey IniRead pass section name as variable in AHK

I have the following tiny .ini file:
["General"]
"runs"="3"
When using this code to read the file, I get a message box stating the correct number of runs
path := A_ScriptDir "\setup.ini"
IniRead, temp, % path, "General", "runs"
MsgBox, % temp
When I try to pass General as a variable, the message box outputs "ERROR"
path := A_ScriptDir "\setup.ini"
iniSection := "General"
IniRead, temp, % path, % iniSection, "runs"
MsgBox, % temp
I tried enclosing the variables in %-signs, instead of just prefixing them, but it does not make a difference.
Any help is appreciated!
Variable names in an expression are not enclosed in percent
signs. Consequently, literal strings must be enclosed in double
quotes to distinguish them from variables.
To include an actual quote-character inside a literal string, specify
two consecutive quotes:
iniSection := """General"""

AHK How to pass variables to "Run" inside a function?

I'm fairly new to autohotkey and ran into a problem recently when trying to pass variables as parameters for the "run" command in autohotkey. Can anyone show me what I'm missing or is this a bug?
Gui, Setup:Add, Edit, w100 vProgram
Gui, Setup:Add, Button, Default w100 gSubmit, OK
Gui, Setup:Show,, Setup
WinWaitClose, Setup
ExitApp
Submit:
Gui, Setup:Submit
RunStuff()
RunStuff() {
Run, %Program%
}
I've even tried changing the line to this:
RunStuff() {
run, Program
}
I would really appreciate the help, thanks in advance.
First things first, while
WinWaitClose, Setup
ExitApp
Is maybe smart thinking, you're supposed to do this with the GuiClose event by just defining a function (or a label) with the name GuiClose.
GuiClose()
{
ExitApp
}
Also, giving the gui a name is redundant, although if you're planning on adding more guis, fair enough.
And to run cmd commands, you'd start off cmd with the /c(docs) switch.
Your example netsh wlan connect ssid=%networkname% name=%networkname% would be done like this:
networkname := "name"
Run, %A_ComSpec% /c netsh wlan connect ssid=%networkname% name=%networkname%
Run, % A_ComSpec " /c netsh wlan connect ssid=" networkname " name=" networkname
The first line is in legacy syntax, I wouldn't really recommend it.
The second line is in expression syntax.
The built in variable A_ComSpec(docs) contains the path to cmd.exe.
Example program based on your code to open a file in notepad:
Gui, Setup:Add, Edit, w300 vFilePath, % "C:\Users\User\Desktop\this is a text file.txt"
Gui, Setup:Add, Button, Default w100 gSubmit, OK
Gui, Setup:Show, , Setup
return
Submit:
Gui, Setup:Submit
Run, % "notepad.exe """ FilePath """"
return
GuiClose()
{
ExitApp
}
Note how the file path includes spaces, so the argument needs to wrapped in quotes.
"""" may seem weird, but a quote is escaped with another quote in AHK. So outer quotes specify that you're writing the string, and inner "" is just one quote escaped. So this produces ".
Legacy syntax vs modern expression syntax can be a bit confusing when you're learning AHK. You'll see a lot of legacy syntax when you look up stuff. This is mainly because AHK was much more popular years and years ago (when legacy syntax was the thing to use).
To get started off on the legacy vs modern expression differences, here's a pretty good documentation page:
https://www.autohotkey.com/docs/Language.htm
EDIT:
Answer to the new problem that as added in via an edit to the OP.
RunStuff() {
Run, %Program%
}
The variable Program is not defined in the function's scope.
Lets consider this example code
var1 := 1
var2 := 2
global var3 := 3
function()
return
function()
{
global var2
MsgBox, % "var1: " var1 "`nvar2: " var2 "`nvar3: " var3 "`n"
}
var1 is not defined in the function's scope, so nothing will be printed in the message box.
var2 will be used from outside the function's scope because of the line global var2.
var3 would also be used from outside of the function scope because var3 was defined as super global. Super global isn't really recommended, because anything anywhere will use that variable then. Quite easy to run into problems on larger scripts, but it's convenient for smaller scripts where you know what you'll be doing and don't have any external libraries for example.
You can read the related documentation from here:
https://www.autohotkey.com/docs/Functions.htm#Locals
It seems that you think your problem is with the gui output.
I think you might want to check things in a different way:
You could create a script to analyze the your run inputs.
For example:
Script #1, let's call it "1.ahk"
Run, 2.ahk param1 param 2 "param 3"
Script #2, let's call it "2.ahk"
txt := "Params as seen by ahk:`n"
for i, param in A_Args
txt .= i " = " param "`n"
MsgBox % txt
By running script "1.ahk" you can see the message that "2.ahk" creates:
Params as seen by ahk:
1 = param1
2 = param
3 = 2
4 = param 3
Which I think it's quite telling about how it understands spaces, and how quotes prevent splitting arguments.
Now if you run your gui outputs against "2.ahk" you might see something different to what you saw before.
RunStuff() {
Run % start "" "C:\blabla\prog.exe" -windowstyle minimized
}

How can AutoHotkey instance variables be used in WinTitle parameters?

Let's say I have a function to get the window title of a process using its HWND id:
GetWindowTitle(hwnd) {
WinGetTitle, title, ahk_id %hwnd%
return title
}
So far, so good. It works like a charm. So, let's say I am trying to wrap some functionality within a class, in this fashion:
class RunningProcess {
hwnd := ""
windowTitle := ""
__New(hwnd) {
this.hwnd := hwnd
this.windowTitle := GetWindowTitle()
}
GetWindowTitle() {
WinGetTitle, title, ahk_id %this.hwnd%
return title
}
}
The aforementioned code fails to load with the following message:
The following variable name contains an illegal character: "this.hwnd".
I have tried several alternatives in order to use the instance variable hwnd as a WinTitle argument in WinGetTitle, to no avail. The only one that works for me involves using a local variable which grabs the contents of this.hwnd and then using the local variable as a WinTitle argument, like this:
GetWindowTitle() {
foo := this.hwnd
WinGetTitle, title, ahk_id %foo%
return title
}
However, this is less than ideal, as you might guess, at least in my opinion.
Is there a way to use this.hwnd as a WinTitle argument right off the bat?
Thanks!
I'd call it a classic case of having trouble with the legacy vs modern expression syntax.
Refreshing to see it this way though, usually people with the issue are writing 2007 level AHK, but nice to see you're writing modern AHK.
So anyway, forget about using %% to refer to variables. That's the legacy AHK way. In a modern expression statement you just type the name of the variable to refer to is, for example your assignments with the := operator are just fine that way, because it's using the modern expression syntax (= to assign would be the legacy way)
However, pretty much all commands, that haven't been replaced with more modern function, still use the legacy syntax on every parameter (unless otherwise specified in the documentation).
So, you're going to have to set the parameter to evaluate an expression, instead of expecting a legacy text parameter. To do that, you start off the parameter with a single % followed up with a space.
So your WinGetTitle command should look like this:
WinGetTitle, title, % "ahk_id " this.hwnd
Quotation marks around ahk_id , because that's how you specify a string in an expression, and then just type in the variable you want to concatenate to that string. The concatenation operator . could be used here like so % "ahk_id " . this.hwnd, but it's totally redundant and looks weird in my opinion as well.
Also, your call to the GetWindowTitle() function in the initializer __New is going to need a this. in front of it.
And initializing the instance variables to nothing is redundant as well. You can remove that if you want.
Finished product:
MyCoolObject := new RunningProcess(WinExist("A"))
MsgBox, % "The handle of currently active window is: " MyCoolObject.hwnd "`nAnd its title is: " MyCoolObject.windowTitle
class RunningProcess
{
__New(hwnd)
{
this.hwnd := hwnd
this.windowTitle := this.GetWindowTitle()
}
GetWindowTitle()
{
WinGetTitle, title, % "ahk_id " this.hwnd
return title
}
}
To learn more about legacy syntax vs expression syntax, see for example this page from the documentation:
https://www.autohotkey.com/docs/Language.htm

autohotkey if statement with and without curly braces

I don't understand the difference between Autohotkey's If and If(...)
According to everything I have found, If(...) behaves as "expected" but there is something not working with my code.
Below does not work. It seems the statement in the If is never evaluated, %TimeString% is never set and nothing is output:
CapsLock & T::
Input Key, L1
If (Key=T)
{
FormatTime, TimeString,, HHmm
}
Send %TimeString%
Below does work, %TimeString% is set and the time is output.
CapsLock & T::
Input Key, L1
If Key=T
FormatTime, TimeString,, HHmm
Send %TimeString%
Autohotkey has two different syntaxes: legacy and expression. This also affects the if statement.
When you use parenthesis, if (expression) is used and Key is compared to the variable T which doesn't exist and is the same as an empty variable which doesn't equal T. You need to changed it to If (Key="T") and then it will compare the variable Key to the String "T" and it will work.
In the second case you're using the traditional(legacy) If which compares the variable Key to the String T and because they are equal, it works.
The curly braces { } just define a block, they do nothing and change nothing when your block contains only one line.
Are you sure this code is identical to your script? Beause
Tjs := T
if (Tjs=T)
{
MsgBox true
}
works fine for me.