Force an Expression (%) in AutoHotkey for More Powerful Commands (Beginning Hotkeys Part 17)

Learn the Secret of Adding Power and Flexibility to AutoHotkey Commands—Use Forced Expressions to Tailor Almost Anything

Four years ago I wrote my first AutoHotkey article as part of a Windows column for ComputorEdge Magazine. (One of my readers introduced me to AutoHotkey.) The more I dug into the scripting language, the more I understood how, with very little effort, it could help virtually any Windows user. I took the path of studying the AutoHotkey online documentation, searching AutoHotkey forums for ideas and techniques, testing various ways to write the code, then chronicling my insights in what eventually became first a number of articles and blogs, then (mostly beginning) books.

ComputorEdge AutoHotkey E-Books*         *          *

This beginning Hotkey blog builds upon the discussions in the previous parts. If you find any of the information too confusing, then reviewing earlier blogs may be worthwhile.

New to AutoHotkey? See “Introduction to AutoHotkey: A Review and Guide for Beginners.”

*          *          *

I’m not a professional programmer, although I have dabbled in a couple of other languages. Therefore, my books do not come from the point of view of an expert, but rather someone who’s learning how to write an AutoHotkey script from scratch. In the process I ran into the same missteps and foibles that many beginners encounter.

Part of my trouble is that I look at a problem, then search for a solution—without necessarily understanding all the available AutoHotkey tools. Although I continually consult the excellent information at AutoHotkey.com, I have not read the online documentation from beginning to end. Exploring and testing the various tools, I get better at determining what to use when. As I learn what seem to be best practices, I pass them along—although in some cases it’s taken years for me to grasp key insights. This blog discusses one of those elusive concepts.

When I look back, I often wonder what I would have written if I knew then what I know now. I’m often tempted to go back and reexamine my previous efforts in an attempt to add my latest epiphanies. I have included many new tips (especially in the Beginner’s Guide), but inserting some of my more recent understandings, although important, would probably cause more confusion for the noobie than clarity. Many of these discernments are slightly more advanced AutoHotkey techniques and the novice reader won’t be ready for them.

This blog discusses one of those revelations inspired by an AutoHotkey feature which I now realize can bring my scripts to another level. When I recently decided to take another look at how and when to use forced expressions, I had no idea how the technique would influence my thinking. It all started this line of code from last time’s MousePrecise.ahk script:

SC052::Send % (toggle := !toggle) ? "{LButton Down}" : "{LButton Up}" 

This Hotkey consist of the zero key on the numeric keypad (keyboard Scan Code SD052) using the Send command to either hold down the left mouse button (LButton Down) or release the left mouse button (LButton Up)—depending upon the value of toggle. The evaluation of the expression is forced (see the heading “Force an expression”) through the use of the single percent sign % followed by a space (or tab). The remainder of the line is a three-part ternary expression (for discussion next time). This blog concentrates on that single percent sign % used to force an expression.

Is Forcing Expressions a Game Changer?

I must admit that it can take me a while to grasp the significance of particular AutoHotkey techniques. I might use them for years, routinely copying them from other scripts, but it is not until I take an in-depth look at how they work that their true importance sinks in. This review of forcing an expression inside an AutoHotkey command was one of those head slapping “Aha!” moments.

If you check out the online documentation for the Send command, you see no sign of this method for evaluating expressions inside the command’s syntax. (This is true for most other AutoHotkey commands.) Yet, in the code line above we find the Send command with the forced evaluation of the ternary operator (?:) acting as a toggle for clicking and holding down the left mouse button, then releasing it with the next Numpad0 key press.

It’s not that there isn’t plenty of information about how to force an expression or numerous examples throughout the documentation. The Variables page of the online documentation offers a number of uses for the technique:

FileAppend, % MyArray[i], MyFile.txt
FileAppend, % MyPseudoArray%i%, MyFile.txt
MsgBox % "The variable MyVar contains " . MyVar . "."
Loop % Iterations + 1
WinSet, Transparent, % X + 100
Control, Choose, % CurrentSelection - 1

And, it’s not that I didn’t understand how to force an expression. I’ve implemented it quite a few times and seen it in code even more. I just always understood the technique as an alternative method rather than an essential tool. I didn’t appreciate the full implications of this AutoHotkey tool for script writing.

The documentation doesn’t say, “Hey! Pay attention! This piece is really important!” In fact, the online explanation for force an expression (in ../Variables.htm#Expressions) seems to propose the feature as merely another way of evaluating variables. I’m not faulting the AutoHotkey online documentation. It offers everything you need to understand and use AutoHotkey. It would be impossible to cover all the various uses of AutoHotkey features—much less prioritize their importance. The commands are well presented, but the user must determine how and when to use them. The challenge is mixing and matching the tools in the most productive way—which isn’t always obvious. It least not for me.

Maybe the true power of forcing an expression isn’t emphasized as an AutoHotkey topic because it’s obvious to the smart people who regularly write programs and scripts. Or, possibly I became so consumed with other features that the technique became obscured. Regardless, I would guess that if for the last four years I missed the game-changing relevance of forcing expressions in AutoHotkey commands, then there could be a few others in the same boat. While the examples online are clear about how it works, what I’ve read does not reinforce the import of how forced expressions placed inside AutoHotkey commands can bring scripts to the next level. That’s now my job.

Forcing Expression Inside an AutoHotkey Command

Eventually, new AutoHotkey script writers reach a point where they want commands to do more. The improvements usually involve using variables to make changes in command parameters depending upon various conditions. Enclosing variables between two percent signs (%variable%) provides one of the most common methods for retrieving variable values and  tailoring AutoHotkey commands:

MsgBox, The value in the variable named Var is %Var%.

The beauty of this approach is that variables bound between % signs can appear almost anywhere within the command parameters any number of times:

FileAppend, x%x% y%y% w%Width% h%Height% `n, ToDoList.txt

In this example taken from the e-book AutoHotkey Applications, window parameters are supplied by including variables which make up the final format when the value is directly substituted for each of the macro variables enclosed with percent signs (e.g. w%Width% might be read by AutoHotkey as w360).

While this approach to adding outside values to commands is effective, it merely replaces the variable surrounded by the percent signs with the value of the variable. It is not an expression, nor can it evaluate an expression.

Using a forced expression with the first MsgBox example looks much more complex:

MsgBox, % "The value in the variable named Var is " . Var . "."

For the FileAppend line, code gets even longer:

FileAppend, % "x" . x . " y" . y . " w" . Width . " h" . Height . "`n", ToDoList.txt

 

(The code above must be read as one continuous line.)

Maybe the additional complication of enclosing text with quotes and using concatenation (dot with space on both sides) to create a single string expression causes people to shy away from the forced expression. However, there are many things that you can do with forced expressions which can’t be done with traditional double percent sign substitutions.

For example, placing a function inside the macro substitution format causes an error (%MyFunction()%). Since AutoHotkey is looking for a simple replacement, it won’t evaluate the function. Yet, the function will be evaluated within most commands by simply forcing its evaluation—% MyFunction().

Practical Forced Expressions

Most AutoHotkey commands initially appear straightforward with little room for outside options in the command syntax or structure. However, forced expressions throw the possibilities wide open.

As an example, a SplashImage command line from the blog on AutoHotkey Scan Codes, Speech, Sound, and Splash Images in Children’s Apps (Beginning Hotkeys Part 13) offers only one image option as written:

SplashImage, cow-skating.jpg, cwYellow ctBlue 
    , C IS FOR COW!, Is the cow laughing?
    , Laughing Cow

(This one line of code wraps into multiple lines for display purposes using AutoHotkey line continuation techniques. AutoHotkey reads it as one continuous line.)

But, what if we want to switch between two different images each time the SplashImage command runs. By replacing the image filename with a forced expression using the same toggle from the initial example, the switch becomes automatic:

SplashImage, % (toggle := !toggle) ? "cow-skating.jpg" : "Dancing Dogs.jpg"
 , cwYellow ctBlue
 , C IS FOR COW!, Is the cow laughing?
 , Laughing Cow

Now the Hotkey changes the image each time it is pressed. Want more images than those provided by the ternary operator? Write a function ChangeImage() which returns filenames based upon any conditions you specify (e.g. list order, random order):

SplashImage, % ChangeImage()
 , cwYellow ctBlue
 , C IS FOR COW!, Is the cow laughing?
 , Laughing Cow

Rules for Forcing an Expression in AutoHotkey Commands

Considerations when using forced expressions in AutoHotkey commands:

  • The percent sign % must be the first character in the parameter and followed by a space or tab.
  • The expression must account for the entire space between any two commas. The comma is an operator. When a comma is encountered, it marks the end of the expression. (Any comma inside a forced expression must be enclosed in quotes.)
  • Any text must be enclosed in quotes and merged with variables and other text with the concatenate operator (dot surrounded by spaces),
  • Forced expressions will not work within commands which already evaluate expressions such as If () statements. Generally, if parentheses are used to contain expressions, trying to force an expression with % will cause an error.
  • Forced expressions are not accepted as output variables (e.g. OutputVar) in AutoHotkey commands.

For me, the groundbreaking feature in my understanding of forced expressions is that they can appear multiple times within a command as long as they are separated by the parameter commas:

SplashImage, % (toggle := !toggle) ? "cow-skating.jpg" : "Dancing Dogs.jpg"
 , cwYellow ctBlue
 , C IS FOR COW!, Is the cow laughing?
 , Laughing Cow , % (font := !font) ? "Arial" : "Comic Sans MS"

In addition to the toggling images, a switch for the text and title font is included.

After first putting together this example, it dawned on me that almost any AutoHotkey command could be composed almost entirely of forced expressions which immediately adapt to the context of the running script. In the command above, the color scheme, the text, and the title might all be the result of forced expressions. I was looking at a single line solution to the problem of tailoring commands to conditions.

Suppose I wanted to increment any parameter in an AutoHotkey command? All I need is to increment a variable in a forced expression:

MsgBox % "The new value is " . numcount++ . "."

After setting an initial value for numcount (numcount = 0), the MsgBox counts up each time it runs. This technique could be useful with any AutoHotkey command which uses coordinates (e.g. WinMove, MouseMove, Click, etc ).

Tip: Both numcount++ and ++numcount increment the variable by 1. When the double plus ++ precedes the variable name, the value increments prior to the evaluation and displays the new value. When the ++ follows the variable name the value increments after the evaluation and displays the old value.

Even the type of Gui (Graphical User Interface command) field can be determined at runtime:

Gui, Add, % (field = 1) ? "Edit" : "Text", w375 vSpeakOutLoud

Some AutoHotkey commands can take up to seven or eight parameters (sections between commas). Most parameters will accept a forced expression. The possibilities boggle the mind.

Combining Traditional Variable Recall (%Variable%) with Forced Expression

You can continue using the standard double percent sign macro substitution (%Variable%) to retrieve the value of a variable. This helps when evaluating pseudo arrays as shown in one example from the online documentation:

FileAppend, % MyPseudoArray%i%, MyFile.txt

The value of the variable i is concatenated to the name MyPseudoArray making up the current variable name (e.g. MyPseudoArray0 MyPseudoArray1MyPseudoArray2), then evaluated (a technique often used within Loops). This combination of forced expressions and traditional double percent sign macro substitution makes complex evaluations much easier.

Can I Do It with a Forced Expression?

In the future when adding variables and conditions to my AutoHotkey commands, I’ll consider whether I can use a forced expression. In many cases, it may save me code and the writing of other subroutines or functions. I’m sure that just as often I’ll find no savings or extra help from the technique, but, at least, I’ll think about it.

It may seem like I’m making too big a deal out of forcing expressions, but there will come a time when you want an AutoHotkey command to change its output based upon a particular set of circumstances. You can usually do it by writing subroutines which run outside the command, but with forced expressions, you might be able to embed all the conditions and variables inside the same AutoHotkey command.

Next time, we look closer at the ternary operator shortcut.

 

Advertisements

4 thoughts on “Force an Expression (%) in AutoHotkey for More Powerful Commands (Beginning Hotkeys Part 17)

  1. This topic is mind boggling, hope you could explain again with real examples using force expression and with normal expressions method.

    Like

  2. You’re right! It is mind boggling.

    The problem with most AutoHotkey commands is that in their basic form the parameters do not accommodate expressions at all. That’s means without either the traditional double percent sign (%variable%) or another trick (i.e. forced expressions), there would be no way to alter command parameters while a script is running.

    As an example, assign this line from the blog to the Hotkey combination ALT+L (!l):

    !l::MsgBox % "The new value is " . numcount++ . "."

    Remember that numcount was set equal to 0 elsewhere in the script.

    Replicating the same action without the forced expression would require more lines of code:

    !::
    MsgBox The new value is %numcount%.
    numcount =: numcount +1 ;or numcount++
    Return

    Even here, use of the traditional double percent sign (%variable%) is required. Otherwise, the MsgBox command would only be able to return whatever is hardcoded in the script.

    You can do most of the same things both with and without forced expressions, but without forced expressions you would need external operations such as that shown above. Not only would it require more lines of code, but in many cases it could become more complex.

    Forced expressions are not always the right answer. In fact, I ultimately dropped the original toggle forced in the MousePrecise.ahk script which started this discussion in favor of a more comprehensive If conditional in the final version. (I will be discussing that change more in a later blog.) There are many cases where forced expressions just won’t do the job, but when they work, they are powerful.

    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 )

Google+ photo

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

Connecting to %s