Understanding AutoHotkey %Var% Variable Text Replacement (AutoHotkey Tip)

Handy Window Transparency Wheel Using Macro Replacement Quickly Peeks Under a Window without Moving It, Plus the Difference Between % Var and %Var% Made Easy

The AutoHotkey online documentation goes into great detail about the traditional method for retrieving values from variables (%Var%) and the force expression evaluation method (% Var). It can take the new AutoHotkey user a little while to comprehend the differences between the two. In an effort to clarify the variations and help beginners to understand when to use which method, I offer an alternative way to view the operations. For the traditional method, I prefer using the terms macro substitution or variable name replacement. Once, you understand how it works, differentiating when and how to use each technique becomes easy.

The value-added trick comes when creating variables containing new variables on-the-fly by combining the two methods (i.e. forcing an expression % which contain a %Var% variable name replacement). The first step involves replacing the variable with its value, the new variable name (%Var%). The second step requires the forced evaluation of the new variable (% VarValue) as part of an expression.

*          *          *

Volume Control
Volume Wheel

A while back I installed a volume control operated by the mouse scroll wheel. Simply hover over the Windows Task Bar and scroll the mouse wheel up or down to adjust the PC speaker volume level higher or lower, respectively. A progress bar (shown at right) pops up displaying the changing volume level. I’ve added this convenient tool to my standard AutoHotkey script and use it all the time.

Tranparency Menu
Transparency Menu

At a later date, while playing with window visibility, I set up a menu for changing the transparency level for the active window (shown at left). At the end of that blog, I suggested, “If you want to get really fancy, then you might use the mouse wheel to set the transparency (or opaqueness) level.” I’ve done just that with my new SeeThruWinWheel.ahk script. Now, by holding down the CTRL key while scrolling the mouse wheel, the window under the mouse cursor becomes less opaque (WheelDown) or more opaque (WheelUp). In the course of writing this short script, I implemented a number of AutoHotkey tricks worth discussing.

I plan to cover the following AutoHotkey tips with this new script:

  1. How to use variables to store variable names (or combining % Var forced expressions with %Var% variable name replacement).
  2. Use Styles/ExStyles to detect conditional changes in a window.
  3. Take advantage of Label name drop-through characteristics to reset Hotkeys.

Over the next couple of blogs, I dissect this script line by line, but for a preview, take a look at the new script:

Control & LButton::
 MouseGetPos,,, currentWindow
 %currentWindow% := 255

Control & WheelUp::
 MouseGetPos,,, currentWindow
 if not (%currentWindow%)
 {
  GoSub GetTransparent
 }
 if (%currentWindow% < 255)
 {
  %currentWindow% += 5
 }
 WinSet, Transparent, % %currentWindow%, ahk_id %currentWindow%
 SplashImage,,w100 x0 y0 b fs12, % %currentWindow% 
 SetTimer, TurnOffSI, 1000, On
Return

Control & WheelDown::
 MouseGetPos,,, currentWindow
 if not (%currentWindow%)
 {
  GoSub GetTransparent
 }
 if (%currentWindow% > 5)
 {
  %currentWindow% -= 5
 }
 WinSet, Transparent, % %currentWindow%, ahk_id %currentWindow% 
 SplashImage,, w100 x0 y0 b fs12, % %currentWindow%
 SetTimer, TurnOffSI, 1000, On
Return

GetTransparent:
 WinGet, ExStyle, ExStyle, ahk_id %currentWindow%
 if (ExStyle & 0x80000) ; 0x8 is WS_EX_LAYERED.
 {
  WinGet, TransLevel, Transparent, ahk_id %currentWindow%
  %currentWindow% := TransLevel
 }
 else
  %currentWindow% := 255
Return

TurnOffSI:
 SplashImage, off
 SetTimer, TurnOffSI, 1000, Off
Return

Note: Years ago I highlighted a script from the AutoHotkey forum which executed always-on-top, plus Hotkeys to change window transparency and click-through-ness. I intended to start with that script and make a few improvements, but I found so many problems in the script that my version now reflects very little from the original. However, one important technique which uses variables to store other variable names (sometimes called macro replacement) remains as an important method for tracking window data—in this case, the transparency level.

First, let’s review how the mouse makes changing the window transparency level (opaqueness) easy.

Using the Mouse in Hotkey Combinations

The script contains three Hotkey combinations: Control & WheelUp, Control & WheelDown, and Control & LButton. Each uses the mouse in combination with the CTRL key. Since it’s natural to change levels continuously, it makes sense to use the scroll wheel rather than a regular Hotkey combination.

Plus, by using the MouseGetPos command, the target window no longer needs to be the active window. Merely hovering over the window allows AutoHotkey to grab the window’s unique ID:

MouseGetPos,,, currentWindow  ; captures window ahk_id

Note: By capturing the unique ID (ahk_id) for each window, the script uses that value as a new variable name to store the transparency level. This trick makes the tracking of individual levels for different windows possible.

You can peek under any window covering another spot on the screen by increasing the window transparency (decreasing opaqueness) without clicking on it.

TransparentWindow
As the mouse wheel scrolls down while pressing the Control key, the transparency of the image windows increases (the opaqueness decreases) allowing the printing on the window underneath to appear. The current transparency value appears in the upper right-hand corner while scrolling the mouse wheel.

Scrolling down while holding down the CTRL key decreases the visibility of the window allowing the user to see through it. Scroll up to reverse the process. Reset the window to totally opaque with CTRL+LButton (left mouse button).

An added plus for this script includes a trick for tracking and saving the transparency level for an unlimited number of windows. The script uses a common technique for instantly creating a unique variable for each window containing the current visibility level. That means you can adjust one window, then another, and go back to the original without losing its last level. AutoHotkey knows the transparency level for each adjusted window. AutoHotkey does this by combining force expressions (%) with tradition variable replacement (%Var%).

Using Variables Containing Variable Names

When I first reviewed the old script, confusion set in. The same variable, currentWindow, seemingly gets used over and over again for different purposes. When I looked at the line:

WinSet, Transparent, % %currentWindow%, ahk_id %currentWindow%

I thought that currentWindow couldn’t possibly work in two positions in that same line of code. However, the variable currentWindow gets used in two different ways. To understand the difference between the two, you need to understand the difference between evaluating an expression (%  forced expression) and replacing a variable with its value (enclosing the term between two percent % signs).

(I wrote extensively about forcing expressions in the blog “Force an Expression (%) in AutoHotkey for More Powerful Commands (Beginning Hotkeys Part 17)“—now included in the book AutoHotkey Hotkey Techniques.)

Variable Evaluation (% Var) Versus Variable Text Replacement (%Var%)

This topic can get pretty confusing—especially for anyone new to script writing. When do you want to force the evaluation of an expression (% Var) and when do you want to replace a variable with its contents (%Var%)? Plus, how do you combine them? To understand when to use what, we need to first understand what each technique does.

The difference lies in the fact that while % Var actually evaluates the variable as part of an expression, while the %Var% operation merely replaces the variable name with its contents. Once you get it into your head that %Var% only replaces itself in a line of code with its text value, its use becomes clear.

Think of AutoHotkey as executing two passes each time it reads a line of code:

  1. AutoHotkey reads the entire line replacing all occurrences of traditional text variables (%Var%) with their individually stored values.
  2. AutoHotkey executes the command using the newly substituted text (or variable names when evaluating expressions—if any).

For example, in the following snippet:

Test := A_Now
%Test% := "yes"
MsgBox, % %Test%

TestMsgBoxThe first line of code saves the current date/time stamp (A_Now, e.g. 20170510102343) to the variable Test. The next line creates a new variable with the value of Test (%Test%) and saves the text value “yes” to it. Then, in the third line of code, AutoHotkey first replaces %Test% with its value, then executes the MsgBox command while evaluating the expression using the value of Test as the variable.

In other words, in the second line of code, AutoHotkey first replaces the %Test% operator with the contents of that variable. If we could see the code after this first pass, the variable replacement, but prior to command execution, it might look like this:

20170510102343 := "yes"

For this example, the actual variable name after the replacement becomes 20170510102343.

Next, the MsgBox command line does the same first pass %Test% replacement, then executes while forcing evaluation of the expression (% 20170510102343)—displaying the variable contents “yes”:

MsgBox, % 20170510102343

While we never see the hidden variable name, we get the right result. If the MsgBox line did not contain the %Test% replacement format or the forced expression operator %, MsgBox would merely display “20170510102343″ in the pop-up. Understand that prior to processing the command, AutoHotkey replaces the variable name,  %Test%, with its contents in text format.

Note: Normally you should not create a variable name with all numeric digits because within any expression, rather than evaluating the variable itself, AutoHotkey would deem it a number and operated upon it accordingly. However, using the %Var% replacement format allows the evaluation of an all digit variable since the operation treats the replacement variable name as text.

While limits on where you can use the %Var% type of variable name replacement exist (i.e. not as an AutoHotkey command itself), AutoHotkey allows many other opportunities to change names on the fly. For example, this replacement technique even works for dynamically calling functions:

FunctionName = InStr
%FunctionName%(Para1,Para2) ;calls the InStr() function

AutoHotkey dynamically reads the second line as InStr(Para1,Para2) just prior to execution.

As an example of its use, in the SeeThruWinWheel.ahk script, the SplashImage command pops up a display in the upper left-hand corner of the screen reporting the transparency level:

SplashImage,,w100 x0 y0 b fs12, % %currentWindow%

Assuming that the script saved the unique currentWindow name for the window under the mouse as 0x206e2, AutoHotkey pulls the previously saved transparency level (e.g. %currentWindow% := 255) from the variable by replacing %currentWindow% with its value in the first step, then executing the SplashImage command with the following forced expression:

SplashImage,,w100 x0 y0 b fs12, % 0x206e2

AutoHotkey never actually displays the variable name 0x206e2 nor shows it in the script. It remains hidden inside currentWindow. (For the curious, you can use MsgBox, %currentWindow% to view the variable name for the current window’s transparency level. Maybe put it in another Hotkey.)

For the purpose of demonstrating this important window visibility tracking technique, we look at the line:

WinSet, Transparent, % %currentWindow%, ahk_id %currentWindow%

After the %currentWindow% macro text replacement, AutoHotkey might see the line of code as:

WinSet, Transparent, % 0x206e2, ahk_id 0x206e2

The expression operation 0x206e2 evaluates to the current transparency level.

As long as you remember that the %Var% substitution method merely replaces a variable name with the text contained in the variable prior to command execution, then you should have no trouble remembering when to use it.

Note: In this case, reading the online AutoHotkey documentation may add to the confusion. I found some of it to be misleading, especially with respect to using %Var% within command parameters which accept expressions.

For backward compatibility, command parameters that are documented as “can be an expression” treat an isolated name in percent signs (e.g. %Var%, but not Array%i%) as though the percent signs are absent. This can be avoided by enclosing the reference in parentheses; e.g. Sleep (%Var%).

I found this not to be the case. My approach to macro replacement behaved consistently and worked fine as long as any replacement variable contained a previously defined value:

%Var% := 25
Array%i% := 500

The problem occurs when AutoHotkey attempts to evaluate an expression with an undefined variable. Nor, does Sleep (%Var%) work unless you assign a value to %Var%.

Look upon the use of %Var% as merely macro text replacement which may act as inserted text or may perform as a variable in an expression. Then it starts making sense.

jack

 

 

 

2 thoughts on “Understanding AutoHotkey %Var% Variable Text Replacement (AutoHotkey Tip)

  1. I feel like this mostly makes sense. The one confusion I have is where you see a lot of scripts printing the clipboard using Send, %clipboard%.
    It seems like that shouldn’t work, rather it should be Send, % clipboard (which also works).
    Does this discrepancy have a simple explanation I’m missing.

    Like

    • It’s not a discrepancy. The %var% format merely inserts the value of one variable (var) into the command as text. The % expr forces the evaluation of the expression expr which may contain any number of variables, array variables (e.g. array[1]), functions, and operators.

      In your example, the first %clipboard% inserts the contents of the clipboard. In the second case, % clipboard evaluates the variable clipboard and returns the results— which in this case happens to be the same thing.

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s