Create a Universal MsgBox Print Function with ControlGetText (AutoHotkey Tip)

When Nothing Else Works for Copying Text, Try the ControlGetText Command and Create a Global MsgBox Print Function

In a previous blog, I highlighted the Control, EditPaste command. The command helped me solve a particular problem where the standard Send, ^v (Windows paste shortcut) responded too slowly. I’ve since discovered that the complementary ControlGetText command resolves some sticky MsgBox printing troubles. It not only works quicker than the Windows copy shortcut (Send, ^c) but it greatly reduces code.

A Print Problem

The issue cropped up when I expanded the cheeseburgerwhiteiconCheeseburger.ahk script to include both a Cheeseburger Animal Style and a mixed recipe Jack Stuffed Cheeseburger (Animal Style). The increased complexity of the PrintItem() function for outputting individual recipe steps added too many extra lines of code—and only looked to get worse.

megadeal180goldI haven’t previously discussed the PrintItem() function because of all the complications involved with using the MsgBox Help button for printing. A number of issues needed resolving:

  1. The MsgBox Help button uses an OnMessage() function. A function’s variables are local and independent of the previously defined variable—unless set as global.
  2. The function used with the MsgBox Help button doesn’t accept variable data passed as a parameter.
  3. The standard CTRL+C copy shortcut for a Windows Message Box does not work properly within the Help button OnMessage() function.

My first solution involved declaring each recipe step variable Global in the auto-execute section of the script and adding a conditional routine to the PrintItem() function for each recipe step:

Global Ingredients
Global Mix
Global Cook
Global Serve

The Global command makes external variables available inside functions.

Next, I needed a method for printing the appropriate step from the recipe:

IfWinActive, Jack Stuffed Cheeseburger - Ingredients
  Task := Ingredients
IfWinActive, Jack Stuffed Cheeseburger - Prepare
  Task := Mix
IfWinActive, Jack Stuffed Cheeseburger - Cook
  Task := Cook
IfWinActive, Jack Stuffed Cheeseburger - Serve
  Task := Serve

WinGetActiveTitle, Title
FileDelete, RecipePrint.txt
FileAppend, %Title%`r`r%Task%, RecipePrint.txt
Run, Notepad /p RecipePrint.txt

The IfWinActive command identifies the active window and sets the variable Task to the proper Global variable containing the text for the recipe step. Saving Task to the RecipePrint.txt file, the script uses the Windows Notepad print technique discussed in “Printing with AutoHotkey Made Simple (AutoHotkey Tip)” to output the variable to paper.

While none of these steps are complicated, the amount of code gets fairly long—especially when you add two more recipes to the same script. I needed to find a simpler way to print individual recipe steps without setting each variable as Global, then identifying and repeating it within the function.

Note: When I start out writing code, such as the above snippets for printing a step in the Cheeseburger.ahk script, I tend to think in terms of solving problems rather than producing the shortest, most elegant routine. Initially, I strive to get something (anything) working. Later, when I realize that the code’s getting too convoluted—as is the case here—I look for other approaches which work better—such as the one offered below. No one gets everything right the first time. In fact, any script can go through a number of iterations in the quest for efficiency. There’s nothing wrong with that. It’s part of the normal scripting process.

CTRL+C Fails Inside PrintItem() Functions

My first thought was to copy the text directly from the active MsgBox. From the online AutoHotkey documentation for the MsgBox command:

Tip: Pressing Control-C while a MsgBox window is active will copy its text to the clipboard. This applies to all MsgBoxes, not just those produced by AutoHotkey.

I’m not sure why, but, within the OnMessage function (discussed in “Tips for Optimizing the Standard AutoHotkey Message Box (MsgBox) Command (AutoHotkey Quick Reference Part Six)“), using the Windows copy command (Send, ^c) for saving the text from a Windows Message Box to the Clipboard doesn’t work with the MsgBox Help button (OnMessage()). This certainly would have simplified the print routine.

Eventually, my research uncovered the ControlGetText command which copies the text contained in any specified Windows control. This AutoHotkey command works in many situations where either the standard copy command (CTRL+C) won’t do or when you need to eliminate its inherent delays:

ControlGetText, OutputVariable, [ControlName] , A  ; (A)ctive window

If not specified in ControlGetText command, AutoHotkey uses the first control encountered. In many cases, leaving the control name blank won’t work since it may not be the needed EDIT or TEXT control. Identify the control name with Window Spy (right-click on the AutoHotkey (filename.ahk) System Tray icon and select Windows Spy from the menu). For the MsgBox, the text control name is Static1.

Adding the ControlGetText command to the PrintItem() function eliminated the need for Global variables, passing data to the function, and the problem with a non-functioning CTRL+C shortcut:

   WinGetActiveTitle, Title
   ControlGetText, Step, Static1, %Title%
   FileDelete, RecipePrint.txt
   FileAppend , %Title%:`r`r%Step%, RecipePrint.txt
   Run, Notepad /p RecipePrint.txt

What started with 19 lines of codes (and threatened to add many more lines with each new recipe), dropped to five lines with no further expansion required—ever. The function PrintItem() acts as a global routine for printing text from any active MsgBox window. It works whether used with the MsgBox Help button OnMessage() routine or separately for any other active message box. In fact, you can just as easily turn the routine into a Label subroutine for use in virtually any script or a Hotkey combination for printing the text in any Windows Message Box which pops up on your computer.

You could say that I lucked out when CTRL+C didn’t operate inside the MsgBox Help button OnMessage() function. It forced me to look for another approach just to get the job done. Who knew that it would be such a great improvement?

Maybe I should have known to use the ControlGetText command in the first place, but remembering the multitude of AutoHotkey commands presents a challenge to any script writer. That’s why coders often proceed down more complex paths to get a result. When I find that things are getting too complicated, I start doing a little more research. I sometimes uncover a hidden gem such as the ControlGetText command which elegantly solves a coding problem. While not the solution for every text copy issue, in this case, the command turned a tedious set of tailored command lines into a universal print tool.

*          *          *

Like anybody else, I have expenses and a need to make ends meet. As “Jack’s AutoHotkey Blog” increases in popularity, coding the test scripts and writing the blogs takes up more of my time. That means I’ve less time to pursue other income earning opportunities. I don’t plan to ever move “Jack’s AutoHotkey Blog” behind a paywall, but if you think my efforts are worth a bit of your hard-earned cash, then you can offer a token of your appreciation by purchasing some of my AutoHotkey books. You may not need the references yourself, but you might know someone who can benefit from one or two of them.

Thank you,



Leave a Reply

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

You are commenting using your 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