In AutoHotkey V2.0, GUI Pop-up Windows Turn into Objects, Plus Replacing the Lost V1.1 gLabel
I’ve converted a few of the simpler AutoHotkey scripts on the ComputorEdge Free AutoHotkey Script page (AddDate.ahk, EggTimer.ahk, and LaunchWindow.ahk) from V1.1 to the latest alpha version of V2.0. As I convert and post the new .ahk2 scripts, you can identify them by the (v1,v2) found to the right of the script name in the Download Index.
These V2.0 scripts won’t run with the current version of AutoHotkey (V1.1). I set up my system to run AutoHotkey 1.1 and AutoHotkey 2.0 simultaneously per my blog “How to Fool Around with the New AutoHotkey Version 2.0.”
I write this current series of blogs comparing the current V1.1 with the future V2.0 as part of my exploration into how AutoHotkey may change. I say may change because I have no idea how long before the full release of V2.0. Even then, no one needs to make the upgrade. You can continue using V1.1 as long as you like. With such a large user base, I don’t see V1.1 going away anytime soon.
Having said that, you’ll discover numerous required alterations while reformatting the traditional commands into the new functions. I don’t see many changes occurring in the parameters and options for the various commands, but shifting to V2.0 will affect how you think about writing scripts. Beyond basic Hotstrings and Hotkeys, the new version introduces Object Oriented Programming (OOP) making it mandatory. (Yeah, I know,…it looks like Greek to me, too. But, we’ll get there…eventually.)
AutoHotkey Objects
We talked about the AutoHotkey’s basic object data type, the associative array, in the blog “Using Associative Arrays to Solve the Instant Hotkey Data Recall Problem.” AutoHotkey V2.0 introduces additional objects in the form of GUI objects and Menu objects which replace the GUI command and Menu command in V1.1, respectively. While you’ll find a lot to digest in AutoHotkey objects, we’ll take it a little bit at a time.
First, before you can use an object, you must create it. For GUI objects use:
GuiObj := GuiCreate(Options, Title := A_ScriptName, EventObj)
In its simplest form, we can name and create the new GUI using:
MyNewGui := GuiCreate()
This barebones form of the function serves two purposes. First, it creates the GUI object. Without this step, nothing else works because the object won’t exist.
Second, the command line names the GUI (MyNewGui or any other name). In AutoHotkey V1.1, the Gui command does not require a name. If you use the Gui, New command, AutoHotkey automatically creates a unique GUI—making it the default GUI. However, assigning an optional name makes conflicts between GUIs much less likely (especially when combining different scripts in a larger file). When creating a new GUI in V2.0, using a unique name for the GUI object (related to its purpose) may save you conflicts in the future.
Converting the AddDate.ahk Script MonthCal GUI Control to V2.0
One of my first tests involved converting the MonthCal GUI control in the AddDate.ahk script—used to insert the MonthCal GUI selected date (formatted month day, year, e.g. January 24, 2018) into any document or text editing field. While many of the traditional AutoHotkey commands quickly converted to the new V2.0 function format, the Gui command offered a bit more of a challenge.
In addition to the required creation of the GUI object, the script must declare the GUI name, plus all variables, Global for use in the called function (as discussed last time). While I found a number of different methods for getting the desired result, V2.0 ultimately required a few more lines of code.
When rewriting the following V1.1 AddDate.ahk script for AutoHotkey V2.0, only two lines don’t require modification (the Hotkey combination and the first Return command):
^#!d:: DetectHiddenWindows, On IfWinNotExist, Select Date { Gui AddDate:Add, MonthCal, vDayPick Gui AddDate:Add, Button, Default, Submit } Gui AddDate:Show,, Select Date DetectHiddenWindows, Off Return AddDateButtonSubmit: ; Label for the above Hotkey (^#D) Gui AddDate:Submit FormatTime, DayPick, %DayPick%, MMMM d, yyyy SendInput, %DayPick% Return
Comparing the new V2.0 script below with AddDate.ahk2 example posted on the Free AutoHotkey Script site, you’ll notice a number of differences. They both work but the sample found here uses less code. Which approach you might use depends on your situation. The AddDate.ahk2 script which runs with AutoHotkey V2.0 follows:
^#+d:: DetectHiddenWindows "On" If WinExist("Select Date") = 0 { Global AddDate AddDate := GuiCreate("AlwaysOnTop","Select Date") AddDate.Add("MonthCal", "vDayPick") AddDate.Add("Button", "Default", "Submit") .OnEvent("Click", "MyBtn_Click") } AddDate.Show DetectHiddenWindows "Off" Return MyBtn_Click() { Date := AddDate.Submit() TimeString := FormatTime(Date["DayPick"],"MMMM d, yyyy") SendInput TimeString }
I changed the Hotkey combination slightly (^#!d ⇒ ^#+d) to prevent conflicts when running the two different version scripts side-by-side.
Change Commands to Functions
The AutoHotkey V1.1 command:
DetectHiddenWindows, On
converts to the V2.0. function (with hidden parentheses):
DetectHiddenWindows "On"
which you can also format in V2.0 as:
DetectHiddenWindows("On")
Lose the comma and add the quotes.
Replace Deleted V1.1 Commands
The IfWinNotExist command disappears from V2.0 in favor of If (expression).
IfWinNotExist, Select Date ; V1.1 command
turns into:
If WinExist("Select Date") = 0
Make Local Variables Global
In AutoHotkey V2.0, declare the required object name Global:
Global AddDate
This makes the GUI object available in all called functions which would normally treat it as a local variable. However, if you only use one or two functions, then placing the command Global inside each function serves the same purpose.
Create the GUI Object
Before you can add anything to a GUI in AutoHotkey V2.0, you must first create it:
AddDate := GuiCreate()
The script can separately set the GUI title with:
AddDate.Title := "Select Date"
Or, you can just as easily include the title when creating the GUI object:
AddDate := GuiCreate( ,"Select Date")
Notice the single comma inside the parentheses. That comma delimits the GUI options such as AlwaysOnTop which you can add to the GuiCreate() function:
AddDate := GuiCreate("AlwaysOnTop" ,"Select Date")
You can also use the Gui.Opt() function to set options:
AddDate.Opt("AlwaysOnTop")
Add GUI Controls
In its simplest form the V1.1 Gui, Add commands:
Gui AddDate:Add, MonthCal, vDayPick Gui AddDate:Add, Button, Default, Submit
convert to the functions:
AddDate.Add("MonthCal", "vDayPick") AddDate.Add("Button", "Default", "Submit")
The new V2.0 functions look remarkably similar to the V1.1 commands—merely placing the parameters inside parentheses between quotation marks and separated by commas. Since we created the GUI object with the name AddDate, we only need to that object name with the Add() function (AddDate.Add()) appended.
When clicking the Submit button, AutoHotkey V1.1 assumes a gLabel with the name AddDateButtonSubmit for launching a subroutine. The GUI gLabel option no longer exists in V2.0. Alternatively, V2.0 uses the Gui.OnEvent() function (from the online documentation):
MyBtn := Gui.Add("Button", "Default", "OK") MyBtn.OnEvent("Click", "MyBtn_Click")
The OnEvent() function designates the event (Click) and the function called (MyBtn_Click) upon a click of the button. I found that I could express the function in one line:
AddDate.Add("Button", "Default", "Submit") .OnEvent("Click", "MyBtn_Click")
(The code above uses line continuation to word wrap for display purposes only.)
OnEvent Function
We replace the AddDateButtonSubmit V1.1 Label subroutine with the corresponding V2.0 function:
AddDateButtonSubmit: Gui AddDate:Submit FormatTime, DayPick, %DayPick%, MMMM d, yyyy Send, %DayPick% Return
converts line-by-line to a function:
MyBtn_Click() { Date := AddDate.Submit() TimeString := FormatTime(Date["DayPick"],"MMMM d, yyyy") SendInput TimeString }
The AddDate.Submit() function creates the associative array Date (another object) which includes all of the GUI variables—in this case, Date[“DayPick”].
We use the FormatTime() function to save the selected date to TimeString in the Month Day, Year format (e.g. January 22, 2018).
The Send function inserts the date string into the current document or editing window.
You’ll notice numerous similarities between the V1.1 and V2.0 syntax. When converting to V2.0, these important differences can force you into tedious editing. To help with the process, I wrote a couple of Regular Expressions (RegEx) which when used in conjunction with Ryan’s RegEx Tester, I could quickly rewrite each line. Not a perfect solution, but much easier than doing it all by hand. I’ll save those for next time.