Search notes:

autohotkey

By default, a script adds an icon in the tray and has a main window (See A_ScriptHwnd).
The title of the main window is used to determine if a script is already running in conjunction with #SingleInstance
Variable names and function names are not case senstitive.
Comments are introduces with a ; (semicolon).
Implicit string concatanation (aka auto-concat):
"some text" a_var
There is a #include.

Variables

Three types (compare Type function)
A variable itself is not typed.
Built-in variables:
A value is assigned with :=
Environment variables can be queried with EnvGet(…).
ListVars

Functions

Some functions are

Defining functions

DoWhatIWant(par_1, byRef par_2, par_3 := "")
{
  …
  return 42
}

Statements

Some statements are:

Operators

Some operators are:

Objects

Some objects are

Hotkeys

A hotkey can be used to trigger actions.
Key modifiers:
Prepending the hotkey with a dollar sign ($) seems to prevent the hotkey from being (possibly recursively) invoked if a hotkey sends the hotkey.
Prepending the hotkey with a tilde (~) seems to not intercept the bound hotkey but rather to let it go to the underlying application.

Labels

A label identifies a line of code. There are three types of labels:

Misc

c:\> autohotkey.exe /Debug
c:\> autohotkey.exe /Debug=server:port

Identifying windows

Functions that need to identify windows to operate on (usually?) have a winTitle parameter. The value of this parameter can be

TODO

Message Box

msgBox  no paranthesis no quotes   ; msgBox, but no text
msgBox "no paranthesis    quotes"
msgBox(    paranthesis no quotes ) ; msgBox, but no text
msgBox("   paranthesis    quotes")

var       := "some text"
nameOfVar := "var"

msgBox( var       ) ; some text
msgBox(%nameOfVar%) ; some text
Github repository temp-AutoHotKey, path: /msgBox.ahk2

One liner

One of the arguably simplest Autohotkey scripts: As soon as hi, followed by a space, is typed, the hi is replaced with Hello World:
::hi::Hello World
Github repository temp-AutoHotKey, path: /one-liner.ahk2

Command line parameters

msgBox("count of parameters: " a_args.length())

for paramNo, paramValue in a_args {

    msgBox("Parameter " paramNo " is " paramValue)

}

Getting text with input()

;
;             L5     : max length
;                T3  : timeout
;
txt := input("L5 T3", "{enter}")


;
; possible Values for errorLevel:
;    Max
;    Timeout
;    EndKey:Enter
;
msgBox("txt = " txt ", errorLevel = " errorLevel)
Github repository temp-AutoHotKey, path: /input.ahk2

Stopping a script

A running autohotkey script can be stopped with exitApp().
loop (10) {

  if a_index = 4 {

    msgBox('a_index reached 4, stopping script')
    exitApp()

  }
  msgBox('a_index = ' . a_index . ' - not yet stopping this script')

}
Github repository temp-AutoHotKey, path: /exitApp.ahk2

Sleep

msgBox("Going to sleep for 2 seconds")
sleep(2000)
msgBox("I Woke up")
Github repository temp-AutoHotKey, path: /sleep.ahk2

Dynamically create a hotkey

Hotkeys are either created by a (double colon) hotkey label (such as i::…) or the hotkey(…) function.
The function hotkey allows to dynamically create a hotkey.
hotkey_trigger  := '^a'
hotkey_function := 'ctrl_a'

hotkey(hotkey_trigger, hotkey_function)  ; ctrl-a opens message box

hotkey '!q', 'exitApp' ; Alt-q quits application

ctrl_a() {
  msgBox('ctrl_a was pressed')
}
Github repository temp-AutoHotKey, path: /hotkey.ahk2

Classes and objects (instances)

Autohotkey allows to declare classes.
The name of a class's constructur is __new.
Member functions are declared like ordinary functions.
class cls {

;
;    The constructur
;
   __new(foo, bar, baz) {
         this.foo := foo
         this.bar := bar
         this.baz := baz
   }

;
;    A member procedure / function:
;
   msg() {

      msgBox('foo = ' . this.foo . 
           '`nbar = ' . this.bar . 
           '`nbaz = ' . this.baz)

   }
}

obj_1 := new cls(   1,     2,       3 )
obj_2 := new cls('one', 'two', 'three')

obj_1.msg()
obj_2.msg()
Github repository temp-AutoHotKey, path: /class-new.ahk2

__get / __set

A class can be implemented with dynamic setters and getters: the name of the attribute to be set or get is passed as a string to __get(attr) or __set(attr, val):
class C {

  __get(attr) {
     msgBox('Someone attempted to get the value of ' . attr)
     return 42
  }

  __set(attr, val) {
     msgBox('Someone attempted to set the value of ' . attr . ' to ' . val)
  }

}

obj := new C()

obj.foo := obj.bar
Github repository temp-AutoHotKey, path: /class-__get-__set.ahk2

__call

Similarly to __get and __set, __call receives the name (and parameters) of a method whose name is not explicitly implemented.
class C {

   __call(method_name, params*) {
   ;

     param_str := ''
     for ix in params {

       param_str := param_str . ' - param_' . ix . '=' . params[ix] 

     }

     msgBox('Someone tried to call ' . method_name . param_str)
   ;
   ; The return statement seems to be kind of important: 
   ;
     return
   }

}

obj := new C

obj.a_func()

obj.another_func('foo', 'bar', 'baz')
Github repository temp-AutoHotKey, path: /class-__call.ahk2

a_tickCount

a_tickCount is a counter of milli seconds with limited precision (Approx. 10 ms?). Better precision can be achieved with DllCall("QueryPerformanceCounter", "Int64*", ms).
tcBegin := a_tickCount
sleep 1000
tcEnd   := a_tickCount

msgBox('Sleep took approximately ' . (tcEnd - tcBegin) . ' ms')
Github repository temp-AutoHotKey, path: /a_tickCount.ahk2

a_coordMode variables

msgBox (  'a_coordModeToolTip = ' . a_coordModeToolTip .
        '`na_coordModePixel = '   . a_coordModePixel   .
        '`na_coordModeMouse = '   . a_coordModeMouse   .
        '`na_coordModeCaret = '   . a_coordModeCaret   .
        '`na_coordModeMenu = '    . a_coordModeMenu
      )
Github repository temp-AutoHotKey, path: /a_coordMode.ahk2

Variables that point to directories

Some a_ variables point to known directories
g := guiCreate()

g.onEvent('close', (*) => exitApp())

lst := g.add('listView',
   'r13 '  . ;  13 rows
   'w600 ' . ; 600 pixels wide
;  'vEdt ' . ; Name of edit is Edt
   'readonly',
   'Variable|Value'
)

g.show()

lst.add('', 'a_winDir'          , a_winDir         )
lst.add('', 'a_programFiles'    , a_programFiles   )
lst.add('', 'a_appData'         , a_appData        )
lst.add('', 'a_appDataCommon'   , a_appDataCommon  )
lst.add('', 'a_desktop'         , a_desktop        )
lst.add('', 'a_desktopCommon'   , a_desktopCommon  )
lst.add('', 'a_startMenu'       , a_startMenu      )
lst.add('', 'a_startMenuCommon' , a_startMenuCommon)
lst.add('', 'a_startUp'         , a_startUp        )
lst.add('', 'a_startUpCommon'   , a_startUpCommon  )
lst.add('', 'a_programs'        , a_programs       )
lst.add('', 'a_programsCommon'  , a_programsCommon )
lst.add('', 'a_myDocuments'     , a_myDocuments    )

;
; Autofit column header:
;
lst.modifyCol
Github repository temp-AutoHotKey, path: /a_directories.ahk2

a_comSpec

The a_comSpec variable contains the path to cmd.exe.
msgBox(a_comSpec)
Github repository temp-AutoHotKey, path: /a_comSpec.ahk2
Compare with the environment variable %ComSpec%.

Run exe or switch to application

:*:gtexcel::
; msgBox "hot string"
; IfWinExist     ahk_exe excel.exe
if (pid_excel := processExist("excel.exe"))
{
  msgBox "excel found, pid_excel = " pid_excel
	winActivate("ahk_pid " pid_excel)

}
else {
  msgBox "excel not found found, starting"
;	run, "C:\Users\xxx\AppData\Local\Google\Chrome\Application\chrome.exe"
  run  "C:\Program Files (x86)\Microsoft Office\Office15\excel.exe"
; msgBox "excel not found found, started"
  WinWait    ("ahk_exe excel.exe")
; WinActivate    ahk_exe excel.exe
  WinActivate("ahk_exe excel.exe")
; WinWaitActive  ahk_exe excel.exe

}


return

Read a file line by line

The following script iterates over each line of a given file:
loop read 'read-file-line-by-line.ahk2' {
  msgBox(a_loopReadLine)
}

noTrayIcon

With the #noTrayIcon directive, no tray icon is shown. The (in-)visibility of the tray icon is stored in the variable a_iconHidden.
;
;  Don't show the tray icon:
;
#noTrayIcon

msgBox("do you see a tray icon, the value of a_iconHidden is: " a_iconHidden)
Github repository temp-AutoHotKey, path: /noTrayIcon.ahk2

singleInstance

#singleInstance force

coordMode

coordMode can be used (among others) to specifiy if the mouse coordinates (mouseGetPos) are reported relative to the active window or the screen.
coordMode('mouse', 'relative')

mouseGetPos mouseX, mouseY
msgBox('mouse position relative to active window:`nX: ' . mouseX . ', Y: ' . mouseY)

coordMode('mouse', 'screen')

mouseGetPos mouseX, mouseY
msgBox('mouse position relative to screen:`nX: ' . mouseX . ', Y: ' . mouseY)
Github repository temp-AutoHotKey, path: /coordMode.ahk2

Variables

num:=42
txt:="The answer is %num%"

msgBox txt         ; The message box shows «txt»
msgBox %txt%       ; The message box shows the content of the variable txt: «The answer is 42»
msgBox(txt)        ; The message box shows the content of the variable txt: «The answer is 42»

varValue := txt    ; Assign value of variable txt to another variable
varName  :="txt"   ; Assign literal string to a variable

msgBox(varValue )  ; The message Box shows the value of varValue: «The answer is 42»
msgBox(varName  )  ; The message box shows the value of varName : «txt»
msgBox(%varName%)  ; The message box shows the value of the variable txt: «The answer is 42»

;msgBox(%txt%) ; Using percents within the paranthesis of msgBox causes an error
Github repository temp-AutoHotKey, path: /variables.ahk2

null value

Autohotkey defines the special null value.
Apparently, a variable that hasn't been assigned a value is null and indistingishable from a variable that was explicitly assigned null.
check_if_null(var) {

  if var = null
     msgBox('var = null')
  else
     msgBox(var . ' != null')
}

var_1 := 42
var_2 := null

check_if_null(var_1) ; 42 != null
check_if_null(var_2) ; var = null
check_if_null(var_3) ; var = null
Github repository temp-AutoHotKey, path: /null.ahk2
The type of null is String.

Types

type(…) reveals the type of an expression.
i :=  42
f :=  99.9
s := 'hello world'

msgBox (
  'type(i)    = ' . type(i) . '`n' .   ; Integer
  'type(f)    = ' . type(f) . '`n' .   ; Float
  'type(s)    = ' . type(s) . '`n' .   ; String
  'type(null) = ' . type(null)         ; String
)
Github repository temp-AutoHotKey, path: /type.ahk2

Arrays

Arrays can be created with […, … ].
The type of an array is Object.
The number of elements in an array is reported by .length() or .count().
Arrays can be nested.
someArray   := [42, 'text', 99]
nestedArray := ['xyz', someArray]

msgBox(type(someArray)) ; Object

msgBox('count of items in someArray: '   . someArray.count())    ; 3
msgBox('count of items in nestedArray: ' . nestedArray.length()) ; 2

iterateOverObject(nestedArray)

iterateOverObject(obj) {

  for ix, val in obj {
     if (type(val) == 'Object') {
        iterateOverObject(val)
     }
     else {
       msgBox (ix . ': ' . val)
     }
  }
}
Github repository temp-AutoHotKey, path: /array.ahk2

Associative Arrays (Dictionaris, Hashes)

someDictionary := {
  'the-number':  42          ,
  'greeting'  : 'Hello world',
  'fruit'     : 'apple'      ,
}

msg(item) {
  global someDictionary
  msgBox(someDictionary[item])
}

msg('greeting')
Github repository temp-AutoHotKey, path: /dictionary.ahk2

Checking if a key exists

An associative array defines the method hasKey(k) that determines if the key k exists.
dict := {
  'foo': 1   ,
  'bar': null,
}

if dict.hasKey('foo')
   msgBox('foo exists')
else
   msgBox('foo does not exists')

if dict.hasKey('bar')
   msgBox('bar exists')
else
   msgBox('bar does not exists')

if dict.hasKey('baz')
   msgBox('baz exists')
else
   msgBox('baz does not exists')
Github repository temp-AutoHotKey, path: /hasKey.ahk2

Variable concatenation

var_1 := "hello"
var_2 := "world"

msgBox(var_1   " "   var_2) ; implicit concatenation
msgBox(var_1 . " " . var_2) ; explicit concatenation

Determine version

msgBox(a_ahkVersion)
Github repository temp-AutoHotKey, path: /version.ahk2

Warn

The #warn directive warns about uninitialized variables.
#warn

initializedVariable := "some text"

msgBox(initializedVariable  )
msgBox(uninitializedVariable) ; Warning: This variable has not been assigned a value
Github repository temp-AutoHotKey, path: /warn.ahk2

envGet

envGet returns the value of a environment variable.
msgBox(envGet("USERPROFILE")) ; Show the user's home directory
Github repository temp-AutoHotKey, path: /envGet.ahk2

setKeyDelay

As per the documentation, setKeyDelay sets the delay that will occur after each keystroke sent by send and controlSend.
However, I was unable to figure out exactly what it is supposed to delay.
setKeyDelay  100, 100
send         some text
Github repository temp-AutoHotKey, path: /setKeyDelay.ahk2

keyWait

;
; D: wait for pressing Down
; T: Specify wait time in seconds
;
res := keyWait("k", "D T2.5")

if (res == 0) {
  msgBox("You didn't press k for two and a halve seconds")
  return
}
msgBox("You pressed k within two and a halve seconds")
Github repository temp-AutoHotKey, path: /keyWait.ahk2

hot keys

;
;  Detect the simultaneous pressing of two keys (f and j)
;

f & j::

;
; Note: pressing f (even if not followed by j) won't
; put it into the message queue of the current process, it
; is consumed (or swallowed)
;

  msgBox('f and j simultaneously')

return
Github repository temp-AutoHotKey, path: /hotkeys-f_and_j_1.ahk2
;
;  The following hot key detects if an f is pressed, released and
;  followed by a j that is pressed.
;
;  As soon as the f is pressed, it will be sent to the receiving
;  application. If AHK detects the following j, the f is erased.
;  
;

:*:fj::

  msgBox('f followed by j')

return
Github repository temp-AutoHotKey, path: /hotkeys-f_and_j_2.ahk2
This does not work how it was intended:
;
; Use $ so that the »send('f')« does not
; retrigger the hot key
;
$f::

  res := keyWait('j', 'D T0.5')
  msgBox('waiting ended, res = ' . res)

  if (res == 0) { ; f was not followed by j
    send 'f'
    return
  }

; msgBox('f followed by j')

return
Github repository temp-AutoHotKey, path: /hotkeys-f_and_j_3.ahk2

tilde

A hot key can be prepended with a tilde in which case the triggering hot key is passed to the receiving application.
Without tilde, the hotkey is «swallowed» by AutoHotKey.
 g::msgBox('g was pressed')
~f::msgBox('f was pressed')
 q::exitApp()
Github repository temp-AutoHotKey, path: /tilde.ahk2

dollar sign

A hot key can be prepended with a dollar sign in which case the hot key is not invoked if the body of the hotkey causes the triggering hot key to be sent again.
$a::

  msgBox('a was pressed - sleep a second, then send key a')
  sleep 1000
  send('a')

return
q::exitApp()
Github repository temp-AutoHotKey, path: /dollar.ahk2

Run application and wait for it to become active

;
;  Run notepad and store its process
;  identifier in notepadPid.
;
run('notepad.exe',,,notepadPid)

;
;  Wait until Window with given pid
;  becomes active
;
winWait('ahk_pid ' . notepadPid)

;
;  Write something into the new window.
;
sendInput ('hello world')
Github repository temp-AutoHotKey, path: /run-winWait.ahk2

fileAppend

fileAppend appends some text to an existing file or creates a file with the given line.
fileAppend a line`n,       fileAppend.txt
fileAppend another line`n, fileAppend.txt
Github repository temp-AutoHotKey, path: /fileAppend.ahk2

order of definition

A function can be called even if it is defined later.
f()


f() {
  msgBox('f was called')
}
Github repository temp-AutoHotKey, path: /orderOfDefinition.ahk2

if

num_1 := 10
num_2 := 32

if num_1 + num_2 = 42
   msgBox("num_1 + num_2 = 42")
else
   msgBox("num_1 + num_2 ≠ 42")


if 1 = 3 {
   msgBox("1 = 3 statement 1")
   msgBox("1 = 3 statement 2")
}
else if 1 = 2 {
   msgBox("1 = 2 statement 1")
   msgBox("1 = 2 statement 2")
}
else {
   msgBox("else statement 1")
   msgBox("else statement 2")
}
Github repository temp-AutoHotKey, path: /if.ahk2

Gui

guiCreate allows to create an «ordinary» window.
g := guiCreate()

g.options(
   '+caption '    . 
   '+border '     .
   '+toolWindow ' . ; +toolWindow avoids a taskbar button and an alt-tab menu item
   '+alwaysOnTop'
)

g.backColor := 'ffcc88'

g.marginX   :=  30
g.marginY   :=  18


g.addText(''    , 'HWND of g is ' . g.hwnd) ; First parameter is options.
g.addText(''    , 'Enter some text: ')      
g.addEdit('vTxt'                     )      ; Note the v that apparently indicates the name to later retrieve the value entered.

b := g.addButton('default', 'Go')
b.onEvent('click', (*) => clicked(g))

g.show(
   'x30 ' .
   'y10 '
)

; winSetTransColor ('ffcc88', 'gui.ahk2')
; winSetTransparent(    200 , 'gui.ahk2')

clicked(this) {
;
; submit()
;    save the contents of the
;    controls into an associative array.
;
  ctrls := this.submit()

  msgBox('txt = ' . ctrls.txt)
  this.destroy()

}
Github repository temp-AutoHotKey, path: /gui.ahk2

Edit control

An edit control might be used for debugging purposes. The following example writes the mouse position every second:
g := guiCreate()

g.onEvent('close', (*) => exitApp())

edt := g.add('edit',
   'r25 '  . ;  25 rows
   'w300 ' . ; 300 pixels wide
   'vEdt ' . ; Name of edit is Edt
   'readonly'
)

; msgBox ('Type(edt) = ' . type(edt)) ; GuiEdit

setTimer 'writeMousePositionIntoEdit', 1000

writeMousePositionIntoEdit() {

  coordMode('mouse', 'screen')
  mouseGetPos mouseX, mouseY

  global edt
  edt.text := edt.text  .  mouseX . ' / ' . mouseY . "`r`n"
}

g.show()
Github repository temp-AutoHotKey, path: /gui-addEdit.ahk2

Positioning controls with the section option

When creation a control, the option of a control can include section. This allows subsequently created controls to be added on the same y coordinate by including ys in their option.
g := guiCreate()

g.onEvent('close', (*) => exitApp())

      ;         type ,  options     ,  caption
      ;         ---- ,  ----------- ,  -------
txt_1 := g.add('text', 'w50'        , 'txt 1'  )
txt_2 := g.add('text', 'w50'        , 'txt 2'  ) ; control added below previous one
txt_3 := g.add('text', 'w50 section', 'txt 3'  ) ; control added below previous one - new section started
txt_6 := g.add('text', 'w50'        , 'txt 6'  ) ; contral added below previous one
txt_4 := g.add('text', 'w50 ys'     , 'txt 4'  ) ; Using ys to place control with same y as previous section, as left as possible
txt_5 := g.add('text', 'w50 ys'     , 'txt 5'  ) ; Using ys to place control with same y as previous section, as left as possible

g.show()
g := guiCreate()

g.onEvent('close', (*) => exitApp())

      ;         type ,  options     ,  caption
      ;         ---- ,  ----------- ,  -------
txt_1 := g.add('text', 'w50'        , 'txt 1'  )
txt_2 := g.add('text', 'w50'        , 'txt 2'  ) ; control added below previous one
txt_3 := g.add('text', 'w50 section', 'txt 3'  ) ; control added below previous one - new section started
txt_6 := g.add('text', 'w50'        , 'txt 6'  ) ; contral added below previous one
txt_4 := g.add('text', 'w50 ys'     , 'txt 4'  ) ; Using ys to place control with same y as previous section, as left as possible
txt_5 := g.add('text', 'w50 ys'     , 'txt 5'  ) ; Using ys to place control with same y as previous section, as left as possible

g.show()

Optional parameters

fnc(p_one, p_two := 42, p_three := 'hello world') {
  msgBox('p_one =   ' . p_one   . '`n' .
         'p_two =   ' . p_two   . '`n' .
         'p_three = ' . p_three . '`n')
}

fnc('use all defaults')

;
; In the following call, the second parameter (p_two)
; will have the value 42.
;
fnc('override 3rd param', , 'overridden')

;
; In the following call, the p_three does not
; name a parameter. In fact, within the
; function p_two will have the value 'x'
; and p_three the value 'hello world'
;
fnc('override 3rd param', p_three := 'x')

Function references

saySomething(txt) {
  msgBox(txt)
}

funcRef := func('saySomething')

%funcRef%('Calling func ref with %')

funcRef.call('calling func ref with call()')

boundFunc := funcRef.bind('bound parameter')
%boundFunc%()
Github repository temp-AutoHotKey, path: /functionReference.ahk2

Closures

globalVar := 'one'


createClosure(txt) {

  f() {
    msgBox('txt = ' . txt)
  }
  return func('f')

}

closure_one := createClosure('one')
closure_two := createClosure('two')

closure_one.call()
closure_two.call()
Github repository temp-AutoHotKey, path: /closures.ahk2

sysGet

;
;  sysGet() seems to call the Windows API function GetSystemMetrics().
;

SM_CMONITORS := 80 ; The number of display monitors on a desktop. Counts visible displays only (Compare with EnumDisplayMonitors)
SM_CXHTHUMB  := 10 ; Pixel-Width of the thumb box in a horizontal scrool bar.

nofMonitors  := sysGet(SM_CMONITORS)
thumbWidth   := sysGet(SM_CXHTHUMB )

msgBox('nofMonitors: ' . nofMonitors . '`n' .
       'thumbWidth:  ' . thumbWidth)
Github repository temp-AutoHotKey, path: /sysGet.ahk2

regexReplace

Autohotkey also supports regular expressions.
txt := 'The num is 42.'

;
;  Find consecutive digits (\d+) and
;  replace them with fixed string NUMBER.
;
res := regexReplace(txt, '\d+', 'NUMBER')
msgBox(res) ; The num is NUMBER

;
;  Find anything, but non-greedy (.*?), then
;  find consecutive digits and capture them
;  in parantheses, then match rest. Replace
;  with captured digits ($1):
;
num := regexReplace(txt, '.*?(\d+).*', '$1')
msgBox('num = ' . num)
Github repository temp-AutoHotKey, path: /regexReplace.ahk2

Say something

The following example uses comObjCreate to create an COM instance of the Microsoft Speech Object Library and then to say Hello World:
sapi := comObjCreate('sapi.spVoice')
sapi.speak('Hello world')
Github repository temp-AutoHotKey, path: /say-hello-world.ahk2

winGetList

The following snippet gets all top level(?) Windows and writes their HWND and title into a list view:
g := guiCreate()

g.onEvent('close', (*) => exitApp())

lst := g.add('listView',
   'r50 '  . ;  50 rows
   'w600 ' . ; 600 pixels wide
   'vEdt ' . ; Name of edit is Edt
   'readonly',
   'Index|HWND|Title'
)

g.show()

allWindows := winGetList()

lst.modifyCol(1, 'integer')
lst.modifyCol(2, 'integer')

for i, hwnd in allWindows {
; edt.text := edt.text  . i . ': ' . hwnd . winGetTitle('ahk_id ' . hwnd) . "`r`n"
  lst.add(, i, hwnd, winGetTitle('ahk_id ' . hwnd))
}

;
; Autofit column header:
;
lst.modifyCol
Github repository temp-AutoHotKey, path: /winGetList-all.ahk2
winGetList can also be used to find windows by their title:
;
;  WinGetList() by default searches case sensitively. 
;
;  By setting the match mode to regEx and using i), the
;  behaviour can be changed to searching case insenstive.
;

setTitleMatchMode('regEx')
l := winGetList('i)prompt')

for i, hwnd in l {
  msgBox(
   'hwnd   = ' . hwnd                                .
  '`ntitle = ' . winGetTitle      ('ahk_id ' . hwnd) .
  '`nclass = ' . winGetClass      ('ahk_id ' . hwnd) .
  '`nProc  = ' . winGetProcessName('ahk_id ' . hwnd)
 )
}
Github repository temp-AutoHotKey, path: /winGetList-title.ahk2

winGetControls

run('notepad.exe',,,notepadPid)   ; Start notepad
winWait('ahk_pid ' . notepadPid)  ; Wait until active
sendInput ('hello world')         ; Type something

sendInput ('!{f4}')

; sleep(1000)

winTitleSaveConfirmation := 'ahk_pid ' . notepadPid . ' ahk_class #32770'

winWait(winTitleSaveConfirmation)

h := winGetID(winTitleSaveConfirmation)
; msgBox('hwnd = ' . h)

  ctrls      := winGetControls(winTitleSaveConfirmation)
; ctrls      := winGetControls('ahk_id ' . h)
  ctrls_hwnd := winGetControlsHwnd(winTitleSaveConfirmation)

; msgBox('type: ' . type(ctrls))
; msgBox(ctrls)
; msgBox('cnts: ' . ctrls.length() . ' / ' . ctrls_hwnd.length())

for i, ctrl in (ctrls) {
    msgBox (i . ': ' . ctrl . ': ' . ctrls_hwnd[i] . ' | ' . winGetTitle('ahk_id ' . ctrls_hwnd[i]))
;   msgBox (i . ': ' . ctrl . ': ' . ctrls_hwnd[i])
}
Github repository temp-AutoHotKey, path: /winGetControls.ahk2

Screen dimensions

The width and height of the screen are stored in a_width and a_height.
If using multiple monitors, only the dimensions of a single monitor (the primary one?) are reported.
msgBox('Screen dimension: ' . a_screenWidth . ' x ' . a_screenHeight)
Github repository temp-AutoHotKey, path: /screen-dimensions.ahk2

Escape characters and Carriage return / line feed

The default escape character in autohotkey is the back-tick. If followed by an n, it produces a new line (ASCII 10), if followed by an r, it produces a carriage return (ASCII 13).
Thus, it is possible to insert line breaks into strings.
msgBox('line one`nline two`nAsc(``n) = ' . ord('`n') . '`nord(``r) = ' . ord('`r'))
Github repository temp-AutoHotKey, path: /new-line.ahk2

Calling a function in a dll

dllCall allows to call a function in a DLL.
The first argument specifies the DLL and the function, separated by a backslash. In case of a WinAPI function (more specifically: if the function is in one of the four DLLs user32.dll, kernel32.dll, comctl32.dll or gdi32.dll), the name of the DLL may be omitted.
The following parameters come in pairs of which the first argument specifies the data type and the second argument the valuer to be passed to the DLL.
Note: the data type Str is equivalent to WStr and specifies a wide character string. An ASCII string is specifed by AStr. (See also WinAPI: A and W functions)
MB_YESNO := 4
IDYES    := 6
IDNO     := 7

yes_or_no := dllCall('MessageBoxW',
                      'Int', "0"         ,
                      'Str', 'Yes or no?',
                      'Str', 'Confess!'  ,
                      'Int', MB_YESNO)

if      yes_or_no = IDYES
        msgBox 'You confessed'

else if yes_or_no = IDNO
        msgBox 'You did not confess'

else
        msgBox 'Unexpected answer'
Github repository temp-AutoHotKey, path: /dllCall.ahk2

Fat arrow / lambda expressions

The => operater is apparently known by the expression fat arrow and seems to make lambda expressions possible.
Lambda functions are useful to define callback-functions where they're used.
Apparently, only one statement is possible in a lambda expression.
sumFuncResultOnArray(ary, f) {
   s := 0 

   for idx, itm in ary {
     s := s + f.call(itm)
   }

   return s
}

msgbox (sumFuncResultOnArray([3, 6, 7], (e) => 2*e )) ; 32   (= 2*3 + 2*6 + 2*7 = 6+12+14)
Github repository temp-AutoHotKey, path: /lambda-1.ahk2
;
;  Why does this compile?
;
;  Found @ https://www.autohotkey.com/boards/viewtopic.php?t=46150 
;

() => {
  lambda:
  dllCall('one')
 	dllCall('two')
}

() => [
	DllCall( 1 )
	DllCall( 2 )
	DllCall( 2 )
]
Github repository temp-AutoHotKey, path: /todo-lambda.ahk2

Anonymous event handlers

g := guiCreate()

txt := g.add('text', 'w200 r1')
txt.text := 'Hello!'

;
; This does not work (https://stackoverflow.com/questions/56849007)
;
; g.onEvent('close', (*) => function() {
;   msgBox('Going to exit application')
;   exitApp()
; })

;
;  Any of the following do (https://stackoverflow.com/a/60476070/180275)
;
g.onEvent('close', (*) => (
  msgBox('Going to exit application')
  exitApp()
))

; g.onEvent('close', (*) => (
;   msgBox('Going to exit application'),
;   exitApp()
; ))

; g.onEvent('close', (*) => (msgBox('Going to exit application') exitApp()))

; g.onEvent('close', (*) => (msgBox('Going to exit application'), exitApp()))

g.show()

See also

AutoHotKey sources

Index